# Craigslist Scraper - Any City, Any Category (`webdata_labs/craigslist-scraper`) Actor

\[💵 $1.90 / 1K] Scrape Craigslist listings from any city and category in one run. Multi-city, price/ZIP/radius filters, duplicate removal, plus optional descriptions, attributes, coordinates and images. Or just paste a search URL.

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

## Pricing

from $1.10 / 1,000 listings

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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 - any city, any Category

**Scrape Craigslist listings into a clean spreadsheet. Many cities in one run, every filter Craigslist has, and pagination that does not stop at page one.**

Give it a keyword and a city - or just paste a Craigslist search URL - and get back every listing with title, price, location, coordinates, photos, posting date and a working link. Turn on **Include full listing details** and each row also carries the full description, the seller's attributes (condition, make, model, bedrooms, mileage...) and exact coordinates.

### ✅ What you get / ❌ what this isn't

| ✅ This Actor gives you | ❌ This Actor is not |
|---|---|
| **Many cities in one run** - list 1 or 50 | Not one run per city |
| **Thousands of listings per search** - it pages past Craigslist's ~360 page cap | Not the first page only |
| Every Craigslist filter: price, ZIP + radius, photos-only, title-only, nearby areas | Not keyword-only search |
| Duplicate reposts removed by default | Not a raw dump of the same ad 12 times |
| Full descriptions, attributes, coordinates and all photos on demand | Not private seller contact details |
| Paste any Craigslist search URL and it just works | Not a puzzle of undocumented city codes |

### 🔎 Why this one

- **No 360-result ceiling.** Craigslist's own search page stops after a few hundred results. This Actor speaks Craigslist's internal pagination protocol and keeps going - 1,000, 5,000, as many as the search has.
- **Multi-city.** `["newyork", "sfbay", "chicago"]` in one run instead of three runs you stitch together yourself.
- **City names that make sense.** `newyork`, `New York`, `sfbay`, `SF bay area`, even a pasted `losangeles.craigslist.org` all resolve. 700+ Craigslist regions worldwide.
- **Paste-a-URL mode.** Built the perfect search in your browser? Paste the URL into `startUrls` - every filter in it is honoured.
- **Duplicates gone.** The same ad reposted under new IDs is collapsed automatically.
- **Category-aware fields.** Cars get `odometer`, apartments get `bedrooms` and `sqft`, jobs get `compensation` and `employer` - without you asking.
- **Fast and cheap.** Pure HTTP, no browser. A thousand listings takes well under a minute.

### 👥 Who it's for

- **Resellers and flippers** watching for underpriced inventory across several metros at once.
- **Real-estate and rental analysts** pulling apartment inventory with beds, sqft and price.
- **Car dealers and buyers** tracking local vehicle pricing with mileage.
- **Recruiters** monitoring job and gig postings by city.
- **Researchers** building local-market datasets.

### ⚙️ How to scrape Craigslist

1. Open the Actor on Apify.
2. Type your **search terms**, e.g. `mountain bike`.
3. Add one or more **cities**, e.g. `newyork` and `sfbay`.
4. Pick a **category** (or leave it on *All for sale*).
5. Set **Max listings** - the budget for the whole run, split evenly across your searches.
6. Optional: turn on **Include full listing details**, set a price range, a ZIP + radius, or photos-only.
7. Click **Start**, then download the results as CSV, JSON or Excel.

Prefer a URL? Skip steps 2-6 and paste your Craigslist search URL into **Craigslist search URLs**.

### 📥 Input

```json
{
  "searchTerms": ["mountain bike"],
  "cities": ["newyork", "sfbay"],
  "category": "bicycles",
  "maxItems": 500,
  "minPrice": 100,
  "maxPrice": 800,
  "hasImage": true,
  "includeDetails": true,
  "sortBy": "newest"
}
```

| Field | Meaning |
|---|---|
| `searchTerms` | Keywords. Leave empty to browse a whole category. |
| `cities` | One or more Craigslist regions. `newyork`, `New York` and `nyc` all work. |
| `category` | Section to search: all for sale, housing, jobs, cars, apartments, gigs... |
| `maxItems` | Listings for the whole run, split across your searches. |
| `includeDetails` | Open every posting for description, attributes, exact coordinates, all photos. |
| `startUrls` | Paste Craigslist search URLs; their filters are honoured as-is. |
| `minPrice` / `maxPrice` | Price range. |
| `postedWithinDays` | Keep only listings from the last N days. |
| `hasImage` | Only listings with photos. |
| `titleOnly` | Match the keyword against the title only - far less noise. |
| `searchNearbyAreas` | Include neighbouring Craigslist regions. |
| `postalCode` + `searchRadiusMiles` | Search around a ZIP code. |
| `sortBy` | Newest, best match, price low→high, price high→low. |
| `deduplicate` | Collapse the same ad reposted under new IDs. On by default. |
| `imageSize` | Thumbnail, small, medium or large image URLs. |
| `proxyConfiguration` | Apify Proxy. Recommended - Craigslist rate-limits by IP. |

### 📤 Output

One row per listing:

| title | price | location | city | category | postedAt | imageCount | url |
|---|---|---|---|---|---|---|---|
| Trek 800 mountain track bicycle | 120 | brooklyn | newyork | bicycles - by owner | 2026-07-25T13:54:46Z | 3 | [link](https://newyork.craigslist.org/) |

**Always present:** `postingId`, `title`, `price`, `priceText`, `location`, `city`, `category`, `categoryCode`, `url`, `postedAt`, `latitude`, `longitude`, `imageCount`, `imageUrls`, `thumbnailUrl`, `postingHash`, `searchTerm`, `totalResultsAvailable`, `scrapedAt`.

**By category, when Craigslist provides it:** `bedrooms`, `sqft` (housing) · `odometer` (vehicles) · `compensation`, `employer`, `jobTitle` (jobs).

**With `includeDetails`:** `description`, `attributes` (every seller-filled field), `condition`, `make`, `model`, `address`, precise `latitude`/`longitude`, `mapAccuracy`, `originalPostedAt`, `updatedAt`, full-resolution `imageUrls`, `isActive`.

<details>
<summary>Sample row (with details on)</summary>

```json
{
  "postingId": 7941528365,
  "title": "Trek 800 mountain track bicycle nice bike $120",
  "price": 120,
  "priceText": "$120",
  "location": "brooklyn",
  "city": "newyork",
  "category": "bicycles - by owner",
  "url": "https://newyork.craigslist.org/bik/d/brooklyn-trek-800-mountain-track/7941528365.html",
  "postedAt": "2026-07-25T13:54:46Z",
  "latitude": 40.610653,
  "longitude": -73.953544,
  "imageCount": 3,
  "imageUrls": ["https://images.craigslist.org/00v0v_gzsOLs7OU3w_0x20oM_600x450.jpg"],
  "description": "Trek 800 mountain track bicycle nice bike",
  "attributes": { "condition": "excellent" },
  "condition": "excellent",
  "address": "Ocean Avenue near Kings Highway",
  "originalPostedAt": "2026-06-17T10:36:29-0400",
  "updatedAt": "2026-07-25T09:49:46-0400",
  "isActive": true
}
```

</details>

#### Quick preview

| Input | Output |
|---|---|
| `mountain bike` in `newyork` + `sfbay`, photos only, $100-$800 | ~40 bikes across both metros with prices, photos and map coordinates |
| `category: apartments`, `postalCode: 10001`, radius 5 mi | Manhattan rentals with `bedrooms`, `sqft` and price |
| Pasted URL `sfbay.craigslist.org/search/cta?query=tacoma&max_price=20000` | Trucks under $20k with `odometer` on every row |

### 💵 How much does it cost?

**$1.90 per 1,000 listings. No start fee** - a run that returns nothing costs you nothing.

Because it runs on plain HTTP instead of a browser, a 1,000-listing run finishes in well under a minute. `includeDetails` adds one request per listing; it is slower, but the price per listing does not change.

### 🚀 Ready-made setups

Five ready-to-run tasks ship with this Actor - open one, hit Start, or copy it and swap in your own cities:

| Task | What it does |
|---|---|
| [Find Craigslist cars and trucks under $10,000](https://apify.com/webdata_labs/craigslist-scraper/examples/craigslist-cars-and-trucks-under-10k) | Cars & trucks under $10k across New York, Los Angeles and Chicago, with mileage and condition on every row. |
| [Scrape Craigslist apartments for rent near a ZIP code](https://apify.com/webdata_labs/craigslist-scraper/examples/craigslist-apartments-for-rent-near-zip) | Rentals within 10 miles of ZIP 10001 under $4,000, with bedrooms, sqft and full descriptions. |
| [Monitor Craigslist free stuff posted today](https://apify.com/webdata_labs/craigslist-scraper/examples/craigslist-free-stuff-posted-today) | Everything listed free today in the SF Bay Area, Los Angeles and Seattle - photos only. |
| [Find underpriced Craigslist furniture to flip](https://apify.com/webdata_labs/craigslist-scraper/examples/craigslist-furniture-deals-to-flip) | Mid-century, solid wood and Herman Miller pieces under $300 in Chicago and Boston. |
| [Scrape Craigslist job postings across several cities](https://apify.com/webdata_labs/craigslist-scraper/examples/craigslist-job-postings-by-city) | Jobs posted in the last week in New York, Austin and Denver, with pay and employer. |

### 🔁 Run it on the Apify platform

Schedule it to sweep your cities every morning, call it from the Apify API, export to CSV/JSON/Excel, or wire it into Make, Zapier, Google Sheets or a webhook so new listings land wherever you work.

### ⚠️ Limits and caveats

- Reads only **public** Craigslist listings. It does not log in, and it does not collect seller emails or phone numbers.
- Craigslist blocks an IP after a burst of requests. The Actor rotates its proxy exit IP per search and part-way through detail fetching, so keep Apify Proxy on (it is by default) - turning it off will cut multi-city runs short.
- `postedAt` is the date Craigslist shows in search results - for renewed ads that is the renewal date. With `includeDetails` you also get `originalPostedAt` and `updatedAt`.
- Craigslist caps any single search at a few thousand results. For very broad searches, split by category, city or price band.
- Fields such as `bedrooms` or `odometer` exist only where the seller filled them in.

### 🧩 Related Actors

- [Mercari Sold Listings Scraper](https://apify.com/webdata_labs/mercari-sold-listings-scraper) - what items actually sold for, not what sellers are asking.
- [Poshmark Sold Listings Scraper](https://apify.com/webdata_labs/poshmark-sold-listings-scraper) - real resale comps for fashion, sold prices only.
- [AutoScout24 Scraper](https://apify.com/webdata_labs/autoscout24-scraper) - used-car listings across six countries, plus a dealer lead list.
- [Etsy Scraper](https://apify.com/webdata_labs/etsy-scraper) - handmade and vintage listings with sponsored versus organic rank.
- [Lead List Cleaner](https://apify.com/webdata_labs/lead-list-deduplicator) - merge several runs into one deduplicated, CRM-ready list.

### ❓ FAQ

**Can I scrape more than one city per run?** Yes. List as many as you like in `cities`; results are tagged with the city they came from.

**Can I get more than the ~360 results Craigslist shows?** Yes - that is the main reason this Actor exists. Set `maxItems` higher and it pages through the full result set.

**Do I need to know Craigslist's city codes?** No. Type the city the way you say it.

**Can I reuse a search I built in my browser?** Yes - paste the URL into `startUrls`.

**Does it collect personal data?** No. Public listing content only, no contact details.

**Why are some fields empty?** Craigslist listings are free-form. A field appears only when the seller filled it in and, for descriptions and attributes, when `includeDetails` is on.

### 🛠️ Support

If a run fails or a field looks wrong, open an Actor issue with the run URL, the input you used, and what you expected. Craigslist changes its layout occasionally - reports get fixed quickly.

### ⭐ Rate this Actor

If this Actor saved you time, please take 30 seconds to leave a review on the **Reviews** tab - reviews are the main trust signal other users see, and they decide which features get built next. If something is broken, please open an issue first: we typically respond within a day and would love the chance to fix it before you rate.

# Actor input Schema

## `searchTerms` (type: `array`):

Keywords to search for. Leave empty to browse a whole category. Each term is searched in every city you list.

## `cities` (type: `array`):

One or more Craigslist cities. Type them however you like - 'newyork', 'New York', 'sfbay' and 'SF bay area' all work. Add as many as you want; the competition makes you run once per city.

## `category` (type: `string`):

Which Craigslist section to search.

## `maxItems` (type: `integer`):

Total listings for the whole run, split evenly across your searches. Craigslist search pages stop at ~360 results - this Actor pages past that and can pull thousands.

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

Open each posting to add the full description, seller attributes (condition, make, model, bedrooms, mileage...), exact coordinates and every image. Slower, but much richer.

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

Paste search URLs straight from your browser - all filters in the URL are honoured. Use this instead of the fields above when you already have a search you like.

## `minPrice` (type: `integer`):

Lowest price to include. Leave empty for no minimum.

## `maxPrice` (type: `integer`):

Highest price to include. Leave empty for no maximum.

## `postedWithinDays` (type: `integer`):

Keep only listings posted in the last N days. Leave empty to keep everything.

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

Skip listings without photos. Useful when you need images for resale or review.

## `titleOnly` (type: `boolean`):

Match the search term against the title instead of the whole posting. Cuts a lot of noise.

## `searchNearbyAreas` (type: `boolean`):

Also return results from Craigslist regions neighbouring each city.

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

Centre the search on a ZIP code. Combine with the search radius below.

## `searchRadiusMiles` (type: `integer`):

Only used together with a ZIP code.

## `sortBy` (type: `string`):

Order Craigslist returns results in. 'Newest first' is best for monitoring; price sorts are best for deal hunting.

## `deduplicate` (type: `boolean`):

Craigslist is full of the same ad reposted under new IDs. On by default: identical title + price + location is kept once.

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

Ask Craigslist itself to collapse repeat postings before they reach you.

## `imageSize` (type: `string`):

Resolution of the image URLs in the output. Larger sizes are the same photos at higher resolution.

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

Retries per request before a search is recorded as failed.

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

Craigslist rate-limits by IP. Datacenter proxies are enough for most runs; switch to residential if you scrape very large volumes.

## Actor input object example

```json
{
  "searchTerms": [
    "mountain bike"
  ],
  "cities": [
    "newyork"
  ],
  "category": "all",
  "maxItems": 200,
  "includeDetails": false,
  "startUrls": [],
  "hasImage": false,
  "titleOnly": false,
  "searchNearbyAreas": false,
  "sortBy": "newest",
  "deduplicate": true,
  "bundleDuplicates": false,
  "imageSize": "medium",
  "maxRequestRetries": 4,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

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

No description

## `details` (type: `string`):

No description

# 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 = {
    "searchTerms": [
        "mountain bike"
    ],
    "cities": [
        "newyork"
    ],
    "startUrls": []
};

// Run the Actor and wait for it to finish
const run = await client.actor("webdata_labs/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 = {
    "searchTerms": ["mountain bike"],
    "cities": ["newyork"],
    "startUrls": [],
}

# Run the Actor and wait for it to finish
run = client.actor("webdata_labs/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 '{
  "searchTerms": [
    "mountain bike"
  ],
  "cities": [
    "newyork"
  ],
  "startUrls": []
}' |
apify call webdata_labs/craigslist-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,webdata_labs/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/v5m1MJ9Uv73VrIEbm/builds/HZkrtVQMrCJOF0BKb/openapi.json
