# Craigslist Scraper & Monitor - $0.50/1K Listings (`zhyou/craigslist-scraper`) Actor

$0.50 per 1,000 listings. Search Craigslist for sale, cars, housing, jobs, gigs and services by area, keyword and filters or by URL. Monitor mode returns only new listings and price drops. Optional full details. No phone numbers or emails.

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

## Pricing

from $0.50 / 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.

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 & Monitor

Scrape Craigslist listings from any of its 700+ areas: for sale, cars & trucks, housing, jobs, gigs and services. Search by area, keyword, category and filters, or paste any Craigslist search URL. Built for deal hunting, car and real-estate sourcing, price research, rental market tracking and AI agents.

- **$0.50 per 1,000 listings**, no start fee beyond the platform's $0.00005. Full posting details are optional.
- **Monitor mode**: schedule it and each run returns only **new listings and price changes** (`priceDrop` / `priceIncrease` with the previous price) since the last run. You only pay for those.
- **Any area, any category**: `sfbay`, `newyork`, `losangeles`, `toronto`, `london` ... or a subarea like `sfbay/eby`. Many areas × keywords in one run.
- **Filters**: price range, by owner / by dealer, posted today, with images, title-only search. Paste a search URL from the site to use any other filter Craigslist has (make / model, odometer, bedrooms, ...).
- **Category fields from the search itself**: bedrooms and square feet for housing, odometer for cars, compensation, job title and employer for jobs.
- **Posting details** (optional): description, every attribute (condition, make / model, year, fuel, title status, rent period, employment type, ...), city, ZIP code, last update time and all photos.
- **No personal contact data**: phone numbers and email addresses are removed from titles, descriptions and attributes. Community, events, resumes and housing-wanted posts are not collected.

### What you get

One row per listing. From the search (always included):

```json
{
  "postingId": 7985162508,
  "title": "Oru Kayak",
  "url": "https://www.craigslist.org/view/d/brooklyn-oru-kayak/8SMkFdFj4aR8omM6ygd4E4",
  "price": 450,
  "priceText": "$450",
  "currency": "USD",
  "postedAt": "2026-10-17T16:00:03Z",
  "category": "for",
  "categoryName": "general for sale - by owner",
  "area": "newyork",
  "subarea": "brk",
  "location": "brooklyn",
  "nearbyArea": false,
  "latitude": 40.6628,
  "longitude": -73.9546,
  "imageUrls": ["https://images.craigslist.org/00V0V_eIoDSBSFtyI_0dM0fo_600x450.jpg", "..."],
  "bedrooms": null,
  "areaSqft": null,
  "odometer": null,
  "compensation": null,
  "jobTitle": null,
  "employer": null,
  "searchUrl": "https://newyork.craigslist.org/search/brk/sss?query=kayak&sort=date",
  "query": "kayak",
  "scrapedAt": "2026-10-20T12:20:37Z"
}
```

With **Include posting details** on, each row also has:

```json
{
  "description": "The Oru Lake: The Lightest, Simplest Origami Kayak Ever ... purchased on kickstarter 2 years ago for $584 and never used.",
  "attributes": {"condition": "new", "make / manufacturer": "Oru", "model name / number": "Kayak", "size / dimensions": "9’L x 32”W"},
  "features": [],
  "updatedAt": null,
  "city": "Brooklyn",
  "region": "NY",
  "postalCode": "11225",
  "country": "US",
  "mapAddress": null,
  "categoryPath": ["new york", "brooklyn", "for sale by owner", "general for sale"],
  "employmentType": null
}
```

A car shows `"attributes": {"year": "2019", "make / model": "Honda Civic Type R", "condition": "like new", "fuel": "gas", "odometer": "50,953", "title status": "clean", "transmission": "manual"}`; an apartment shows `"attributes": {"rent period": "monthly"}`, `"features": ["1BR / 1Ba", "available oct 29", "apartment", "laundry on site", "attached garage"]` and the `mapAddress` the landlord published.

In monitor mode every row also has `change` (`new`, `priceDrop`, `priceIncrease`) and `previousPrice`.

### How to use

**Option 1: areas + keywords**

1. **Areas**: Craigslist subdomains, one per line (`sfbay`, `newyork`, `chicago`, ...). Add a subarea after a slash (`sfbay/eby`, `newyork/brk`). Names like "SF bay area" work too.
2. **Keywords**: one per line, or leave empty to list a whole category.
3. Pick a **Category** (For sale, Cars & trucks, Apartments, Jobs, ...) and optional filters.

**Option 2: search URLs**

Set up a search on craigslist.org with any filters, copy the address bar, and paste it into **Search URLs**. Both forms work:

- `https://sfbay.craigslist.org/search/cta?query=tacoma&max_price=20000&auto_transmission=2`
- `https://www.craigslist.org/search/area/newyork?cat=apa&min_bedrooms=2&max_price=3500`

Then run and download the dataset as JSON, CSV or Excel, or read it through the API.

#### Monitor new listings and price drops

Turn on **Monitor mode**, choose a **Monitor key** (e.g. `tacoma-under-20k`) and schedule the Actor every hour or every day. The first run returns the current listings as the baseline. After that, each run returns only listings posted since the previous run and listings whose price changed. Connect the dataset to Slack, email, Make, n8n or Zapier to get an alert for every new match. Use a different key for each independent schedule, and don't start two runs with the same key at the same time.

If more new listings can arrive between two runs than **Max listings per search**, raise the max (up to 360) or run more often.

#### Input example

```json
{
  "areas": ["sfbay", "losangeles", "seattle"],
  "queries": ["toyota tacoma", "4runner"],
  "category": "cta",
  "sellerType": "owner",
  "maxPrice": 25000,
  "hasImage": true,
  "maxItemsPerSearch": 100,
  "monitorMode": true,
  "monitorKey": "west-coast-trucks"
}
```

### Pricing

Pay per result:

- **$0.0005 per listing** ($0.50 per 1,000), search fields only.
- **$0.001 per listing with details** ($1 per 1,000), when **Include posting details** is on.
- $0.00005 per run start. Proxy and compute are included.

Example: checking 10 searches every hour in monitor mode costs only the new listings, typically a few cents a day. Failed requests and listings removed before they could be opened are not charged as detailed. Set a maximum cost per run in the run options and the Actor stops exactly there.

### Notes and limits

- **360 listings per search.** Craigslist's search returns at most 360 listings per query, even when the site counts more. To collect more, split by price range (`minPrice` / `maxPrice`), subarea or keyword. In monitor mode, keep **Max listings per search** above the number of new listings that can appear between two runs: extras beyond the max are marked as seen and not reported later.
- **Nearby areas.** When an area has few matches, Craigslist adds listings from neighbouring areas. They are left out by default; turn on **Include nearby areas** to keep them (they have `nearbyArea: true`). A subarea search (`newyork/brk`) keeps only that subarea.
- Keywords match the title and the description, as on the site. Turn on **Search titles only** for stricter matches.
- `price` is `null` when the listing has no price (most jobs, gigs and services). Prices are in the area's currency (`currency`).
- Listings can be deleted at any time; with details on, a listing removed between the search and the detail request is returned with search fields only and `detailsError`.
- Phone numbers and email addresses in titles, descriptions and attributes are replaced with `[phone removed]` / `[email removed]`. The Actor never collects reply emails or contact details.
- Community (missed connections, rideshare, groups ...), events, resumes and housing-wanted posts are not collected because they are mostly about private people.
- Data is public Craigslist content. Use it in line with Craigslist's terms and the laws that apply to you.

### FAQ

**Do I need a Craigslist account?** No.

**Can I search all of the US at once?** Add the areas you need to **Areas**; each one is a separate search. The 50 largest metro areas cover most listings.

**Which area names exist?** Every subdomain listed on [craigslist.org/about/sites](https://www.craigslist.org/about/sites) works, in the US, Canada, Europe, Asia and Latin America.

# Actor input Schema

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

Craigslist areas as subdomains (sfbay, newyork, losangeles, chicago, seattle, toronto, london, ...) or names ("SF bay area"). Add a subarea after a slash to narrow it: sfbay/eby, newyork/brk. Every area is searched for every keyword. Ignored when Search URLs are given.

## `queries` (type: `array`):

One search per keyword and area. Leave empty to list the whole category.

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

Craigslist category. Community, events, resumes and housing-wanted posts are not collected (they are mostly about private people).

## `searchUrls` (type: `array`):

Paste searches straight from Craigslist, with any filters you set on the site (make / model, bedrooms, odometer, ...), e.g. https://sfbay.craigslist.org/search/cta?query=tacoma\&max_price=20000. When given, Areas, Keywords, Category and the filters below are ignored (sort still applies unless the URL has its own).

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

Optional.

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

Optional.

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

For-sale categories only.

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

Craigslist's own 'posted today' filter.

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

Only listings that have photos.

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

Match keywords in the title only, not the description.

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

Craigslist's option to group near-identical reposts.

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

Craigslist returns up to 360 listings per search, picked in this order. Monitor mode always uses Newest.

## `maxItemsPerSearch` (type: `integer`):

Craigslist returns at most 360 listings per search. For more, split the search by price range, subarea or keyword.

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

When an area has few matches, Craigslist adds listings from nearby areas. Off = only the areas you asked for. Nearby rows have nearbyArea: true.

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

Opens every listing to add the description, all attributes (condition, make / model, odometer, bedrooms, compensation, ...), city, ZIP code, last update time and every photo. Priced as a detailed listing. Phone numbers and email addresses in the text are removed.

## `monitorMode` (type: `boolean`):

Remembers the listings each search returned (per monitor key). Schedule the Actor and every run returns only listings posted since the last run, plus listings whose price changed (change: priceDrop / priceIncrease, with previousPrice). The first run returns the current listings as the baseline. Uses Newest sorting.

## `monitorKey` (type: `string`):

Name of the watch list. Use different keys for independent schedules.

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

Parallel requests. Lower it if you see many retries.

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

Requests go out through Apify Proxy and are retried on a fresh IP if blocked. Datacenter proxies are the default and work well.

## Actor input object example

```json
{
  "areas": [
    "sfbay"
  ],
  "queries": [
    "bike"
  ],
  "category": "sss",
  "sellerType": "all",
  "postedToday": false,
  "hasImage": false,
  "searchTitlesOnly": false,
  "bundleDuplicates": false,
  "sort": "date",
  "maxItemsPerSearch": 100,
  "includeNearbyAreas": false,
  "includeDetails": false,
  "monitorMode": false,
  "monitorKey": "default",
  "maxConcurrency": 10,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `results` (type: `string`):

One row per listing.

# 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 = {
    "areas": [
        "sfbay"
    ],
    "queries": [
        "bike"
    ],
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("zhyou/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 = {
    "areas": ["sfbay"],
    "queries": ["bike"],
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("zhyou/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 '{
  "areas": [
    "sfbay"
  ],
  "queries": [
    "bike"
  ],
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call zhyou/craigslist-scraper --silent --output-dataset

```

## MCP server setup

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