Craigslist Scraper - Cars, Housing, Jobs & For Sale
Pricing
from $1.20 / 1,000 posting records
Craigslist Scraper - Cars, Housing, Jobs & For Sale
Scrape Craigslist postings in any of 700+ cities worldwide: price, title, posting text, attributes, photos, coordinates, neighbourhood and posted date. Search by city, section, keyword and price, or paste search and posting links. Incremental monitoring, resume, MCP export.
Pricing
from $1.20 / 1,000 posting records
Rating
0.0
(0)
Developer
Abot API
Maintained by CommunityActor stats
0
Bookmarked
1
Total users
0
Monthly active users
4 days ago
Last modified
Categories
Share
Scrape Craigslist (craigslist.org), the world's largest local classifieds network, across 700+ city sites in 79 countries. The actor returns postings with price, title, posting text, the section's own attribute list, photos, neighbourhood, coordinates and posted date. It also monitors postings across runs (NEW, UPDATED, REAPPEARED, EXPIRED), resumes interrupted pulls, and pipes results into your apps through MCP connectors.
Why This Scraper?
- A whole search in one go. A craigslist search returns its entire result set, so a 9,000-posting search comes back complete and you are never charged twice for the same posting.
- Coordinates, neighbourhood and posted time on every row, not just on the postings you open in full. You are not charged extra to find out where a posting is or when it went up.
- The section's real attributes. Cars come back with make and model, year, odometer, title status, fuel, transmission, drivetrain, paint and body type. Housing comes back with bedrooms, bathrooms, move-in date, laundry, parking and pet rules. Jobs come back with compensation and employment type.
- Every city, not just the US. Name a city as
sfbay, as, or by pasting any link from it. London, Toronto, Berlin, Sydney, Tokyo and 700 more resolve the same way.SF bay area - Works on every Apify plan, including the free one.
- Change monitoring: scheduled runs classify every posting as NEW, UPDATED, UNCHANGED, REAPPEARED or EXPIRED, with per-campaign state you can name or share.
- MCP connector export: send results to Notion and other connectors without changing the dataset output.
- Structured failures: a blocked or broken run fails loudly with a clear message instead of returning an empty dataset. A search the source rejects says so in different words from a connection problem, so you can tell a typo from an outage.
Data You Get
Sample shape: values are illustrative placeholders, not from a live posting.
| Field | Example value |
|---|---|
| kind | posting |
| recordId / postingId | 7900000000 |
| postingUuid | AbCdEfGhIjKlMnOpQrStUv |
| url | https://www.craigslist.org/view/d/example-city-bicycle/AbCdEfGhIjKlMnOpQrStUv |
| title | Example road bicycle, lightly used |
| price / priceString / currency | 625 / $625 / USD |
| categoryAbbr / categoryName / section | bik / bicycles - by owner / for sale |
| postedDate / updatedDate / createdDate | 2026-09-04T00:00:00+00:00 |
| cityHost / cityName / areaId | sfbay / SF bay area / 1 |
| subareaAbbr / subareaName | eby / east bay |
| neighborhood / locationDescription | example neighbourhood / example town |
| displayAddress | 100 Example Street |
| latitude / longitude | 37.7749 / -122.4194 |
| imageUrls / imageCount | ["https://images.craigslist.org/00d0d_example_1200x900.jpg"] / 4 |
| bedrooms / sqft | 3 / 1200 |
| odometer | 84000 |
| salary / company / jobTitle | Competitive hourly pay / Example Co / Example role |
| monthlyPaymentString | $312/mo |
| eventFirstDate / eventLastDate / openHouses | 2026-09-10 / 2026-09-12 / ["2026-09-07"] |
| detailLoaded | true |
| description | Bought new in 2012. Lightly used, excellent condition. |
| attributes | [{"key": "condition", "label": "condition", "value": "good", "type": "key_value"}] |
| attributesByKey | {"condition": "good", "bicycle_frame_material": "aluminum"} |
| hasContactInfo | true |
| repostOf / seeMyOther / notices | 7899999999 / 1 / [] |
| changeType / changedFields | NEW / [] |
| firstSeenAt / lastSeenAt | 2026-09-04T00:00:00+00:00 |
Result rows carry everything above the detailLoaded line and
detailLoaded: false. Postings read in full (a pasted posting link, or the
detail toggle) add the posting text, the attribute list, the display
address and the update time, and set detailLoaded: true. Section extras
appear on the sections that have them: bedrooms and square footage on
housing, odometer on vehicles, salary, company and job title on jobs, event
dates and open houses where the section has them.
Contact data. The actor reports hasContactInfo so you know whether a
poster left a way to be reached, and returns the posting text as written.
It does not open the source's reply relay, so it never collects a personal
email address or phone number from a contact route.
How to Use
City search (default)
- Set Cities to one or more craigslist cities:
sfbay,newyork,london, orSF bay area,new york,vancouver, BC. - Set Section to a section code or name, for example
sss(for sale),cta(cars+trucks),apa(apartments / housing for rent),jjj(jobs). The source requires a section, so leaving it alone usessss. - Optionally add a Keyword, a price range, Posted by, Only postings with photos, Only postings from today and a Sort by order.
- Set Max items. With several cities, each gets an equal share and the last one takes the remainder.
Craigslist links (URL mode)
Set Mode to Craigslist links and paste any mixture of:
- search links, per city:
https://sfbay.craigslist.org/search/cta?query=truck&min_price=5000 - search links, shared form:
https://www.craigslist.org/search/area/newyork?cat=apa&max_price=3000 - posting links:
https://www.craigslist.org/view/d/<slug>/<id> - classic posting links:
https://sfbay.craigslist.org/eby/bik/d/<slug>/0000000000.html
A search link re-runs that exact search, keeping the query written into the link. The city-search filter fields are not applied to a pasted link. A posting link is read in full.
Input Parameters
| Parameter | Type | Description |
|---|---|---|
mode | select | search (cities + section + filters) or url (paste craigslist links). Default search. |
cities | array | City search: one or more craigslist cities, as a site name (sfbay), a display name (SF bay area) or any link from that city. Default ["sfbay"]. |
category | string | City search: the section to read, by code or by name. Default sss (for sale). The source requires a section, so this is never empty. |
query | string | City search: keyword to match in the posting. Leave empty to browse the whole section. |
minPrice | integer | City search: lowest price to return, in the city's own currency. |
maxPrice | integer | City search: highest price to return, in the city's own currency. Setting either bound drops postings that carry no price. |
soldBy | select | City search: all, owner or dealer. Default all. |
hasImage | boolean | City search: keep only postings that carry at least one photo. Default false. |
postedToday | boolean | City search: keep only postings published today. Default false. |
sortBy | select | City search: rel, date, dateoldest, priceasc or pricedsc. Default rel. |
startUrls | array | URL mode: craigslist search links or posting links, in either the per-city or the shared form. |
urls | array | Alias for startUrls, accepted under the name other actors use for URL mode. |
maxItems | integer | THE run cap: how many records to return. Default 20; 0 means no limit. With several cities each gets an equal share and the last takes the remainder. |
fetchDetails | boolean | Off by default. Also read every posting in full (posting text, attribute list, display address, update time). Adds one Posting detail event per posting read. |
resumeFromRunId | string | Continue ONE interrupted run: paste its run ID or dataset ID and postings already collected there are skipped. For recurring monitoring use incrementalMode instead. |
incrementalMode | boolean | Off by default. Turn on for daily or recurring monitoring of the same search: the first run returns everything as NEW, later runs return only NEW, UPDATED and REAPPEARED, each carrying changeType, changedFields, firstSeenAt and lastSeenAt. |
stateKey | string | Optional, incremental mode only. Name a monitoring campaign to keep its state stable, or deliberately share it. Leave empty to derive the key from the search and filter settings. |
emitUnchanged | boolean | Off by default, incremental mode only. Also return postings unchanged since the last run, marked UNCHANGED (those rows are billed too). |
emitExpired | boolean | Off by default, incremental mode only. Also return tracked postings no longer found, marked EXPIRED. Produced only after a complete, uncapped, non-resumed scan. |
mcpConnectors | array | Optional MCP connectors to pipe a copy of each posting into. Authorize one under Apify, Settings, API & Integrations, then pick it here. Leave empty to skip. |
notionParentPageUrl | string | Notion only: URL or id of the page under which posting pages are created. Required to enable the Notion export; ignored by other connectors. |
maxNotifyListings | integer | Cap on postings written to each connector per run. Default 50. Does not affect the dataset. |
proxyConfiguration | object | Apify Proxy settings. Works on every Apify plan, including the free one. |
Cities
Cities are recognised three ways, all case and punctuation insensitive:
- site name, the label in the address:
sfbay,newyork,losangeles,chicago,seattle,london,toronto,vancouver,berlin,paris,sydney,tokyo,mexicocity,delhi - display name, as craigslist writes it:
SF bay area,new york,los angeles,vancouver, BC - any link from that city, which is the easiest way to be sure
707 cities across 79 countries are shipped. The United States has 413, Canada 55, the United Kingdom 27, India 16, Mexico 16, Germany 15, France 13, Australia 12, China 12, Italy 11, Spain 11 and so on. An unrecognised city is reported in the log and skipped; if none resolves, the run fails with the list rather than returning nothing.
Sections
Eight top sections cover the whole network:
| Code | Section |
|---|---|
| sss | for sale |
| hhh | housing |
| jjj | jobs |
| ggg | gigs |
| bbb | services |
| ccc | community |
| eee | events |
| rrr | resumes |
A section is always sent, because the source refuses a search that names
none. Leave Section alone and sss is used.
Narrower codes work too, for example cta cars+trucks, apa apartments /
housing for rent, roo rooms & shares, bia bikes, ela electronics,
fua furniture, sof software / QA / DBA, web web / info design, cpg
computer gigs. A code that ends in o is usually the owner-only variant
and one ending in d the dealer-only variant; prefer the wider code and
use Posted by to narrow, so the filter shows up in your input rather
than being hidden in a code. 228 section codes are shipped, and section
names such as cars+trucks or for sale resolve as well as codes.
Recurring monitoring
Turn on Incremental changes for scheduled runs and schedule the actor.
The first run returns every match as NEW. Later runs return only what
changed:
| changeType | Meaning |
|---|---|
| NEW | first time this posting was seen for this campaign |
| UPDATED | the posting changed; changedFields lists what |
| UNCHANGED | nothing changed (suppressed unless you turn on Emit unchanged) |
| REAPPEARED | a posting that had gone came back |
| EXPIRED | a tracked posting is gone (only after a complete scan, and only with Emit expired on) |
State is kept separately for each city, section, filter and link setup, so two different searches never share a baseline. Name a campaign with State key to keep its state stable, or to share it deliberately.
EXPIRED is only produced when a run scanned the whole tracked search: not
resumed, not stopped by Max items, no search or posting read left
unfinished, and at least one record actually seen. A partial run never
marks live postings gone.
Resume
Paste a previous run ID or dataset ID into Resume from a previous run to continue a large pull without returning postings already collected there.
Send results into your apps (MCP connectors)
Optionally pipe results into the apps you already use through Model Context Protocol (MCP) connectors. This is an extra delivery step after the scrape: the Apify dataset is never changed, delayed or reduced, and a connector failure never fails the run.
- Authorize a connector once under Apify, Settings, API & Integrations.
- List its id in
mcpConnectors. If the picker is empty, no connector is authorized yet. - For Notion, also set
notionParentPageUrlto the page under which posting pages are created. Other connectors get a best-effort record write or a digest message. - Use
maxNotifyListingsto cap how many postings are written to each connector per run.
The connection is mediated by Apify's MCP proxy, so this actor never sees
your third-party credentials. Leave mcpConnectors empty to skip.
What you are charged for
The Store page shows the current rates. Three things are counted:
- Actor Start, once per run.
- Posting record, one per posting returned in the dataset.
- Posting detail, one per posting read in full. Rows that were not read in full never carry it, and a posting read that fails still ships the base record without it.
Limits and honest caveats
- A craigslist search returns what the source itself matches. The largest single result set observed was about 9,000 postings; the source does not offer more of one search than that.
- Setting a price bound drops postings that carry no price at all, because the source filters them out server side. That is the source's behaviour, not a client-side choice.
- Sub-area narrowing (for example east bay inside SF bay area) is not offered: the source accepts the parameter and then ignores it, so an input for it would silently do nothing. Sub-area is still reported on every record, so you can filter it yourself.
- Photos are returned as addresses, not downloaded.
- The actor does not post, reply, flag or log in. It reads public pages only.