# Craigslist Scraper - Listings, Prices & Contact by City (`santhej/craigslist-scraper`) Actor

Scrape Craigslist listings from any city: title, price, category, neighborhood, coordinates, images and direct listing URL. Search any keyword across for-sale, housing, jobs, gigs and more. 360 results per request, no API key.

- **URL**: https://apify.com/santhej/craigslist-scraper.md
- **Developed by:** [Santhej Kallada](https://apify.com/santhej) (community)
- **Categories:** E-commerce, Lead generation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: 5.00 out of 5 stars

## Pricing

Pay per event

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?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## Craigslist Scraper — Listings, Prices & Location by City

**Pull Craigslist listings from any city in seconds: title, price, category, neighbourhood, GPS coordinates, every photo and the direct listing URL. Search any keyword across for-sale, housing, cars, jobs and gigs. 360 listings per request, no API key.**

Most Craigslist scrapers open one page per listing, which makes a 360-result search 361 HTTP requests and slow enough that you notice. This one reads the same structured feed the Craigslist site itself uses, so **a full page of 360 listings arrives in a single request in about four seconds** — and you pay a third of what the usual per-result price comes to.

### What you get per listing

| Field | What it tells you |
|---|---|
| `title` | The listing headline |
| `price` | Price as a number, ready to sort and filter (`null` where the posting has no price) |
| `price_text` | Price exactly as Craigslist displays it, e.g. `$8,995` |
| `url` | Direct link to the listing — canonical form, resolves with no redirect |
| `posting_id` | Craigslist's numeric posting id, stable for de-duplication |
| `category` / `category_code` | Resolved section, e.g. `bicycles - by owner` / `bik` |
| `city` / `area_id` | The Craigslist city the listing belongs to |
| `subarea` | Metro sub-region, e.g. `brk` for Brooklyn |
| `neighborhood` | Neighbourhood — Craigslist's own where it has one, otherwise the seller's own wording |
| `latitude` / `longitude` | Map coordinates for the listing |
| `image_count` / `image_urls` | Every photo on the posting, as direct full-size image links |
| `posted_at` | When the listing was posted or last refreshed |
| `bedrooms` / `sqft` | Housing listings |
| `odometer` | Vehicle listings |
| `compensation` / `employer` / `job_title` | Job listings |
| `search_term` | Which of your search terms produced this row |

A run summary row is also written, with searches run, postings returned, how many exist in total, errors and the billing breakdown.

### Use cases

- **Resale and arbitrage** — watch a category across several cities and catch underpriced items the moment they appear.
- **Local market pricing** — pull hundreds of comparable listings and get a real price distribution instead of a guess.
- **Real-estate research** — rents by neighbourhood with bedrooms, square footage and coordinates attached.
- **Vehicle sourcing** — price against odometer across a whole metro in one run.
- **Lead generation** — find people actively selling, hiring or advertising services in a specific area.
- **Recruitment intel** — who is hiring in a market, for what role, at what advertised pay.

### Pricing

Pay per event. No monthly fee, no setup fee, no minimum.

| Event | Price |
|---|---|
| Actor start | $0.001 per run |
| Posting | **$0.0005 per listing — $0.50 per 1,000** |

**You are charged only for listings actually returned.** A search that finds nothing, or fails, costs you nothing beyond the start event.

Worked example: a full 360-listing search costs `$0.001 + 360 × $0.0005` = **$0.181**. Three cities at 360 listings each = **$0.541**. Ten thousand listings = **$5.00**.

### Input example

```json
{
  "searchTerms": ["bike", "road bike"],
  "city": "newyork",
  "category": "sss",
  "maxResultsPerSearch": 360
}
```

`city` takes the subdomain from the site's address — `newyork`, `sfbay`, `losangeles`, `chicago`. Plain names like `new york` and pasted Craigslist URLs work too.

### Output example

```json
{
  "record_type": "posting",
  "posting_id": 7949427273,
  "url": "https://www.craigslist.org/view/d/brooklyn-tony-hawk-20bmx-20wheels/1Z6ehVThLqLQmKFRpAdj8m",
  "title": "Tony Hawk 20”BMX 20”wheels",
  "price": 50,
  "price_text": "$50",
  "category": "bicycles - by owner",
  "category_code": "bik",
  "city": "newyork",
  "area_id": 3,
  "subarea": "brk",
  "neighborhood": "Brooklyn",
  "latitude": 40.5927,
  "longitude": -73.9269,
  "image_count": 5,
  "image_urls": [
    "https://images.craigslist.org/00B0B_lLO1Bb4FVuv_0t20CI_600x450.jpg",
    "https://images.craigslist.org/00w0w_jWJuinNJrs5_0t20CI_600x450.jpg"
  ],
  "posted_at": "2026-08-29T10:05:10.000Z",
  "search_term": "bike",
  "scraped_at": "2026-08-29T10:19:14.706Z"
}
```

### FAQ

**Do I need an API key or a proxy?** Neither. The Actor reaches the source directly, which is why it is fast and cheap to run. A proxy option is there if you specifically need traffic to originate from a given country, but it is off by default and you do not need it.

**How many listings can I get?** One search request returns up to 360. Ask for more and the Actor automatically splits the search across the city's neighbourhoods and across price bands to collect additional unique listings — up to 3,000 per search term. Every listing is de-duplicated by posting id, so you never pay for the same row twice.

**Why did I get fewer than I asked for?** Because that is all Craigslist has. The `total_available` figure in the run summary tells you how many exist for your search, and you are only charged for rows actually delivered.

**Which cities are supported?** All of them — every Craigslist city worldwide is resolved automatically from the site's own directory, so `paris`, `tokyo` and `berlin` work exactly like `newyork`.

**What categories can I search?** All for sale, cars & trucks, apartments & housing, jobs, gigs, electronics, furniture and garage sales. Leave the search term empty to browse a whole category.

**What exactly is `posted_at`?** The time the listing was posted or last refreshed. Craigslist bumps a listing's timestamp when a seller renews it, and that renewed time is what the search feed carries.

**Can I export it?** JSON, CSV, Excel, or straight into n8n, Make or Zapier via the Apify API.

### Related actors

- [Similarweb Scraper](https://apify.com/santhej/similarweb-traffic-scraper) — traffic, rank and AI-referral data for any website.
- [Google Maps Business Scraper](https://apify.com/santhej/local-rank-grid-tracker) — local business listings and rankings by map grid.

***

*Tags: craigslist, craigslist scraper, craigslist api, classifieds scraper, listings scraper, marketplace scraper, used cars, apartments for rent, rental listings, job listings, price monitoring, resale arbitrage, local marketplace, lead generation, real estate data, ecommerce data*

# Actor input Schema

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

Keywords to search for, one per line. Each term is searched separately. Leave a single empty entry to browse the whole category without a keyword.

## `city` (type: `string`):

The Craigslist city to search. Use the subdomain from the site's address — newyork, sfbay, losangeles, chicago, seattle. Plain names ('new york') and pasted URLs also work.

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

Which Craigslist section to search.

## `maxResultsPerSearch` (type: `integer`):

How many postings to return per search term. One request returns 360; asking for more automatically splits the search across neighbourhoods and price bands to gather additional unique postings.

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

Optional. This Actor reaches the source directly and does not need a proxy, so leaving this off is both faster and free. Enable it only if you need traffic to originate from a specific country.

## Actor input object example

```json
{
  "searchTerms": [
    "bike"
  ],
  "city": "newyork",
  "category": "sss",
  "maxResultsPerSearch": 360,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

## `dataset` (type: `string`):

One row per posting with title, price, category, neighbourhood, coordinates, images and the direct listing URL.

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

Searches run, postings returned, total available, errors and the billing breakdown for the run.

# 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": [
        "bike"
    ],
    "city": "newyork",
    "category": "sss",
    "maxResultsPerSearch": 360,
    "proxyConfiguration": {
        "useApifyProxy": false
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("santhej/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": ["bike"],
    "city": "newyork",
    "category": "sss",
    "maxResultsPerSearch": 360,
    "proxyConfiguration": { "useApifyProxy": False },
}

# Run the Actor and wait for it to finish
run = client.actor("santhej/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": [
    "bike"
  ],
  "city": "newyork",
  "category": "sss",
  "maxResultsPerSearch": 360,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}' |
apify call santhej/craigslist-scraper --silent --output-dataset

```

## MCP server setup

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