Craigslist Scraper
Scrape Craigslist listings by city, category and keyword: id, title, price, neighborhood, date, images and URL. No account or API key. $0.85 per 1,000.
How it works
- 1Open it on Apify
Hit Run on Apify — it opens the tool in the cloud, no install.
- 2Set the inputs
Adjust
city,query,category(sensible defaults are pre-filled). - 3Click Run
The tool runs on Apify’s cloud and collects the data for you.
- 4Export the results
Download as JSON, CSV or Excel, or pipe straight into your app, Google Sheets, or an AI agent.
Pricing
$0.00085 per listing = $0.85 per 1,000
| You are charged for | When | Price |
|---|---|---|
| Listing returned | Charged once per genuine listing row. Blocked, empty and sample runs are never charged. | $0.00085 |
Pay-per-event pricing: you are billed per result, not per subscription. Billing is handled by Apify on your own account. These are the live Apify store prices, in effect since 2026-08-07, and they are what you are actually charged.
Inputs
| Field | What it does | Type |
|---|---|---|
city | Craigslist city (the subdomain), e.g. "newyork", "sfbay", "losangeles", "london". Plain city names like "new york city" also work. Add several to search several cities in one run. 707 Craigslist sites in 79 countries are recognised. | array |
query | What to search for, e.g. "mountain bike". Leave empty to return everything in the category. | string |
category | Craigslist category abbreviation. Groups: sss = all for sale, hhh = housing, jjj = jobs, ggg = gigs, bbb = services, ccc = community, cta = cars & trucks, eee = events. Leaf categories work too: bia bicycles, apa apartments, fuo furniture, zip free stuff, ela electronics. | string |
searchUrls | Optional. Paste full Craigslist search URLs instead of filling in the fields above, e.g. https://newyork.craigslist.org/search/bia?query=trek. Filters already in the URL are kept. | array |
maxItems | How many listings to return in total across all searches (1-50000). Each returned listing is one charged result. | integer |
fetchDetails | Open each posting page to add the seller's body text, the attribute table (condition, make, bedrooms, ...), the street address when shown, and the last-updated time. Slower: roughly one extra request per listing. | boolean |
sort | Newest first is the only order that can return more than 360 listings - Craigslist caps relevance-ordered results at 360. Price sorting is not offered by Craigslist's API. | string |
minPrice | Optional lower price bound. | integer |
maxPrice | Optional upper price bound. | integer |
postalCode | Optional. Search around this postal code instead of the whole city. Use together with the radius below. | string |
radiusMiles | Optional. Only used when a postal code is set. | integer |
sellerType | Restrict to owner or dealer postings. Only meaningful in categories that have both. | string |
hasImage | Skip postings that have no images. | boolean |
titleOnly | Match the search terms against listing titles instead of the whole posting. | boolean |
postedToday | Restrict to postings from today. | boolean |
What you get
A structured dataset — each result includes fields like:
listingIdtitlepricelocationneighborhoodpostedAtcategoryNameimageCounturlExport every run as JSON, CSV or Excel, or send it to your app, a database, Google Sheets, or an AI agent.
1 ready-to-run use cases
Craigslist For Sale By Owner - One City
Search a Craigslist city for owner-posted listings, newest first. Get price, title, neighborhood, date and link.
Related tools in Real Estate & Classifieds
Other ready-to-run tools in the same category — all pay-per-use on the Apify cloud.
Airbnb Listings Scraper
Scrape Airbnb listings by location, dates and guests. Get listing ID, name, room type, price, rating, reviews and host. No account, no API key.
Avito Listings Scraper
Scrape Avito.ru listings by keyword, category or city. Get id, title, price, seller name and type, publish date and photos. $0.30 per 1,000 listings.
Facebook Marketplace Scraper
Scrape Facebook Marketplace listings by keyword and city. Rows carry title, price, currency, location, link, posted date, sold status.
Zillow Scraper
Scrape Zillow search results and full listing details: price, beds, baths, sqft, photos, price history, schools. No login or API key. $0.0008 per property.
Realtor.com Scraper
Realtor.com listings as JSON, by city, ZIP or county. Fields: address, price, beds, baths, sqft, year built, days on market, agent, broker. $0.68/1k.
Where this tool sits
- Categories
- Real Estate & Classifieds
- Platforms
- Craigslist
Craigslist Scraper: listings by city, category and keyword, no API key
Give it a city, a category and something to search for. You get rows with the listing id, title, price, posted time, neighbourhood, coordinates, image links and the listing URL. Switch on full posting text and each row also carries the seller's body text and the attribute table.
Craigslist has no nationwide index. Every city is its own site, so one search covers one city. You can list several cities in one run, and each one is searched separately.
| Input | A city, a category and a search term, or Craigslist search URLs |
| Output | One row per listing |
| Ceiling | 50,000 listings per run |
| Account needed | None, and no API key |
| Price | $0.85 per 1,000 listings, flat on every plan |
🔍 What Craigslist Scraper does
It runs the search Craigslist's own filter bar would run, and hands you the results as structured rows instead of a page you have to read. Price bounds, owner or dealer, photos only, titles only, posted today, and a postal code with a radius are all there.
City names are forgiving. newyork, new york city, sfbay and london all resolve, and 707 Craigslist sites across 79 countries are recognised. If you would rather not think about abbreviations at all, paste a Craigslist search URL into searchUrls and whatever filters are already in it are kept.
Rows are written at the end of the run rather than as they are found, so keep maxItems at a size the run can finish.
📥 What you give it
{
"city": ["sfbay"],
"query": "toyota tacoma",
"category": "cta",
"maxItems": 500,
"maxPrice": 25000
}
| Field | Default | What it is |
|---|---|---|
city | none | The Craigslist site, as a subdomain like newyork or a plain name like new york city. Add several to cover several cities. The box starts with newyork in it, which is a suggestion and not a default. |
query | none | What to search for. Leave it empty to take the whole category. The box starts with bike in it. |
category | sss | The category abbreviation. Groups: sss all for sale, hhh housing, jjj jobs, ggg gigs, bbb services, ccc community, cta cars and trucks, eee events. Leaf codes work too: bia bicycles, apa apartments, fuo furniture, zip free stuff, ela electronics. |
searchUrls | none | Paste Craigslist search URLs instead of filling in the fields above. |
maxItems | 100 | Total listings across every search in the run, up to 50,000. |
fetchDetails | false | Open each posting for the body text, the attribute table, the street address where one is shown and the last-updated time. Slower, roughly one extra request per listing. |
sort | newest | newest or relevant. Relevance stops at 360 results, which is Craigslist's cap. |
minPrice, maxPrice | none | Price bounds. |
postalCode, radiusMiles | none | Search around a postal code rather than the whole city. Set both. |
sellerType | any | owner or dealer, in the categories that have both. |
hasImage | false | Skip postings with no photos. |
titleOnly | false | Match your terms against titles only. |
postedToday | false | Only today's postings. |
proxyConfiguration | none | Optional. Leave it alone unless you need the run to go out through a particular network. |
📤 What you get back
A real row, with the image list cut short:
{
"listingId": "7959183765",
"title": "Dutch Gazelle Tour Populair C8, 61CM, In storage, like NEW IMPORT",
"price": 850,
"priceText": "$850",
"currency": "USD",
"url": "https://www.craigslist.org/view/d/long-island-city-dutch-gazelle-tour/fRrdPyQukG7jW8afcTduEd",
"postedAt": "2026-09-14T05:37:44.000Z",
"categoryId": 68,
"categoryAbbr": "bik",
"categoryName": "bicycles - by owner",
"location": "LIC",
"neighborhood": null,
"subarea": "que",
"city": "newyork",
"cityName": "new york city",
"region": "NY",
"country": "US",
"latitude": 40.7446,
"longitude": -73.9345,
"images": ["https://images.craigslist.org/00L0L_2mdiEek2CdR_0dI07I_600x450.jpg", "..."],
"imageCount": 9,
"searchUrl": "https://newyork.craigslist.org/search/sss?query=bike",
"scrapedAt": "2026-09-14T05:42:36.888Z"
}
| Field | What it is |
|---|---|
listingId | Stable. Use it as your dedupe key across runs. |
price | A number, and null when the posting has no price. Jobs, gigs and most community posts have none. priceText keeps Craigslist's own formatting. |
postedAt | A real timestamp, not a relative phrase. |
location | Craigslist's free-text place label, filled in on effectively every row. neighborhood is a separate assigned field and is usually null. |
latitude, longitude | Coordinates for the posting, which is what makes a map or a distance filter possible. |
images | Image URLs at 600x450. imageCount is how many of those were built for the row. |
searchUrl | Which of your searches produced this row, so a multi-city run is easy to split. |
With Fetch full posting text on, five more fields land on the same row: description (the seller's body text), attributes (the labelled table, so condition and odometer on a car, rent period on a rental, frame size on a bike), attributeTags (the unlabelled chips like 1BR / 1Ba), updatedAt and address. A posting that disappeared between the search and the detail fetch keeps its search fields and gains a detailError.
🧾 Reading the output
| Row | How to spot it | Charged |
|---|---|---|
| A listing | It has a listingId and no charged field | yes |
| The sample row | _sample: true and charged: false | no |
| A diagnostic | _diagnostic: true and an errorCode | no |
charged: false is the marker on the rows that are not listings. A real listing row does not carry the field at all, so filter on _sample and _diagnostic being absent.
errorCode | What it means |
|---|---|
BAD_INPUT | That city could not be resolved to a Craigslist site. Check the spelling, or use the subdomain. |
BAD_SEARCH | Craigslist turned the search down, nearly always a category abbreviation that does not exist for that site. |
NO_RESULTS | The search ran and matched nothing. Try a broader term, another category, or a bigger radius. |
SEARCH_REJECTED | Craigslist answered with something that could not be read. Re-run it. |
BLOCKED | The request did not get through. Try again in a few minutes. |
Every diagnostic carries a hint in plain words, and one failed search never stops the others.
▶️ How to run it
1. Open Craigslist Scraper and click Try for free. 2. Put your city into City and what you want into Search terms. 3. Set Category. sss covers everything for sale and is a fine starting point. 4. Set Maximum listings, then click Start. 5. Download the dataset as JSON, CSV or Excel, or read it from the Apify API.
💰 How much does it cost?
$0.85 per 1,000 listings. Flat on every Apify plan, no volume tiers.
You pay per listing row. Turning on full posting text does not add a second charge, it just adds fields to the same row. The sample row is not charged, diagnostic rows are not charged, and a listing id seen twice in one run only becomes one row.
💡 What people use it for
- Watching a city and category on a schedule and diffing on
listingId, so you see what went up
since yesterday without reloading a page.
- Pulling every car under a price in one metro, with
attributeson, so odometer and title status
arrive as columns rather than as paragraphs.
- Rental research:
hhhorapawith a postal code and a radius, then readingattributeTagsfor
bedroom counts and square footage.
- Finding dealer postings hiding in an owner category, or the reverse, using
sellerType. - Mapping what is for sale where, because every row carries coordinates.
🚧 What it does not do
- One city per search. There is no nationwide Craigslist index. List several cities and each is
searched on its own.
- Relevance sorting stops at 360 results. Craigslist's cap, not a setting here.
newesthas no
such limit, which is why it is the default.
- No sorting by price. Craigslist no longer offers it. Sort the dataset yourself.
- No seller contact details. No phone number, no email, no reply-to address. Craigslist keeps
those behind its own relay.
neighborhoodis usuallynull. Craigslist only assigns neighbourhoods in a few dense metros.
location is the field to rely on.
- Cross-posts are separate rows. The same couch posted to three subareas is three postings with
three ids, and Craigslist reports them separately.
- Rows land at the end of the run, so a run that hits its time limit writes nothing. Full posting
text roughly doubles the work, so pick maxItems with that in mind.
- Postings expire and get deleted.
scrapedAtrecords when the row was read.
🧭 Which listings scraper do you need?
| If you want | Use |
|---|---|
| Craigslist listings by city and category | This one |
| Classified listings across Russia and the CIS | Avito Listings Scraper |
| AliExpress search results with prices and order counts | AliExpress Products Scraper |
| Wholesale prices, minimum order quantities and suppliers | 1688 Wholesale Scraper |
| Buyer reviews with photos for a shop | Shopee Shop Reviews Scraper |
❓ Questions people ask
Do I need a Craigslist account? No. Nothing to log into and no key to apply for.
Can I search the whole country at once? No, and neither can Craigslist. Pass a list of cities instead.
Why did I only get 360 results? You used relevance sorting. Switch Sort to newest first.
Can I get the seller's phone or email? No. Craigslist hides them behind its own relay, so they are not on the page to read.
Is price missing a lot? In job, gig and community categories, yes, because those postings have no price. For-sale postings where the seller left it blank also come back null.
Can I schedule it? Yes. Keep listingId as your key and each run tells you what is new.
Is scraping Craigslist legal? These are public postings, and they can contain personal data, which GDPR and similar laws cover, so have a reason for collecting it. Check Craigslist's terms too. Apify's write-up on scraping and the law is a good starting point, and we are not lawyers.
🆘 If something breaks
Open the Issues tab on the actor page. Send the city, the category and the run ID. If you got a diagnostic row, its errorCode and hint usually name the problem on their own.