# Craigslist Scraper | Listings, Prices & Details (`datascraperes/craigslist-scraper`) Actor

Collect Craigslist listings across 50 US and Canadian regions. Search cars, housing, jobs, electronics, furniture, services, gigs and events with keyword, price, condition, image and date filters. Export unique listings with descriptions, images, post IDs, locations and category-specific attributes.

- **URL**: https://apify.com/datascraperes/craigslist-scraper.md
- **Developed by:** [DataScraperES](https://apify.com/datascraperes) (community)
- **Features:** Limited permissions
- **Stats:** 2 total users, 2 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.85 / 1,000 craigslist 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

Collect **Craigslist listings with prices, descriptions, images and category-specific attributes**. Choose a city and category, add optional filters, or paste search and posting URLs. Export unique results for market research, inventory monitoring and classifieds analysis.

### What this Actor does

The Actor searches Craigslist and returns one Dataset item per unique posting. The city selector contains 50 presets: 44 US regions and six Canadian regions. Categories cover general sale listings, cars and trucks, electronics, furniture, apartments and houses, rooms, sublets, jobs, gigs, services, community, resumes and events.

You can collect search-listing information alone or request full posting details. Full details include the published description, category-specific attributes, available gallery images, posting dates and location information. Phone numbers and email addresses are extracted only when present in the public description.

### Use cases

- Compare advertised vehicle prices, condition and mileage across cities.
- Monitor housing listings by asking price, bedrooms and published features.
- Collect job and gig descriptions with compensation when disclosed.
- Track second-hand product availability and asking prices.
- Build a deduplicated classifieds dataset with links back to each posting.

### How to use

1. Choose a **City / region** and **Category**, then optionally enter a keyword. Alternatively, paste Craigslist search or posting URLs.
2. Set **Maximum results** and choose whether to include full details.
3. Click **Start** and open the Dataset when the run finishes.
4. Download results in JSON, CSV or Excel. Check the run summary if any sources or details could not be retrieved.

The run log shows processed listings versus the requested limit, percentage, successful and failed sources, collection speed, estimated time remaining and elapsed time. Updates are sent periodically while work is in progress. The final message distinguishes completion, an empty search and collection problems.

### Input

```json
{
  "startUrls": [],
  "region": "sfbay",
  "category": "cta",
  "searchTerm": "honda",
  "priceMin": 0,
  "priceMax": 100000,
  "condition": "any",
  "hasImage": false,
  "postedToday": false,
  "sort": "rel",
  "includeDetails": true,
  "maxResults": 10,
  "includeNearby": false
}
```

| Field | Default | Behavior |
|---|---|---|
| `startUrls` | Empty | Up to 100 search, category or posting URL strings. URL filters are preserved. When supplied, all guided search settings below are ignored. |
| `region` | `newyork` | One of the 50 preset regions. |
| `category` | `sss` | Top-level category code: `sss` For sale, `cta` Cars & trucks, `ela` Electronics, `fua` Furniture, `apa` Apartments & houses, `roo` Rooms & shares, `sub` Sublets & temporary, `jjj` Jobs, `ggg` Gigs, `bbb` Services, `ccc` Community, `rrr` Resumes, `eee` Events. Use `startUrls` for a specific subcategory. |
| `searchTerm` | Empty | Optional keyword, up to 500 characters. |
| `priceMin`, `priceMax` | Unset | Price range in the listing's local currency, for applicable categories. |
| `condition` | `any` | `new`, `like-new`, `excellent`, `good`, `fair` or `salvage`, where supported. |
| `hasImage`, `postedToday` | `false` | Apply Craigslist's corresponding search filters. |
| `sort` | `date` | Newest, relevance (`rel`), lowest price (`priceasc`) or highest price (`pricedsc`). |
| `includeDetails` | `true` | Fetch full posting details. Individual posting URLs always receive detail extraction. |
| `maxResults` | `200` | Strict global limit across all sources. `0` allows up to 100,000 unique rows. |
| `includeNearby` | `false` | Include nearby-area suggestions when Craigslist supplies them. |

The same posting appears only once across the run. Sources are processed in input order; the result limit can be reached before later sources are searched. Sorting applies within each search, not across all regions combined. The 100,000-row limit is an Actor safety cap, not a promise that Craigslist exposes that many matches.

The Canadian presets are Montreal, Toronto, Vancouver, Calgary, Ottawa and Edmonton. US presets include New York, Los Angeles, Chicago, San Francisco Bay Area, Seattle, Boston, Miami, Dallas, Houston and the other regions in the selector. Pasted URLs may identify additional Craigslist areas, but coverage outside the presets is not comprehensively verified.

Example input:

```json
{
  "region": "seattle",
  "category": "ela",
  "searchTerm": "20uf",
  "maxResults": 1
}
```

### Output

Results are stored in the default Dataset. Each item identifies the original posting and the search or URL that produced it. Prices use the listing's local currency and are not converted to US dollars. Category attributes vary by posting, and absent information remains `null`, an empty array or an empty object.

`detailsStatus` distinguishes complete detail extraction (`ok`), listing-only output (`not_requested`), confirmed deletion (`deleted`) and detail retrieval problems such as `not_found`, `blocked` or `network_error`. If an optional detail request fails, the valid search listing is retained with the failure status. A direct URL that cannot be retrieved produces a summary error rather than an invented listing.

`isDeleted` is `true` only for an explicit deletion message, `false` for a valid fetched posting, and otherwise unknown (`null`). `isNearby` marks suggestions from outside the requested area. `contactObfuscated` is `false` when public contact text was found, `true` when only a reply button was observed, and otherwise `null`. Contact extraction does not verify ownership or deliverability.

Craigslist may show a **Reply** button without publishing the seller's email address or phone number in the public posting. The Actor does not open that private reply flow, solve its verification challenge or reconstruct its relay address. In those cases `emails` and `phoneNumbers` correctly remain empty arrays; `replyToken` identifies the public reply link and is not a contact address.

This is the complete Dataset item from a real successful run:

```json
{
  "url": "https://www.craigslist.org/view/d/clinton-new-20uf-400v-motor-start-run/jcKfSpd4HtqMRBcrfaqHjX",
  "postId": "7926770440",
  "title": "NEW!!! 20uf 400V Motor Start run Capacitor",
  "price": 25.0,
  "currency": "USD",
  "region": "seattle",
  "categorySlug": "ela",
  "categoryLabel": "Electronics",
  "subcategorySlug": "ele",
  "subcategoryLabel": "electronics - by owner",
  "location": "South End of Whidbey",
  "neighborhood": null,
  "latitude": 47.9508,
  "longitude": -122.3916,
  "mapAccuracy": null,
  "postedAt": "2026-04-09T20:13:58-0700",
  "updatedAt": "2026-09-05T08:41:45-0700",
  "description": "*** if you are reading this the item is still available***\nWhat you see is what you get. I am assuming if you are reading this then you are familiar with what you are looking at so no other description should be needed.",
  "attributes": {},
  "imageUrls": [
    "https://images.craigslist.org/00d0d_9llB9E1MrRC_0oZ0t2_600x450.jpg",
    "https://images.craigslist.org/00h0h_jOekMWAiA3s_0ki0t2_600x450.jpg",
    "https://images.craigslist.org/00s0s_gMRdXUH4WJP_0bh0oN_600x450.jpg",
    "https://images.craigslist.org/01111_jy8jhXGnKU9_0k80eR_600x450.jpg"
  ],
  "hasImages": true,
  "phoneNumbers": [],
  "emails": [],
  "contactObfuscated": true,
  "replyToken": "sea/ele/7926770440",
  "sellerListingsUrl": null,
  "isDeleted": false,
  "isNearby": false,
  "detailsStatus": "ok",
  "sourceUrl": "https://www.craigslist.org/search/area/seattle?cat=ela&sort=date&query=20uf",
  "scrapedAt": "2026-09-05T18:15:35.875261+00:00"
}
```

### Pricing

Check the **Pricing** tab for current prices, plan discounts and spending limits before starting a run. The billable unit is one unique listing delivered to the Dataset. Empty searches, failed requests, discarded duplicates and run-summary records are not charged. A valid search listing can still be returned when its optional detail enrichment fails; check `detailsStatus` when evaluating these results.

### Related Actors

| Actor | Best for |
|---|---|
| [Built In Jobs Scraper | Salaries & Skills](https://apify.com/datascraperes/builtin-jobs-scraper) | Research technology jobs with employers, skills and published salary information. |
| [Fotocasa Spain Property Listings Scraper](https://apify.com/datascraperes/fotocasa-property-search-scraper) | Collect Spanish property listings with prices, rooms, photos and agency information. |

### Limits and data quality

Default memory is 256 MB, with a supported range of 256–512 MB.

Craigslist listings change while a run is in progress. Counts, ordering and availability can differ between requests. Seller-entered prices, condition and attributes are returned as published; a low price may describe a payment or deposit rather than the full purchase price. Keywords can match description text, so a matching title is not required.

Coordinates describe the location published by Craigslist and should not be treated as a verified street address. Search timestamps can differ from the original posting dates available in the full detail page. Image links are returned as supplied or as search-gallery images; their availability can change after extraction.

When Craigslist publishes a neighborhood label, it is returned in `neighborhood`. `mapAccuracy` is the source map precision value when present, and `sellerListingsUrl` is the public link to additional listings by the seller when Craigslist exposes it. These three fields are nullable and are not inferred when the source omits them.

The Actor collects public content without signing in. Email addresses are returned only when the seller publishes them in visible posting text, a public `mailto:` link or an obfuscated form such as `name [at] example [dot] com`. Contact information hidden behind Craigslist's reply flow remains unavailable. Failed searches are recorded in the summary; successful sources can still return results. If access is temporarily restricted, saved listings remain available and you can try again later. Long-running stability and maximum coverage depend on source availability.

The summary's `collectionComplete` field is true only when the requested listing limit or the end of every selected source has been reached without collection errors. A spending limit, failed source, unavailable detail or interrupted run leaves collection incomplete. Expected source failures can end the run without a failed execution, including when no listings could be collected. The final status and summary still identify the collection as incomplete. Invalid configuration, corrupt recovery data or unconfirmed delivery or billing remain critical stops. Resuming preserved run storage requires the same input settings; saved listings are checked before new results are added.

### Frequently asked questions

#### Does this work in the United States and Canada?

Yes. The region selector contains 44 US presets and six Canadian presets. The currency field distinguishes published USD and CAD prices when that information is available.

#### Can I mix searches and individual posting URLs?

Yes. Supply them as plain strings in `startUrls`. Existing URL filters take precedence over guided search fields, and deduplication applies across the entire run.

#### Can I collect listings without their descriptions?

Yes. Set `includeDetails` to `false` for search URLs. Search fields such as title, price, location, images and posting ID remain available. Individual posting URLs are always fetched as details.

#### Why are there fewer results than requested?

The requested maximum is a cap. Searches may contain fewer matches, duplicate postings, excluded nearby results or unavailable records. Access restrictions and the run's spending limit can also stop collection early.

#### Why are `emails` or `phoneNumbers` empty?

Those fields contain only contact information that the seller publishes in the visible description, a public `mailto:` link or an obfuscated text form. Craigslist often keeps contact details behind its Reply flow, which may require an interactive verification challenge. This Actor leaves that contact hidden and returns empty arrays instead of guessing or exposing a relay token.

### Responsible use

Use the data for lawful purposes and comply with applicable Craigslist terms and privacy requirements. Publicly visible contact information should not be treated as permission for unsolicited messaging. Verify listing details directly before making purchasing, housing or employment decisions.

### Support

Open an issue in the Actor's **Issues** tab with your run ID, a reproducible input and a description of the expected result. Do not include account credentials or other secrets.
See the [Craigslist Scraper web guide, API examples and sample dataset](https://github.com/datacrawler-edu/craigslist-scraper-python) for no-code instructions, Python, JavaScript and cURL examples, and sanitized output files.

# Actor input Schema

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

Optional Craigslist search, category or posting URLs. Use one URL per line, for example https://newyork.craigslist.org/search/sss?query=bike or a direct /view/ posting URL. URL filters are preserved and take precedence over region, category, keyword and other guided filters. Leave empty to build a search from the fields below. Maximum 100 URLs.

## `region` (type: `string`):

Select the Craigslist area where the search runs. Example: newyork searches New York City; toronto searches Toronto, Canada. This setting is ignored when startUrls contains a URL.

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

Choose the top-level Craigslist category to search. Use the code that matches the category: sss = For sale; cta = Cars & trucks; ela = Electronics; fua = Furniture; apa = Apartments & houses; roo = Rooms & shares; sub = Sublets & temporary; jjj = Jobs; ggg = Gigs; bbb = Services; ccc = Community; rrr = Resumes; eee = Events. Example: select cta to collect vehicle listings or jjj to collect jobs. Use startUrls when you need a specific subcategory URL.

## `searchTerm` (type: `string`):

Optional keyword or phrase sent to Craigslist's search filter. Example: enter electric bike to find listings matching those words. Leave empty to collect the newest listings without a keyword. Maximum 500 characters.

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

Optional lower bound for the asking price, expressed in the listing region's currency (USD or CAD). Example: 500 returns listings priced at 500 or more. Leave empty when price filtering does not apply.

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

Optional upper bound for the asking price, expressed in the listing region's currency (USD or CAD). Example: 2500 returns listings priced up to 2,500. Leave empty when price filtering does not apply; it must be greater than or equal to Minimum price.

## `condition` (type: `string`):

Filter by the condition selected by the seller in supported for-sale categories. Example: choose excellent to keep only listings marked excellent. any leaves all conditions unchanged.

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

When enabled, keep only search results that include at least one Craigslist image. Example: true is useful for photo inventory research; false keeps listings with or without images.

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

When enabled, apply Craigslist's posted-today filter. Example: true returns listings posted during the current day according to Craigslist; false includes older listings.

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

Choose the order within each search. date returns newest first (default), rel uses Craigslist relevance, priceasc sorts from lowest to highest price, and pricedsc sorts from highest to lowest. Sorting already present in a startUrl takes precedence.

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

When true, fetch each posting page to add the published description, category attributes, dates, map data, gallery images and visible contact text. Example: true gives richer records; false is faster and returns search-listing fields only. Direct posting URLs always receive details.

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

Maximum number of unique listings written across all supplied sources. Example: 50 stops after 50 rows; 0 enables the safety cap of up to 100,000 rows. The value is global for the whole run, not per URL.

## `includeNearby` (type: `boolean`):

When true, include nearby-area suggestions returned by Craigslist in addition to the selected region. Example: true can broaden a city search; those rows are marked isNearby=true. false keeps only the requested area.

## Actor input object example

```json
{
  "startUrls": [],
  "region": "newyork",
  "category": "sss",
  "searchTerm": "",
  "priceMin": 0,
  "priceMax": 1000000000,
  "condition": "any",
  "hasImage": false,
  "postedToday": false,
  "sort": "date",
  "includeDetails": true,
  "maxResults": 20,
  "includeNearby": false
}
```

# Actor output Schema

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

No description

## `summary` (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 = {
    "startUrls": [],
    "region": "newyork",
    "category": "sss",
    "searchTerm": "",
    "priceMin": 0,
    "priceMax": 1000000000,
    "condition": "any",
    "hasImage": false,
    "postedToday": false,
    "sort": "date",
    "includeDetails": true,
    "maxResults": 20,
    "includeNearby": false
};

// Run the Actor and wait for it to finish
const run = await client.actor("datascraperes/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 = {
    "startUrls": [],
    "region": "newyork",
    "category": "sss",
    "searchTerm": "",
    "priceMin": 0,
    "priceMax": 1000000000,
    "condition": "any",
    "hasImage": False,
    "postedToday": False,
    "sort": "date",
    "includeDetails": True,
    "maxResults": 20,
    "includeNearby": False,
}

# Run the Actor and wait for it to finish
run = client.actor("datascraperes/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 '{
  "startUrls": [],
  "region": "newyork",
  "category": "sss",
  "searchTerm": "",
  "priceMin": 0,
  "priceMax": 1000000000,
  "condition": "any",
  "hasImage": false,
  "postedToday": false,
  "sort": "date",
  "includeDetails": true,
  "maxResults": 20,
  "includeNearby": false
}' |
apify call datascraperes/craigslist-scraper --silent --output-dataset

```

## MCP server setup

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