CarGurus Vehicle Listings Scraper avatar

CarGurus Vehicle Listings Scraper

Pricing

Pay per event

Go to Apify Store
CarGurus Vehicle Listings Scraper

CarGurus Vehicle Listings Scraper

Extract public CarGurus US vehicle listings with VIN, price, IMV, mileage, deal rating, days on market, dealer details, and search context.

Pricing

Pay per event

Rating

0.0

(0)

Developer

Stas Persiianenko

Stas Persiianenko

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

a day ago

Last modified

Categories

Share

Extract public CarGurus US search inventory into structured vehicle records. Get VIN, make, model, year, price, CarGurus Instant Market Value (IMV), mileage, deal rating, days on market, dealer details, colors, features, and search context.

The Actor accepts the search URLs you already use on CarGurus. It follows result pages, removes duplicate listing IDs, and saves one dataset row per vehicle. No CarGurus login is required for the supported public search-results scope.

What this Actor does

  1. Validates one or more cargurus.com US search URLs.
  2. Retrieves the public server-rendered search state.
  3. Extracts listing, vehicle, pricing, deal, dealer, and inventory fields.
  4. Follows search pagination until the result set ends or maxItems is reached.
  5. Deduplicates listings across pages and across all supplied URLs.
  6. Charges only for records accepted into the default dataset.

This version focuses on fields available in search results. It does not require a second request to every detail page. That keeps runs lighter and avoids claiming fields that were not proven for this scope.

Who is it for

Vehicle dealers

Monitor competing inventory, compare advertised prices with CarGurus IMV, and identify vehicles carrying a strong or weak deal rating.

Automotive analysts

Build repeatable samples by ZIP code, make, model, radius, price range, condition, or other filters encoded in a CarGurus search URL.

Valuation and marketplace teams

Track price, mileage, days on market, and price-to-IMV differences without manually copying search results.

Inventory and pricing monitors

Schedule the same search daily or weekly and load the dataset into a warehouse, spreadsheet, webhook, or change-detection pipeline.

Why use this Actor

  • Search-URL input: configure the exact query in CarGurus and paste its URL.
  • Useful automotive fields: VIN, stock number, IMV, deal score, dealer, and vehicle attributes.
  • Pagination: collect more than the first search page.
  • Global deduplication: overlapping searches do not create duplicate listing IDs in one run.
  • Typed output: every saved row follows the dataset schema.
  • Lightweight route: the default workflow does not download listing images or render a full browser.
  • Explicit failures: a blocked or changed page is reported as an error, not silently returned as an empty result.

Extracted data

GroupFields
IdentitylistingId, listingUrl, vin, stockNumber
Vehicletitle, make, model, year, trim, bodyType, condition
Price and valueprice, totalPrice, carGurusImv, priceDifference
Market signalsdealRating, dealScore, daysOnMarket, distanceMiles
Specificationsmileage, fuelType, drivetrain, transmission, engine
AppearanceexteriorColor, interiorColor, features, imageUrl, imageCount
DealerdealerName, dealerId, dealerPhone, dealerCity, dealerRegion, dealerPostalCode
Search contextsearchUrl, searchPage, totalSearchResults, scrapedAt

Fields are nullable because individual sellers and listings do not always provide every attribute. price and IMV values are numeric US-dollar amounts when CarGurus supplies them. mileage and distanceMiles use miles for the supported US scope.

Pricing

The Actor uses pay per event (PPE). The declared one-time start fee is $0.005 per run. The per-listing fee is tiered by Apify plan:

Apify planPrice per saved listing
Free$0.000039446
Bronze$0.000034301
Silver$0.000026755
Gold$0.000020581
Platinum$0.000013720
Diamond$0.000010000

A duplicate, rejected record, blocked response, or empty search is not charged as an item. Normal Apify spending limits can cap a run.

Cost examples

At Bronze pricing:

  • 10 saved listings: about $0.00534 including the start fee.
  • 100 saved listings: about $0.00843 including the start fee.
  • 1,000 saved listings: about $0.03930 including the start fee.

At Free-plan pricing, 100 saved listings cost about $0.00894 including the start fee. Actual charges follow the active pricing displayed by Apify when the run starts.

Getting started

  1. Open CarGurus.com and create a US vehicle search.
  2. Apply the location, make, model, price, radius, or condition filters you need.
  3. Copy the resulting URL from the browser.
  4. Open this Actor's Input tab.
  5. Add the URL under CarGurus search URLs.
  6. Set Maximum listings to a small value for the first run.
  7. Leave proxy disabled unless you have a specific fallback requirement.
  8. Click Start.
  9. Open the Vehicle listings dataset view when the run finishes.
  10. Export the results as JSON, CSV, Excel, XML, or another Apify-supported format.

Input parameters

startUrls

Required array of one or more public HTTPS CarGurus US search URLs. Each URL must use cargurus.com and a path beginning with /Cars/. The Actor normalizes cargurus.com to www.cargurus.com. A pasted page cursor is removed so each search starts from page one. All other search-filter query parameters are preserved.

Example:

{
"startUrls": [
{
"url": "https://www.cargurus.com/Cars/l-Used-Toyota-Camry-Raleigh-d292_L25152"
}
],
"maxItems": 20,
"proxyConfiguration": {
"useApifyProxy": false
}
}

maxItems

Optional integer from 1 to 10,000. The default is 100. The limit applies globally across every URL, page, and unique listing in the run. Pagination stops as soon as this number of rows has been saved.

proxyConfiguration

Optional Apify proxy configuration. The Actor uses a public lightweight search-data surface by default. If configured, the same sticky proxy session is kept for the pages of one search URL and is also available to the direct CarGurus fallback. Proxy traffic can add platform cost.

Output example

The following abbreviated object reflects the current search-result output shape:

{
"listingId": "450352573",
"listingUrl": "https://www.cargurus.com/details/450352573",
"title": "2025 Toyota Camry",
"vin": "4T1DAACK3SU620978",
"make": "Toyota",
"model": "Camry",
"year": 2025,
"trim": "SE FWD",
"bodyType": "Sedan",
"price": 32292,
"totalPrice": 32292,
"carGurusImv": 30837,
"priceDifference": -1455,
"mileage": 18329,
"condition": "CPO",
"daysOnMarket": 45,
"dealRating": "FAIR_PRICE",
"dealScore": 2.6836534,
"stockNumber": "AB63325",
"features": ["Adaptive Cruise Control", "Bluetooth", "Backup Camera"],
"dealerName": "Capital Ford",
"dealerCity": "Raleigh",
"dealerRegion": "NC",
"searchPage": 1,
"totalSearchResults": 339,
"scrapedAt": "2026-07-25T00:00:00.000Z"
}

Search inventory changes continuously. The same query may return different IDs, ordering, prices, and totals later.

Pagination and deduplication

The Actor reads CarGurus's reported page number and page count. It increments the page query parameter and stops at the last page, an empty listing page, or maxItems.

The stable deduplication key is listingId. If two supplied search URLs overlap, the first accepted occurrence is saved and later occurrences are skipped without an additional item charge.

Sponsored, priority, featured, and standard listing tiles are normalized into the same output record when they contain a listing ID. Non-listing UI tiles are ignored.

Reliability and retry behavior

Temporary network failures, HTTP 429 responses, and temporary server errors receive bounded retries with exponential backoff and jitter. Deterministic blocked responses are not retried repeatedly on the same route.

The Actor verifies all of the following before parsing:

  • HTTP status is successful.
  • The response is HTML.
  • CarGurus embedded Remix state is present.
  • The state contains a route with search listing tiles.

If those checks fail, the run exits non-zero with a concise diagnostic. This prevents a challenge page from looking like a valid zero-result search.

No-result searches

A legitimate search can report zero matching listings. In that case the run succeeds and the dataset remains empty. This differs from a blocked or unrecognized page, which fails explicitly.

To verify an empty result, open the same search URL and check its filters. Overly narrow price, radius, model, or condition filters commonly produce no inventory.

Workflow examples

Daily dealer inventory watch

Schedule a ZIP/make/model URL every morning. Store each run's dataset ID and compare listing IDs, price, mileage, and days on market with the prior run.

Price-to-IMV analysis

Load price, carGurusImv, priceDifference, dealRating, and dealScore into a spreadsheet or warehouse. Group by year, trim, mileage band, or dealer region.

Dealer inventory enrichment

Join vin or stockNumber with an internal inventory table. Use dealerName, location, and listing URL for review queues. Do not treat public phone numbers as consent for unsolicited contact.

Regional supply comparison

Provide several comparable search URLs for different ZIP-code markets. Use searchUrl as the source dimension and deduplicate overlapping vehicles automatically.

API: cURL

Start a run and wait for completion:

curl -X POST \
"https://api.apify.com/v2/acts/automation-lab~cargurus-vehicle-listings-scraper/run-sync-get-dataset-items?token=$APIFY_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"startUrls": [{"url": "https://www.cargurus.com/Cars/l-Used-Toyota-Camry-Raleigh-d292_L25152"}],
"maxItems": 20
}'

For larger runs, use the asynchronous /runs endpoint, then read items from the run's default dataset. Keep tokens in environment variables rather than source code.

API: JavaScript

import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const input = {
startUrls: [{
url: 'https://www.cargurus.com/Cars/l-Used-Toyota-Camry-Raleigh-d292_L25152',
}],
maxItems: 100,
};
const run = await client.actor('automation-lab/cargurus-vehicle-listings-scraper').call(input);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items);

Use client.actor(...).start(input) when your application should not wait synchronously.

API: Python

import os
from apify_client import ApifyClient
client = ApifyClient(os.environ["APIFY_TOKEN"])
run = client.actor("automation-lab/cargurus-vehicle-listings-scraper").call(
run_input={
"startUrls": [
{
"url": "https://www.cargurus.com/Cars/l-Used-Toyota-Camry-Raleigh-d292_L25152"
}
],
"maxItems": 100,
}
)
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
print(item)

MCP integration

Claude Code

Add the Actor to Claude Code through Apify MCP:

claude mcp add --transport http apify \
"https://mcp.apify.com?tools=automation-lab/cargurus-vehicle-listings-scraper"

Claude Desktop

Add the following remote server in Claude Desktop's MCP configuration:

{
"mcpServers": {
"apify": {
"url": "https://mcp.apify.com?tools=automation-lab/cargurus-vehicle-listings-scraper"
}
}
}

Cursor

Open Cursor Settings → Tools & MCP, add a remote server named apify, and use the same https://mcp.apify.com?tools=automation-lab/cargurus-vehicle-listings-scraper URL.

VS Code

Add an HTTP MCP server named apify in the VS Code MCP settings with the same Actor-specific URL shown above.

Example prompts for MCP usage:

  • “Using MCP, run the CarGurus scraper for this Raleigh Camry search and return 25 listings.”
  • “Use the MCP CarGurus tool to compare price with IMV and rank the strongest deals.”
  • “Through MCP, group these vehicle listings by dealer and compute median mileage.”

Your MCP client still needs authorization to run paid Apify Actors.

Integrations and exports

Apify datasets can be exported to JSON, CSV, Excel, XML, RSS, or HTML. Use schedules for recurring monitoring. Use webhooks to notify a service when a run succeeds or fails. Use Make, Zapier, Google Sheets, or your own API client for downstream automation.

For longitudinal monitoring, persist the run date and dataset ID externally. The Actor's default dataset is run-specific and does not merge historical snapshots.

Limits and responsible scaling

  • V1 supports public CarGurus US search URLs only.
  • Canadian and UK domains are not accepted.
  • Detail-page-only fields are outside the current contract.
  • Search ranking and available inventory can change between requests.
  • CarGurus can change its embedded state or anti-bot behavior.
  • Very broad searches can have many pages; use maxItems and schedules responsibly.
  • Optional proxy settings may increase transfer cost.
  • The Actor does not download image files; it returns the primary image URL.
  • A saved phone number is public source data, not proof of marketing consent.

You are responsible for ensuring that your collection and use comply with CarGurus terms, applicable laws, contractual duties, and data-protection rules. Collect only the fields and volume needed for a legitimate purpose.

Public availability does not remove obligations around personal data, database rights, automated access, retention, or unsolicited communications. Do not use output for discrimination, deception, harassment, or prohibited outreach. When unsure, obtain legal advice for your jurisdiction and workflow.

Troubleshooting

“Only public CarGurus US search URLs are supported”

Confirm the URL begins with https://www.cargurus.com/Cars/. Do not use a vehicle detail URL, Canadian domain, UK domain, shortened URL, or third-party redirect.

The run succeeds with zero rows

Open the same search and check whether its filters currently return inventory. A price ceiling or narrow radius can validly produce zero listings.

The run fails with an embedded-state error

The source returned a blocked, incomplete, or changed page. Retry later, reduce parallel scheduled runs, or configure an appropriate Apify proxy. If the error persists, include the run URL and redacted input in a support report.

The dataset has fewer rows than the search total

maxItems is a hard global cap. Overlapping pages or URLs are deduplicated by listing ID. The source total can also change while pagination is in progress.

A field is missing on some rows

CarGurus and individual sellers do not provide every field for every listing. Use null-safe downstream logic and key joins on listingId or vin when available.

These Actors have separate source contracts and pricing. They are not required by this Actor.

FAQ

Does this Actor require a CarGurus account?

No. The supported V1 workflow uses public US search-result data and does not log in.

Can I pass several search URLs?

Yes. Results share one global maxItems limit and one listing-ID deduplication set.

Does it scrape every vehicle detail page?

No. V1 intentionally emits fields proven in search inventory. This makes the route lighter and keeps the output contract honest.

Can I schedule it?

Yes. Scheduling is a core use case for dealer inventory, pricing, and days-on-market monitoring.

Are prices guaranteed to be current?

No. Output reflects the source at extraction time. Always use scrapedAt and re-run searches when freshness matters.

Will an empty search incur item charges?

No item event is charged when no listing record is saved. The one-time start event still applies.

How are duplicates handled?

The first occurrence of a listing ID is saved. Later occurrences in the same run are skipped without another item charge.

Can I scrape Canada or the UK?

Not in V1. Use an Actor whose documented source contract covers that domain.