# CarGurus Scraper - Used Car Listings & Dealer Leads (`scrapesage/cargurus-scraper`) Actor

Scrape CarGurus used-car listings & dealer leads by location or search URL: VIN, price, Instant Market Value & deal rating, mileage, specs, photos, plus dealer name, phone & address. Optional listing details, dealer leads & monitoring. No login or API key.

- **URL**: https://apify.com/scrapesage/cargurus-scraper.md
- **Developed by:** [Scrape Sage](https://apify.com/scrapesage) (community)
- **Categories:** E-commerce, Lead generation, Automation
- **Stats:** 3 total users, 2 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.00 / 1,000 car listing scrapeds

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/platform/actors/running/actors-in-store#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

## CarGurus Scraper — US Used Car Listings, Deal Ratings & Dealer Leads

Scrape **[CarGurus](https://www.cargurus.com)** — the largest US used-car marketplace — into clean, structured data. Pull every search result with **year / make / model / trim, asking price, the CarGurus Instant Market Value & deal rating, mileage, VIN, body style, drivetrain, engine, MPG, colours, photos, and days on market** — plus the selling **dealer's name, phone and full address** as a ready-to-use B2B lead. Add full **listing-detail** records (options, seller description, vehicle history, price history, all photos) and deduplicated **dealer leads** with one toggle. Built-in **monitor mode** returns only new listings and price drops between runs.

No API key, no login, no browser automation — fast HTTP straight to the source, with a **0–100 lead score** on every record.

### Why this CarGurus scraper?

Most car-listing scrapers give you a name and a price for a handful of cars, then break on the next site update. This actor ships the **full CarGurus record** with everything a pricing model, an inventory feed, or a dealer-prospecting list actually needs:

| Data | Typical car scrapers | This actor |
|---|---|---|
| Year / make / model / trim / body type | ✅ | ✅ |
| Asking price + **MSRP** + price-with-fees | partial | ✅ |
| **CarGurus Instant Market Value** + **deal rating** (Great/Good/Fair/High) + deal score | ❌ | ✅ |
| Mileage, **VIN**, condition (new / used / CPO) | partial | ✅ |
| Drivetrain, engine, transmission, MPG, exterior/interior colour | ❌ | ✅ |
| Days on market, stock number, photos | partial | ✅ |
| **Vehicle history** — accidents, owners, salvage/lemon/frame, fleet use *(opt-in detail)* | ❌ | ✅ |
| **Price history**, full options & seller description *(opt-in detail)* | ❌ | ✅ |
| Selling **dealer name, phone, full street address, city/state/ZIP** | partial | ✅ |
| **Dealer leads** (deduped, with rating & lead score) | ❌ | ✅ |
| **Monitor mode** — only new listings & price drops | ❌ | ✅ |
| Lead score (0–100) | ❌ | ✅ |

### Who buys CarGurus data?

- **Car dealers & dealer groups** — track competitor pricing, deal ratings and days-on-lot on the exact year/make/model you stock.
- **Automotive marketplaces, pricing & valuation tools** — feed live asking prices, market values and mileage into your model.
- **Dealer-facing SaaS, ad-tech, CRM & DMS vendors** — build prospect lists of dealers by market, inventory and rating, with phone and address.
- **Lenders, F\&I, insurers & warranty providers** — size markets and reach dealers and shoppers.
- **Wholesalers, flippers & exporters** — surface under-priced cars and recent price drops fast using the CarGurus deal rating.
- **Researchers & analysts** — used-car price trends, inventory and depreciation by make/model/region.

### How to use

1. [Sign up for Apify](https://console.apify.com/sign-up) — the free plan is enough to try this actor.
2. Open the **CarGurus Scraper**, then either enter **ZIP codes** (with a search radius) or paste **CarGurus search URLs** built with your own make/model/price filters, and click **Start**.
3. Watch results stream into the dataset table.
4. **Export** as JSON, CSV, Excel, XML, or RSS — or pull results programmatically via the [Apify API](https://docs.apify.com/api/v2).

### Input

The easiest way to run an exact search is to set your filters on cargurus.com (make, model, price, year, mileage) and paste the resulting URL into **Search URLs**. Or search by location with **ZIP codes**:

```json
{
    "zipCodes": ["90001", "78704"],
    "distance": 50,
    "maxResults": 100,
    "includeListingDetails": false,
    "includeDealerLeads": true,
    "dealRatingFilter": ["GREAT_PRICE", "GOOD_PRICE"],
    "makeFilter": ["Toyota", "Honda"],
    "maxMileage": 80000,
    "maxPrice": 30000,
    "withDealerPhoneOnly": true,
    "monitorMode": false
}
```

| Field | Type | Description |
|---|---|---|
| `zipCodes` | array | 5-digit US ZIP codes to search around. |
| `searchUrls` | array | Paste any CarGurus search-results URL (best for make/model & advanced filters). |
| `startUrls` | array | CarGurus search URLs **or** single `/details/<id>` listing URLs (auto-routed). |
| `distance` | integer | Search radius around each ZIP, in miles (default 50). |
| `sortBy` | string | `best_match`, `newest_listed`, `lowest_price`, `highest_price`, `lowest_mileage`, `best_deal` (honored best on pasted searchUrls). |
| `maxResults` | integer | Cap on listing records (default 100). |
| `maxPagesPerSearch` | integer | Result pages (24 listings each) to paginate per search (default 10). |
| `includeListingDetails` | boolean | Open each listing for options, seller description, vehicle & price history, all photos, safety features. |
| `includeDealerLeads` | boolean | Also output one deduplicated dealer record per dealership. |
| `conditionFilter` | string | `any` / `used` / `cpo` / `new`. |
| `dealRatingFilter` | array | Keep only listings with these CarGurus deal ratings. |
| `makeFilter` | array | Keep only these makes. |
| `minYear` / `maxYear` / `maxMileage` / `minPrice` / `maxPrice` | integer | Numeric filters (0 = off). |
| `withDealerPhoneOnly` | boolean | Only listings that carry a dealer phone (best for lead-gen). |
| `excludePrivateSellers` | boolean | Dealer listings only. |
| `monitorMode` | boolean | Emit only new & price-changed listings between runs. |
| `proxyConfiguration` | object | Defaults to Apify **Residential, US** (recommended). |

### Output

Each listing is one row tagged `type: "listing"` (dealer rows are tagged `type: "dealer"`). Example listing:

```json
{
  "type": "listing",
  "listingId": "449427865",
  "vin": "KL8CB6SA7LC408569",
  "url": "https://www.cargurus.com/details/449427865",
  "title": "2020 Chevrolet Spark",
  "make": "Chevrolet",
  "model": "Spark",
  "year": 2020,
  "trim": "LS FWD",
  "bodyType": "Hatchback",
  "condition": "Used",
  "price": 14195,
  "msrp": 14195,
  "marketValue": 15089,
  "priceVsMarket": 894,
  "dealRating": "GOOD_PRICE",
  "dealRatingLabel": "Good Price",
  "dealScore": 1.88,
  "mileage": 5489,
  "daysOnMarket": 25,
  "exteriorColor": "Caribbean Blue",
  "drivetrain": "Front-Wheel Drive",
  "engine": "1.4L I4",
  "transmission": "Continuously Variable Transmission",
  "fuelType": "Gasoline",
  "mpgCombined": 33.6,
  "features": ["Bluetooth", "Backup Camera", "Android Auto", "CarPlay"],
  "photoUrl": "https://static.cargurus.com/.../2020_chevrolet_spark.jpeg",
  "photoCount": 34,
  "dealerName": "Trust Auto",
  "dealerPhone": "(443) 205-7240",
  "dealerStreet": "1551 W Old Liberty Rd",
  "dealerCity": "Sykesville",
  "dealerState": "MD",
  "dealerZip": "21784",
  "dealerAddress": "1551 W Old Liberty Rd, Sykesville, MD, 21784",
  "leadScore": 74,
  "scrapedAt": "2026-06-23T21:00:00.000Z"
}
```

With `includeListingDetails` on, each listing also carries `description`, `options`, `allPhotos`, `priceHistory`, `accidentCount`, `ownerCount`, `salvageTitle`, `lemon`, `frameDamage`, `safetyFeatures`, and more.

### Monitor mode

Turn on **`monitorMode`** to remember every listing (and its price) across runs. The next run emits **only**:

- **new listings** (`monitorStatus: "new"`), and
- **price changes** (`monitorStatus: "price_drop"` / `"price_increase"`).

State is stored in a named key-value store (`monitorStoreName`, default `cargurus-scraper-monitor`) — use a different name per tracked search to keep histories separate. This is **orthogonal to [Apify Schedules](https://docs.apify.com/platform/schedules)**: the schedule decides *when* the run fires, monitor mode decides *what's new* — they work together without conflict.

### Automate & schedule

- **[Apify API](https://docs.apify.com/api/v2)** — start runs, fetch datasets, and manage schedules over REST.
- **[apify-client for JavaScript](https://docs.apify.com/api/client/js/)** and **[apify-client for Python](https://docs.apify.com/api/client/python/)** — official SDKs.
- **[Schedules](https://docs.apify.com/platform/schedules)** — run it hourly/daily/weekly to track new inventory and price drops in a market; perfect for pricing feeds and dealer-prospecting pipelines.
- **[Webhooks](https://docs.apify.com/platform/integrations/webhooks)** — trigger downstream actions (CRM import, Slack alert, repricing job) the moment a run finishes.

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

const client = new ApifyClient({ token: 'MY_APIFY_TOKEN' });

const run = await client.actor('scrapesage/cargurus-scraper').call({
    zipCodes: ['90001'],
    distance: 50,
    includeDealerLeads: true,
    maxResults: 100,
});

const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items);
```

### Integrate with any app

Connect the dataset to 5,000+ apps — no code required:

- **[Make](https://docs.apify.com/platform/integrations/make)** — multi-step automation scenarios.
- **[Zapier](https://docs.apify.com/platform/integrations/zapier)** — push new dealer leads straight into your CRM.
- **[Slack](https://docs.apify.com/platform/integrations/slack)** — get notified when a monitored search finds a new price drop.
- **[Google Drive / Sheets](https://docs.apify.com/platform/integrations/drive)** — auto-export every run to a spreadsheet.
- **[Airbyte](https://docs.apify.com/platform/integrations/airbyte)** — pipe results into your data warehouse.
- **[GitHub](https://docs.apify.com/platform/integrations/github)** — trigger runs from commits or releases.

### Use with AI assistants (MCP)

The output is clean, LLM-ready JSON. You can call this actor from Claude, ChatGPT, or any agent framework through the **[Apify MCP server](https://docs.apify.com/platform/integrations/mcp)** — ask your assistant to "find Toyota RAV4s near 90001 under $30k with a great deal rating and list the dealers" and let it run this scraper for you.

### Agent-ready: autonomous payments (x402 & Skyfire)

This actor is **agent-ready** — AI agents can discover it, run it, and **pay for it autonomously**, with no Apify account and no human in the loop. It uses [pay-per-event](https://docs.apify.com/platform/actors/publishing/monetize/pay-per-event) pricing and [limited permissions](https://docs.apify.com/platform/actors/development/permissions), so it qualifies for Apify's agentic-payment standards:

- **[x402](https://docs.apify.com/platform/integrations/x402)** — an open, HTTP-native payment protocol. Agents pay per run in USDC on the Base network directly through the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp) — no account, no API key.
- **[Skyfire](https://docs.apify.com/platform/integrations/skyfire)** — agent-to-service payments for fully autonomous AI-agent workflows.

Building an AI agent, MCP tool, or autonomous data pipeline? This scraper is ready to plug in and pay as it goes.

### More scrapers from scrapesage

- **[Cars.com Scraper](https://apify.com/scrapesage/cars-com-scraper)** — US new & used car listings, prices and dealer leads.
- **[AutoScout24 Scraper](https://apify.com/scrapesage/autoscout24-scraper)** — European used-car listings and dealers.
- **[AutoTrader Canada Scraper](https://apify.com/scrapesage/autotrader-ca-scraper)** — Canadian car listings and prices.
- **[SgCarMart Used Car Scraper](https://apify.com/scrapesage/sgcarmart-used-car-scraper)** — Singapore used-car listings.
- **[US Auto Dealer Scraper](https://apify.com/scrapesage/us-auto-dealer-scraper)** — licensed auto-dealer registry leads.
- **[Vehicle Manufacturer Leads](https://apify.com/scrapesage/vehicle-manufacturer-leads)** — manufacturer & importer firmographics.
- **[Google Maps Scraper](https://apify.com/scrapesage/google-maps-scraper)** — local business leads, emails and reviews.
- **[Website Contact Scraper](https://apify.com/scrapesage/website-contact-scraper)** — emails, phones and socials from any website.

### Tips

- **Make/model & advanced filters**: build the exact search on cargurus.com and paste the URL into `searchUrls` — CarGurus honors all its filters and sort there.
- **Best deals**: set `dealRatingFilter` to `["GREAT_PRICE", "GOOD_PRICE"]` to surface under-priced cars relative to the CarGurus Instant Market Value.
- **Cleanest dealer lists**: turn on `includeDealerLeads` + `withDealerPhoneOnly` to get a deduplicated, phone-verified dealer prospect list.
- **Recurring monitoring**: combine [Schedules](https://docs.apify.com/platform/schedules) with `monitorMode` to track only newly listed cars and price drops.

### FAQ

**Do I need a CarGurus API key or login?** No. This actor reads the public server-rendered search and listing pages — no key, no login, no browser.

**Can I search by make and model?** Yes — paste a CarGurus search URL with your make/model filters into `searchUrls`, or search by `zipCodes` and apply `makeFilter` / `minYear` / `maxPrice` / `maxMileage`.

**Why Residential proxy?** CarGurus serves clean pages over US residential IPs but challenges datacenter IPs. The default is Apify Residential (US); blocked requests retry automatically on a fresh IP.

**Does it get dealer phone numbers and addresses?** Yes — every listing carries the selling dealer's name, phone, full street address and city/state/ZIP. Turn on `includeDealerLeads` for a deduplicated dealer list.

**Can I export to Google Sheets, CSV, or Excel?** Yes — one click in the dataset view, or automatically on every run via the [Google Drive integration](https://docs.apify.com/platform/integrations/drive).

**How do I track new inventory and price drops?** Turn on `monitorMode` and create a [Schedule](https://docs.apify.com/platform/schedules); optionally add a [webhook](https://docs.apify.com/platform/integrations/webhooks) or [Zapier zap](https://docs.apify.com/platform/integrations/zapier) to push changes into your CRM as they appear.

***

*Not affiliated with or endorsed by CarGurus. Use responsibly and in accordance with applicable laws and terms. Scrapes only publicly available data.*

# Actor input Schema

## `zipCodes` (type: `array`):

5-digit US ZIP codes to search around. The actor pulls used-car listings within the search distance of each ZIP. One per row. (e.g. 90001, 78704.)

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

Paste any CarGurus search-results URL (build a search on cargurus.com with your make / model / price / year / mileage filters and copy the URL). The actor scrapes and paginates it. One per row. Use this for make/model and advanced filtering.

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

CarGurus URLs to scrape directly: search-results URLs (https://www.cargurus.com/Cars/...) or single listing detail URLs (https://www.cargurus.com/details/<id>). Auto-detected and routed. One per row.

## `distance` (type: `integer`):

Radius around each ZIP code to search, in miles.

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

Sort order. Note: CarGurus' location "shop" pages mostly use their own relevance order — sort options are honored best on pasted searchUrls.

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

Cap on car-listing records across the whole run. Searches paginate automatically until this cap or the page limit is reached. (Dealer-lead records do not count against this cap.)

## `maxPagesPerSearch` (type: `integer`):

How many result pages (24 listings each) to paginate through per ZIP / search URL before moving on.

## `includeListingDetails` (type: `boolean`):

Open each listing's detail page for the richest record: the seller's description, the full options list, vehicle history (accidents / owners / title), the full photo gallery, safety features and performance specs. One extra request per listing. Turn off for a faster, cheaper run (the listing record is already rich).

## `includeDealerLeads` (type: `boolean`):

Output one deduplicated dealer record (type `dealer`) per unique dealership seen — name, phone, full street address, city/state/zip and logo — alongside the car listings.

## `conditionFilter` (type: `string`):

Keep only listings of a given condition. (CarGurus location search returns used inventory; "new" relies on the listing flags.)

## `dealRatingFilter` (type: `array`):

Keep only listings with one of these CarGurus deal ratings. Leave empty for all.

## `makeFilter` (type: `array`):

Keep only listings of these makes (case-insensitive, e.g. Toyota, Ford). Leave empty for all.

## `minYear` (type: `integer`):

Keep only listings from this model year or newer. 0 = no filter.

## `maxYear` (type: `integer`):

Keep only listings from this model year or older. 0 = no filter.

## `maxMileage` (type: `integer`):

Keep only listings at or below this mileage. 0 = no filter.

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

Keep only listings priced at or above this. 0 = no filter.

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

Keep only listings priced at or below this. 0 = no filter.

## `withDealerPhoneOnly` (type: `boolean`):

Output only listings that have a dealer phone number (best for lead generation).

## `excludePrivateSellers` (type: `boolean`):

Output only dealer listings, skipping private (for-sale-by-owner) sellers.

## `deduplicateListings` (type: `boolean`):

Skip a listing already emitted earlier in the same run (CarGurus rotates inventory across pages).

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

Remember listings (and their last price) from previous runs and emit ONLY new listings and price-changed ones (each tagged monitorStatus = new / price\_drop / price\_increase). Pairs with Apify Schedules to track fresh inventory and price drops over time.

## `monitorStoreName` (type: `string`):

Named key-value store that holds the 'already seen' listing ids + prices for monitoring mode. Use a different name per tracked target/search to keep their histories separate.

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

Maximum parallel requests. Lower it for very large runs if you see transient blocks; raise it for speed.

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

Proxy settings. CarGurus serves clean pages over US residential IPs but Cloudflare-challenges datacenter IPs, so US Residential is the default and recommended setting. Blocked requests retry automatically on a fresh IP.

## Actor input object example

```json
{
  "zipCodes": [
    "90001"
  ],
  "distance": 50,
  "sortBy": "best_match",
  "maxResults": 100,
  "maxPagesPerSearch": 10,
  "includeListingDetails": false,
  "includeDealerLeads": false,
  "conditionFilter": "any",
  "dealRatingFilter": [],
  "minYear": 0,
  "maxYear": 0,
  "maxMileage": 0,
  "minPrice": 0,
  "maxPrice": 0,
  "withDealerPhoneOnly": false,
  "excludePrivateSellers": false,
  "deduplicateListings": true,
  "monitorMode": false,
  "monitorStoreName": "cargurus-scraper-monitor",
  "maxConcurrency": 8,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

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

All scraped records in the default dataset. Listing rows carry full vehicle data, the CarGurus Instant Market Value deal rating, dealer contact info and a lead score; dealer rows carry deduplicated dealership leads.

# 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 = {
    "zipCodes": [
        "90001"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("scrapesage/cargurus-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 = { "zipCodes": ["90001"] }

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

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

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

```

## CLI example

```bash
echo '{
  "zipCodes": [
    "90001"
  ]
}' |
apify call scrapesage/cargurus-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=scrapesage/cargurus-scraper",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

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