# Craigslist Scraper & API - Listings, Prices, Cars, Homes, Jobs (`rel8ble/craigslist-scraper`) Actor

Craigslist scraper and API for any Craigslist site (US, Canada, UK, worldwide): keywords, areas, categories, price, ZIP + radius or search URLs, past the 10,000 cap. One result = one listing: title, price, place, date, photos, URL; details included. $0.45 per 1,000, no start fee.

- **URL**: https://apify.com/rel8ble/craigslist-scraper.md
- **Developed by:** [Giovanni Rich](https://apify.com/rel8ble) (community)
- **Categories:** E-commerce, Lead generation, Real estate
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$0.45 / 1,000 results

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Craigslist Scraper & API - Listings, Prices, Cars, Homes, Jobs

This **Craigslist scraper** and unofficial **Craigslist API** searches any Craigslist site (US, Canada, UK, Europe, Asia, worldwide) by keyword, area, category, price, postal code + radius and the site's own filters, and exports the listings to JSON, CSV or Excel. Use it as a **Craigslist price tracker**, a **Craigslist search alert**, for **used car and for-sale prices**, **rental listings**, **local job ads**, resale and flipping research, and market data for AI agents.

- **What goes in:** search keywords, Craigslist areas (`sfbay`, `newyork`, `london`, or a whole country like `US`), categories (`sss` for sale, `cta` cars & trucks, `apa` apartments, `jjj` jobs ...), price range, ZIP / postal code + miles, "has image", "posted today", titles-only, owner / dealer, sort, or Craigslist search / posting URLs.
- **What comes out:** one row per listing: title, price, currency, place, neighborhood, approximate map position, posted date, category, all photos, URL, plus bedrooms / sqft (housing), odometer (cars), salary / job title / company (jobs). Optional: full description, all attributes (condition, make / model, year, VIN, title status, size, bathrooms, pets, laundry ...), updated date.
- **Typical cost:** $0.45 per 1,000 listings, details included, no start fee. A 20-listing check costs under 1 cent.
- **When to use it:** pricing a used item or car before you buy or sell, watching a search for new listings, comparing rents across neighborhoods, collecting local job ads, finding underpriced items to flip, feeding live Craigslist data to an AI agent.

It reads the same JSON the craigslist.org search page loads, over plain HTTP, with **no headless browser** and no login: one request returns up to 360 listings with titles, and a full search list of up to 10,000 postings comes in about 10 requests. Deep search goes past Craigslist's 10,000-per-search limit automatically: in our tests all of "furniture" in the SF bay area returned **22,027 of 22,027** listings in 29 seconds (31 requests), and everything for sale in the East Bay returned 82,877 of the 83,372 the site counted (99.4%) in 74 seconds (138 requests). Unofficial: not affiliated with or endorsed by craigslist.

### Sample output

Real rows from a cloud run for `bike` in the SF bay area (`sfbay`):

| title | priceText | location | category | postedAt |
|---|---|---|---|---|
| Giant Revolt Advanced 1 Gravel Bike | $1,400 | napa county | bik | 2026-10-20T00:25:39Z |
| Juiced Ripcurrent S XL 32+mph Fat Tire ebike | $1,600 | brentwood / oakley | bik | 2026-10-20T00:25:56Z |
| Shimano Dura-Ace FC-R9200 Crankset 165MM 52/36 | $525 | san jose north | bop | 2026-10-20T00:28:29Z |
| Harley 2006 Dyna Street Bob FXDB \*\*AS NEW 900 Original Miles!! | $12,400 | morgan hill | mcy | 2026-10-20T00:21:00Z |

### Use cases

- **Price research**: what a used car, bike, phone or couch really sells for in your area, from hundreds of live listings with `price`, `odometer`, `year` and `condition`.
- **New-listing alerts**: schedule `sort: "newest"` every hour and send only new `id`s to Slack, Telegram or e-mail.
- **Flipping and resale**: find underpriced items across many Craigslist sites (or a whole country) in one run.
- **Rental market data**: compare rents, bedrooms and sqft across neighborhoods with `apa` (apartments).
- **Local job ads**: collect `jjj` postings with job title, salary, employment type and company.
- **AI agents**: `{"searchQueries": ["iphone 13"], "areas": ["chicago"], "maxResults": 20}` returns live listings for under 1 cent.

### Pricing

**$0.45 per 1,000 listings** (pay per result). Posting details (description, all attributes, VIN, odometer, bedrooms, salary) are included at the same price, and there is **no start fee**. Failed or blocked requests, retries, duplicates and posting URLs that no longer exist are never charged.

| You scrape | You pay |
|---|---|
| 100 listings | $0.045 |
| 1,000 listings | $0.45 |
| 10,000 listings | $4.50 |
| 100,000 listings | $45.00 |

The Apify free plan's $5 monthly credit covers about 11,100 listings. The prefilled input (`bike` in `sfbay`, 20 listings) costs $0.009 and took 7 seconds in a cloud test. If you set a maximum cost per run, the scraper stops cleanly when it reaches it.

#### Why this one

- **A quarter of the leaders' price**: solidcode $1.80, memo23 $1.50 + $0.007 per run (details and emails extra), fatihtahta $1.49, automation-lab $2.30 + start, ivanvs $6.00 + start, and the $0.50 tier (newbs, unitbytes, ocrad) per 1,000. Here it is $0.45 with details included and no start fee.
- **Every Craigslist site**: US, Canada, UK, Europe, Asia, or a whole country (`US` = 413 sites) in one run.
- **Past the 10,000 cap**: deep search returned 22,027 of 22,027 "furniture" listings in the SF bay area in 29 seconds.
- **Your own filters work**: paste a craigslist.org search URL and make / model, odometer, bedrooms, condition and the rest are kept.
- **Fast and light**: the site's own JSON over plain HTTP, up to 360 listings per request, no browser or login.

### FAQ

**Does it need a Craigslist account or a browser?**
No. It reads the same public JSON the craigslist.org search page loads (`sapi.craigslist.org`, `rapi.craigslist.org`), over HTTPS, without logging in.

**How do I find the area name?**
It's the first part of the address of your local Craigslist: `https://seattle.craigslist.org` = `seattle`, `https://sfbay.craigslist.org` = `sfbay`. City names like "los angeles" or "SF bay area" work too. Every row has its `area` and `subarea`.

**How do I use the filters from the Craigslist website?**
Set the filters on craigslist.org, copy the URL from the address bar and paste it into `startUrls`. Keyword, area, sub-area, category, price, has-image, posted-today, owner / dealer, postal code + distance, sort and category-specific filters (make / model, model year, odometer, condition, bedrooms, pets, laundry ...) are all kept from the URL.

**How do I track new listings for a search?**
Schedule the actor with `sort: "newest"` and a `maxResults` that covers what appears between two runs (for example 50 every hour), and keep the `id`s you have already seen.

**What about personal data?**
Many posters are private people, so the actor collects no names, phone numbers, e-mail addresses, reply addresses or street addresses. E-mail addresses and phone numbers that posters type into titles and descriptions are replaced with `[email removed]` / `[phone removed]`. Map positions are rounded to about 1 km. For job ads, the hiring company name is kept (it is a business).

**Is it legal to scrape Craigslist?**
This actor collects publicly available listing information without logging in, at a polite pace, and stays away from the paths Craigslist's robots.txt disallows (reply, flag, suggest and similar). You're responsible for using the data in line with Craigslist's terms and applicable law. This isn't legal advice; if you're unsure, check with a lawyer.

**How does it avoid blocks?**
It sends normal browser-like requests at a polite pace (about two a second without a proxy), through Apify Proxy when enabled, and rotates sessions when a request is refused (up to 8 retries).

**What happens if I run it with no input?**
It does a demo search for "bike" in the SF bay area (20 listings) instead of failing.

### How to use

1. Type one or more **search keywords** (`bike`, `toyota tacoma`, `couch`) and one or more **areas** (`sfbay`, `losangeles`, `chicago`, `newyork/brk`, `london`). The area is the first part of the site address: sfbay.craigslist.org = `sfbay`.
2. Optionally add **categories** (`bia` bicycles, `cta` cars & trucks, `fua` furniture, `apa` apartments), a **price range**, or a **ZIP code** with a distance in miles.
3. Or paste **Craigslist URLs**: set the filters on craigslist.org, copy the address bar, paste it into `startUrls`. Category filters (make / model, odometer, bedrooms, condition ...) are kept. Posting URLs work too.
4. Click **Start**. Listings are saved as they come in; download them as JSON, CSV or Excel, or read them through the Apify API.
5. For a price tracker or new-listing alerts, schedule the actor (for example every hour with `sort: "newest"` and `maxResults: 50`) and deduplicate on `id`.

### Input

An empty input runs a 20-listing demo search for "bike" in the SF bay area. Keywords or categories need an area (Craigslist has no nationwide search), a country code, or a postal code.

| Field | Default | What it does |
|---|---|---|
| `searchQueries` | - | Keywords as typed into the Craigslist search box, one per line. |
| `areas` | - | Craigslist sites: `sfbay`, `newyork`, `losangeles`, `seattle`, `london`, `toronto` ...; sub-areas `newyork/brk` or `brooklyn`; `US`, `CA`, `GB` ... for every site in a country (707 sites in total). |
| `categories` | `sss` | Category codes or names: `sss` all for sale, `bia` bicycles, `cta` cars & trucks, `cto` cars by owner, `fua` furniture, `ela` electronics, `zip` free stuff, `hhh` housing, `apa` apartments, `roo` rooms, `jjj` jobs, `ggg` gigs, `bbb` services ... |
| `postalCode`, `distanceMiles` | - | Search around a ZIP / postal code instead of whole areas (`94110`, 5 miles). Rows get `distanceMiles`. |
| `priceMin`, `priceMax` | - | Price range in whole units of the local currency. |
| `hasImage` | false | Only listings with photos. |
| `postedToday` | false | Only listings posted today. |
| `searchTitlesOnly` | false | Keywords must be in the title. |
| `bundleDuplicates` | false | Collapse re-posted duplicates into one row (`duplicateCount`). |
| `sellerType` | `any` | `any`, `owner` or `dealer` (for-sale categories). |
| `sort` | `newest` | `newest`, `oldest`, `price_asc`, `price_desc`, `relevance`, `distance` (with `postalCode`). |
| `startUrls` | - | Craigslist search URLs (all filters kept) and posting URLs (looked up with full details). |
| `maxResults` | 100 | Listings per search (keyword x category x area). A country counts as one area. `0` = all of them. |
| `deepSearch` | true | Goes past the 10,000-per-search limit by splitting into sub-areas, categories and price bands. |
| `includeDetails` | false | Opens each posting for description, attributes, condition, make / model, year and updated date. Same price, slower. |
| `includeNearbyAreas` | false | Also keep the "more from nearby areas" postings Craigslist adds to small searches. |

Example: owner-sold bicycles with photos, $100-300, cheapest first, keyword in the title (this exact input returned 100 listings in 1.7 s in our test, all within the price range, all with photos; the site counted 920 matches):

```json
{
    "searchQueries": ["bike"],
    "areas": ["sfbay"],
    "categories": ["bia"],
    "priceMin": 100,
    "priceMax": 300,
    "hasImage": true,
    "searchTitlesOnly": true,
    "sellerType": "owner",
    "sort": "price_asc",
    "maxResults": 100
}
```

Around a ZIP code, nearest first:

```json
{
    "searchQueries": ["couch"],
    "postalCode": "10001",
    "distanceMiles": 3,
    "sort": "distance",
    "maxResults": 50
}
```

Several cities at once, or a whole country (maxResults then applies to the country as a whole):

```json
{
    "searchQueries": ["toyota tacoma"],
    "areas": ["losangeles", "sandiego", "phoenix"],
    "categories": ["cta"],
    "maxResults": 200
}
```

Straight from URLs copied from the browser:

```json
{
    "startUrls": [
        "https://sfbay.craigslist.org/search/sby/cta?auto_make_model=toyota&max_price=15000&sort=priceasc",
        "https://www.craigslist.org/search/area/newyork?cat=apa&min_bedrooms=2",
        "https://sfbay.craigslist.org/pen/bik/d/millbrae-open-wide-gravel-bike-in-xs/7945993826.html"
    ],
    "maxResults": 40
}
```

### Output

One dataset item per listing. This one is from a real run on 19 Oct 2026, search URL `https://sfbay.craigslist.org/search/cta?purveyor=owner` with `includeDetails: true` (photo list and attributes shortened):

```json
{
    "id": "7986506352",
    "url": "https://www.craigslist.org/view/d/santa-rosa-porsche-targa-pdk/sh1z1GdmZAgesdP41tDv7e",
    "postingUrl": "https://sfbay.craigslist.org/nby/cto/d/santa-rosa-porsche-targa-pdk/7986506352.html",
    "title": "Porsche 2015 911 4S Targa PDK…",
    "price": 129000,
    "priceText": "$129,000",
    "currency": "USD",
    "category": "cto",
    "categoryName": "cars & trucks - by owner",
    "area": "sfbay",
    "areaName": "SF bay area",
    "subarea": "nby",
    "subareaName": "north bay / marin",
    "location": "Santa Rosa",
    "country": "US",
    "latitude": 38.47,
    "longitude": -122.64,
    "postedAt": "2026-10-20T00:21:08.000Z",
    "imageUrl": "https://images.craigslist.org/00N0N_fuNRyWj0oMP_0CI0t2_600x450.jpg",
    "imageUrls": ["https://images.craigslist.org/00N0N_fuNRyWj0oMP_0CI0t2_1200x900.jpg", "..."],
    "imageCount": 6,
    "odometer": 13600,
    "searchArea": "sfbay",
    "position": 1,
    "scrapedAt": "2026-10-20T00:25:40.517Z",
    "description": "Only 13,480 miles\n\nThe car has Fuchs Rims on it now and -\n\nThe car comes with the -original set of wheels from Porsche stored in there boxes - additional value of $10,000 for the 4 rims.",
    "attributes": { "make/model": "911 4 S Targa  PDK", "year": "2015", "condition": "excellent", "cylinders": "6 cylinders", "fuel": "gas", "odometer": "13,600", "title status": "clean", "transmission": "automatic", "type": "convertible" },
    "condition": "excellent",
    "makeModel": "911 4 S Targa  PDK",
    "year": 2015,
    "titleStatus": "clean",
    "section": "for sale",
    "updatedAt": "2026-10-20T00:21:08.000Z"
}
```

An apartment and a job from the same run (shortened):

```json
{ "id": "7986506097", "title": "Beyond Four Walls: A Place to Truly Call Home!", "price": 3022, "bedrooms": 2, "sqft": 657, "location": "Emeryville", "subarea": "eby", "housingType": "apartment", "bathrooms": "2", "attributes": { "laundry": "w/d in unit", "parking": "carport", "cats are OK - purrr": true, "dogs are OK - wooof": true } }
{ "id": "7986500661", "title": "HIRING NOW: Office Admin  – (Walnut Creek)", "jobTitle": "Office Admin", "company": "apollo roofing  company", "salary": "TBD", "employmentType": "full-time", "categoryName": "admin/office" }
```

The dataset has two ready-made views, **Overview** (with photo thumbnails) and **Details**. A `RUN_SUMMARY` record in the key-value store lists, for each search, how many listings were saved, the total the site shows, how many narrower searches deep search ran, why it stopped, and any warnings (for example an area that was not found).

#### Field fill rates (real test runs)

Search rows (2,500 rows, "bike" in the SF bay area): id, url, postingUrl, title, currency, category, area, subarea, location, latitude / longitude, postedAt, imageCount 100%; price / priceText 96%; photos 95%; neighborhood 71%.

With `includeDetails` (120 rows: cars by owner, apartments, jobs, furniture): description, attributes, updatedAt 100%; cars: makeModel, year, odometer, titleStatus 100%, condition 73%, VIN 20%; apartments: bedrooms, sqft, bathrooms, housingType 100%; jobs: jobTitle, salary, employmentType 100%, company 63%; furniture: condition 100%, make 57%.

### API example

Python (`pip install apify-client`):

```python
from apify_client import ApifyClient

client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("rel8ble/craigslist-scraper").call(run_input={
    "searchQueries": ["toyota tacoma"],
    "areas": ["sfbay", "losangeles"],
    "categories": ["cta"],
    "maxResults": 200,
})
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item["title"], "|", item["priceText"], "|", item["location"], "|", item["url"])
```

One HTTP call that runs the actor and returns the rows (curl):

```bash
curl -X POST "https://api.apify.com/v2/acts/rel8ble~craigslist-scraper/run-sync-get-dataset-items?token=<YOUR_APIFY_TOKEN>" \
  -H "Content-Type: application/json" \
  -d '{"searchQueries": ["iphone 13"], "areas": ["chicago"], "maxResults": 20}'
```

### Integrations

- **Make, Zapier and n8n**: trigger runs and pass new Craigslist listings into any workflow (Telegram, Slack or e-mail alerts for new cars or apartments under a price).
- **Google Sheets**: send each run's dataset straight into a spreadsheet to track prices over time.
- **Apify API**: start runs and fetch results over REST, or with the JavaScript and Python API clients.
- **Webhooks**: get notified when a run finishes, then pull the new data.
- **MCP for AI agents**: the Apify MCP server (https://mcp.apify.com) lets Claude, ChatGPT, Cursor and other agents call this actor and read Craigslist listings directly. Typical agent call: `{"searchQueries": ["iphone 13"], "areas": ["chicago"], "maxResults": 20}`, under 2 cents.
- **Schedules**: run it every hour with `sort: "newest"` (or `postedToday: true` once a day) to catch new listings as they appear.

### Limits

- **One Craigslist search lists at most 10,000 postings.** Deep search (on by default) splits bigger searches by sub-area, then category, then price band, and merges the results without duplicates. A few postings fall outside every narrower slice (for example listings without a price once price bands are needed), so a split search can end slightly below the site's count: everything for sale in the East Bay gave 82,877 of 83,372 (99.4%). The run summary shows the site's total next to what was saved.
- **No nationwide search on Craigslist.** Use `US` (or another country code) to search every site in a country; sites are searched in Craigslist's own area order, a few at a time, until `maxResults` is reached.
- **Dates.** Search rows carry the posted (or last renewed) time; with `includeDetails` you also get the time the poster last edited the posting.
- **Not included:** poster names, e-mail addresses, phone numbers, reply / relay addresses, street addresses, and anything that needs a Craigslist account. The actor never calls Craigslist's reply or contact endpoints.

### How it works (for developers)

craigslist.org's search page is a JavaScript app that loads results from `sapi.craigslist.org/web/v8/postings/search/full`. The first call returns up to 360 postings in a compact array format with lookup tables (`decode`): posting ids and dates are stored as offsets from `minPostingId` / `minPostedDate`, places as indexes into area, place-name and neighborhood tables, and extra fields as tagged arrays (`[4, ...photo ids]`, `[6, url slug]`, `[10, price text]`, `[5, bedrooms, sqft]`, `[9, odometer]`, `[7, salary]` ...). Asking for the whole list returns up to 10,000 postings without titles plus a `cacheId`; titles and photos then come from `.../search/batch` in blocks of 1,080. Posting details come from `rapi.craigslist.org/web/v8/postings/<uuid>`. Area and category lists are Craigslist's public `reference.craigslist.org` files.

```bash
npm install
npm test                                   # parser tests on saved real API answers
APIFY_LOCAL_STORAGE_DIR=./storage node src/main.js   # input in storage/key_value_stores/default/INPUT.json
```

# Actor input Schema

## `searchQueries` (type: `array`):

Optional. What you would type into the Craigslist search box, one per line: "bike", "iphone 13", "toyota tacoma", "couch", "2 bedroom". Each keyword is one search (times each category and area). Leave empty to list a whole category instead.

## `areas` (type: `array`):

Craigslist sites to search, one per line: the site name from the address (sfbay.craigslist.org = "sfbay", "newyork", "losangeles", "chicago", "seattle", "london", "toronto", "berlin"), an area name ("SF bay area"), a sub-area ("newyork/brk", "brooklyn", "south bay"), or a country code for every site in it ("US" = 413 sites, "CA", "GB", "AU"). Several = one search per area. Needed unless you give a postalCode or startUrls. A country counts as one search: maxResults applies to all its sites together.

## `categories` (type: `array`):

Optional. Craigslist category codes or names, one per line. The code is the part after /search/ in a Craigslist URL (/search/bia = bicycles). Main ones: sss = for sale (all), bia = bicycles, cta = cars & trucks, fua = furniture, ela = electronics, zip = free stuff, hhh = housing (all), apa = apartments / housing for rent, jjj = jobs (all), ggg = gigs (all), bbb = services (all), ccc = community (all). Narrower ones work too: "cto" (cars & trucks by owner), "mca" (motorcycles), "moa" (cell phones), "sya" (computers), "roo" (rooms), "sof" (software jobs). Several = one search per category. Empty = "sss" (everything for sale).

## `postalCode` (type: `string`):

Optional. Search around a US ZIP or other postal code instead of whole areas, e.g. "94110" or "10001"; combine with distanceMiles. Craigslist picks the right site(s) itself, so areas are not needed (and not used) with a postal code. Rows then carry distanceMiles.

## `distanceMiles` (type: `integer`):

Optional, only used with postalCode. Search radius in miles, e.g. 5, 10, 25, 50. Empty = the site's default around that code.

## `priceMin` (type: `integer`):

Optional. Lowest price in whole units of the local currency (USD on US sites), e.g. 50. Empty = no minimum. Listings without a price are left out by any price filter, as on the website.

## `priceMax` (type: `integer`):

Optional. Highest price in whole units of the local currency, e.g. 500. Empty = no maximum.

## `hasImage` (type: `boolean`):

Optional boolean, default false. true = only listings that have at least one photo ("has image").

## `postedToday` (type: `boolean`):

Optional boolean, default false. true = only listings posted today ("posted today"). Good for daily schedules.

## `searchTitlesOnly` (type: `boolean`):

Optional boolean, default false. true = keywords must appear in the title, not just the description (fewer, more exact matches).

## `bundleDuplicates` (type: `boolean`):

Optional boolean, default false. true = postings Craigslist marks as duplicates (the same item re-posted) are collapsed into one row (the newest), with duplicateCount saying how many copies were folded in.

## `sellerType` (type: `string`):

Optional. "any" (default), "owner" (private sellers, "by owner") or "dealer" (businesses, "by dealer"). Only has an effect in for-sale categories.

## `sort` (type: `string`):

Optional. "newest" (default; use it on a schedule to catch new listings), "oldest", "price_asc", "price_desc", "relevance" or "distance" (needs postalCode).

## `startUrls` (type: `array`):

Optional. URLs copied from craigslist.org, one per line. A search URL ("https://sfbay.craigslist.org/search/cta?auto_make_model=toyota\&max_price=15000", "https://www.craigslist.org/search/area/newyork?cat=apa\&min_bedrooms=2") is scraped with every filter in it, including category-specific ones (make/model, odometer, bedrooms, condition ...); the fields above are not applied to it. A posting URL ("https://sfbay.craigslist.org/pen/bik/d/.../7945993826.html" or "https://www.craigslist.org/view/d/.../<id>") is looked up directly with full details.

## `maxResults` (type: `integer`):

Optional. Maximum listings saved per search (one keyword x category x area, or one URL), integer >= 0. Default 100; 0 = every listing the search has. You pay per listing saved ($0.00045 each), so 1,000 listings = $0.45. Use 10-20 for a quick answer.

## `deepSearch` (type: `boolean`):

Optional boolean, default true. One Craigslist search lists at most 10,000 postings. With deep search on, a bigger search is split automatically by sub-area, then category, then price band, and the results are merged without duplicates. Only kicks in when maxResults is above 10,000 (or 0). Costs extra requests and time, not extra money per listing.

## `includeDetails` (type: `boolean`):

Optional boolean. false (default) = data from the search: title, price, place, neighborhood, approximate map position, date, category, all photos, plus bedrooms / sqft (housing), odometer (cars), salary / company (jobs); about 1,000 listings per request. true = also open each posting for the full description (e-mails and phone numbers masked), all attributes (condition, make / model, year, size, type ...), notices, exact posted and updated time. Same price per listing, about 1 extra request per listing.

## `includeNearbyAreas` (type: `boolean`):

Optional boolean, default false. When an area has few matches, Craigslist adds postings from nearby sites below them. false = keep only the area you searched; true = keep those too (marked isNearbyArea: true).

## `maxConcurrency` (type: `integer`):

Optional, advanced. Parallel requests, integer 1-20. Default 5; requests are also paced to stay polite. Leave unset.

## `maxRequestRetries` (type: `integer`):

Optional, advanced. Retries per failed or blocked request, integer 0-20; each retry uses a new session (and proxy IP when a proxy is on). Default 8. Leave unset.

## `proxyConfiguration` (type: `object`):

Optional, advanced. Apify Proxy settings object. Default {"useApifyProxy": true} (datacenter proxy, enough for Craigslist). Leave unset.

## Actor input object example

```json
{
  "searchQueries": [
    "bike"
  ],
  "areas": [
    "sfbay"
  ],
  "hasImage": false,
  "postedToday": false,
  "searchTitlesOnly": false,
  "bundleDuplicates": false,
  "sellerType": "any",
  "sort": "newest",
  "maxResults": 20,
  "deepSearch": true,
  "includeDetails": false,
  "includeNearbyAreas": false,
  "maxConcurrency": 5,
  "maxRequestRetries": 8,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `listings` (type: `string`):

All listings found: title, price, currency, place, neighborhood, approximate map position, date, category, photos and URLs, plus bedrooms / odometer / salary where Craigslist shows them (and description, attributes, condition, make / model when includeDetails is on).

## `summary` (type: `string`):

Per-search counts, the total the site shows for each search, how many narrower searches deep search ran, stop reasons, warnings (unknown areas) and anything that failed.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "searchQueries": [
        "bike"
    ],
    "areas": [
        "sfbay"
    ],
    "maxResults": 20,
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("rel8ble/craigslist-scraper").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "searchQueries": ["bike"],
    "areas": ["sfbay"],
    "maxResults": 20,
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("rel8ble/craigslist-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "searchQueries": [
    "bike"
  ],
  "areas": [
    "sfbay"
  ],
  "maxResults": 20,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call rel8ble/craigslist-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,rel8ble/craigslist-scraper"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/T35sBbkchWKKj13A4/builds/chv9HoawXTgyKdtyP/openapi.json
