# AutoTrader Vehicle Listings Scraper (US & UK) (`usestring/autotrader-listings`) Actor

Scrape AutoTrader car listings from a ZIP code, a UK postcode or a search URL you built on the site. Rows carry year, make, model and trim, numeric price and mileage, VIN, body style, fuel and transmission, plus the selling dealer's name, city and state. Covers autotrader.com and autotrader.co.uk.

- **URL**: https://apify.com/usestring/autotrader-listings.md
- **Developed by:** [String](https://apify.com/usestring) (community)
- **Categories:** E-commerce, Business
- **Features:** Limited permissions
- **Stats:** 3 total users, 1 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.50 / 1,000 results

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

### What does the AutoTrader Vehicle Listings Scraper do?

Hand it a ZIP code, a UK postcode, or a search URL you built on AutoTrader itself, and it returns the
vehicles from that search as structured rows. Year, make, model and trim arrive in separate columns.
Price and mileage arrive as numbers. US rows also carry the VIN, the body style, the fuel type, the
gearbox, and the dealer's name with city and state.

The Actor covers two sites: `autotrader.com` in the United States and `autotrader.co.uk` in the
United Kingdom. Pick one with the `market` field. Both are read as a logged-out visitor, with no
account, no login and no cookies.

- Up to 100 US listings from a single search, which is the most one autotrader.com results page
  serves
- `price` is `43413` and `mileage` is `126431`, so filtering and averaging need no string work
- Paid spotlight and boost placements are dropped from US results, so a row answers your search
  rather than someone's ad budget
- Every row records the search URL it came from and when the run started
- A search that fails is written into the run's `SUMMARY` with its error, and a run where every
  search failed exits as a failure rather than reporting success on an empty dataset

### What data does it extract?

| Field | Type | Description |
| --- | --- | --- |
| `listingId` | string | AutoTrader's own listing ID. Stable across runs, use it as your key |
| `title` | string | e.g. `"New 2026 Hyundai Santa Fe SEL"` |
| `year` | number | Model year, e.g. `2026` |
| `make` | string | e.g. `Hyundai` |
| `model` | string | e.g. `Santa Fe` |
| `trim` | string | e.g. `SEL`. On UK rows this is the listing's subtitle |
| `price` | number | Numeric price, e.g. `43413`. UK prices include fees |
| `priceText` | string | The formatted price, or the dealer's own label when no price is published |
| `mileage` | number | Numeric odometer reading, e.g. `126431` |
| `bodyStyle` | string | e.g. `Sport Utility`. US only |
| `fuelType` | string | e.g. `Gasoline`. US only |
| `transmission` | string | e.g. `Automatic`. US only |
| `vin` | string | 17-character VIN. US only |
| `dealerName` | string | The selling dealer |
| `city` | string | Dealer city in the US, vehicle location in the UK |
| `state` | string | US only |
| `detailUrl` | string | Link to the listing page on AutoTrader |
| `sourceUrl` | string | The search this row came from |
| `collectedAt` | string | ISO timestamp, set once per run |

Fields a market does not publish come back as `null`, never as an empty string or a guess.

### Why scrape AutoTrader?

Used-car pricing is local and it moves weekly, which is exactly the kind of thing a spreadsheet
pulled by hand cannot keep up with.

- **Price a vehicle against its real market.** Pull every 2019-2022 listing of one model within 50
  miles and you have the actual asking-price curve by mileage band, not a national average from a
  valuation site.
- **Watch a dealer's lot.** Re-run the same search on a schedule, key on `listingId`, and you can see
  what a dealership added, what it cut the price on, and what finally sold.
- **Build a VIN-keyed dataset.** US rows carry the VIN, which is the join key for history, recall and
  valuation data you already hold.
- **Find dealers to sell to.** `dealerName`, `city` and `state` across a market give you a list of
  active dealerships with a rough sense of inventory size, which is a better lead list than a
  directory scrape.
- **Compare two markets honestly.** Run the same make and model against `us` and `uk` and you can see
  how the two markets price the same metal, with the caveat that UK prices include fees.

### How to use it

1. Open the Actor and click **Try for free**.
2. Choose the **Market**: `us` for autotrader.com or `uk` for autotrader.co.uk. This is the one input
   that changes everything else, so set it first.
3. Fill **Searches**. A bare US ZIP or UK postcode works. So does a full search URL copied out of your
   browser after you have set the filters on the site by hand, which is the easier way to get a
   narrow search.
4. Set **Maximum results** if you want fewer rows than the searches would naturally return.
5. Click **Start**.
6. Export the dataset from the **Storage** tab as CSV, JSON or Excel, or read it over the API.
7. For price tracking, put the run on a **Schedule** and diff successive runs on `listingId`.

Do not mix markets in one run. A UK postcode against `market: "us"` is a search for a ZIP code that
does not exist, and it will come back as a failure.

### Input

| Field | Type | Default | Description |
| --- | --- | --- | --- |
| `searches` | string\[] | required | US ZIPs, UK postcodes, or full AutoTrader search URLs. 1 to 100 per run |
| `market` | string | `us` | `us` for autotrader.com, `uk` for autotrader.co.uk |
| `maxItems` | integer | `1000` | Cap on dataset rows, 1 to 50000 |
| `concurrency` | integer | `5` | Searches fetched in parallel, 1 to 10 |

```json
{
  "searches": ["78701", "https://www.autotrader.com/cars-for-sale/all-cars?zip=10001&makeCode=TOYOTA"],
  "market": "us",
  "maxItems": 200
}
```

A bare US ZIP searches all cars within 50 miles and asks for 100 records. A bare UK postcode searches
from that postcode with the site's default sort.

A full search URL is the better input whenever you want filters. For the US market the URL is fetched
as you wrote it, with `numRecords` set to 100 unless you set it yourself. The UK gateway takes its
criteria as a checked filter list rather than as query parameters, so a UK search URL is translated,
and these are the parameters that carry across:

`postcode`, `make`, `model`, `radius`, `price-from`, `price-to`, `year-from`, `year-to`,
`minimum-mileage`, `maximum-mileage`, `fuel-type`, `body-type`, `transmission`, `colour`, `doors`,
`seller-type`, `sort`, `page`.

Anything else on a UK URL is ignored rather than passed through, because an unrecognised filter name
fails the whole gateway query.

### Output

One row per vehicle. This is the shape, with plausible values rather than a captured run:

```json
{
  "listingId": "769104338",
  "title": "Used 2021 Toyota RAV4 XLE Premium",
  "year": 2021,
  "make": "Toyota",
  "model": "RAV4",
  "trim": "XLE Premium",
  "price": 27995,
  "priceText": "$27,995",
  "mileage": 41208,
  "bodyStyle": "Sport Utility",
  "fuelType": "Gasoline",
  "transmission": "Automatic",
  "vin": "2T3P1RFV8MW164027",
  "dealerName": "Charles Maund Toyota",
  "city": "Austin",
  "state": "TX",
  "detailUrl": "https://www.autotrader.com/cars-for-sale/vehicle/769104338",
  "sourceUrl": "https://www.autotrader.com/cars-for-sale/all-cars?zip=78701&searchRadius=50&numRecords=100",
  "collectedAt": "2026-08-19T09:14:02.771Z"
}
```

A UK row has the same columns, with `vin`, `bodyStyle`, `fuelType`, `transmission` and `state` set to
`null` and `price` quoted as a fees-inclusive total.

The run also writes a `SUMMARY` record to the key-value store carrying the item count, the failure
count, and every search that failed with its error.

### The two markets are not the same product

They share a brand and nothing else, and it shows in the data. Reading this before you plan a UK run
will save you a surprise.

`autotrader.com` renders its search results into the page's own hydrated state, which holds the same
listing objects the site's private listing API returns. That means exact prices, exact mileages and
VINs rather than text scraped off a card. The Actor takes the active search results only, so the
spotlight and boost placements sitting in the same blob are left out.

`autotrader.co.uk` ships an essentially empty document and calls a GraphQL gateway from the browser,
so the Actor calls that gateway directly and asks only for natural listings, which keeps adverts out
of the result set. The response is card-shaped: mileage and registration year arrive as badge text,
and fuel, gearbox, body style and VIN are simply absent, because the site does not request them for a
results card. No other field carries them, so they are `null` rather than filled in from somewhere
else. The UK response also has no dealer name, only a link to the dealer's page, so `dealerName` is
reconstructed from that link's slug and may not match the dealer's trading name exactly.

### Reliability and limitations

One results page per search, in both markets. In the US that is 100 listings, the maximum
autotrader.com serves. In the UK it is one page of gateway results; add `page=2` to a UK search URL to
read the next one. To cover a market more deeply, run several narrower searches, split by make, model
or price band, rather than expecting one search to page forever.

Search results only. Vehicle history reports, full photo sets, complete option and feature lists,
seller phone numbers and financing terms are all out of scope. Only `autotrader.com` and
`autotrader.co.uk` URLs are accepted; a URL on any other host is rejected before it costs a fetch.

There are no retries, deliberately. The String Unblocker owns proxy rotation and anti-bot solver
selection, so a retry loop here would only re-roll the same block.

### How much does it cost?

The Actor uses Apify's pay-per-event pricing and charges once per result row written to the dataset.
You pay for rows, not for run time, memory or the number of searches it took to produce them, and a
run that returns nothing charges nothing. The current per-result price is on the pricing tab above.

Charging happens on the push, so an account spend limit trims the write rather than overrunning it: a
row that could not be charged for is never written.

Runs started from an Apify **free plan** stop at 250 requests and 250 results and report that they
hit the limit. Any paid plan runs the full input and whatever `maxItems` you set. The limit exists
because this Actor fetches through our own infrastructure, which Apify does not cover for free-plan
runs, and it binds on requests as well as rows so a hundred-search input cannot spend those fetches
on rows the run will never return.

### Using it with the Apify API

```javascript
import { ApifyClient } from "apify-client";

const client = new ApifyClient({ token: "YOUR_APIFY_TOKEN" });

const run = await client.actor("usestring/autotrader-listings").call({
  searches: ["78701", "10001"],
  market: "us",
  maxItems: 200
});

const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items.length, items[0]);
```

Swap `market` to `"uk"` and pass postcodes such as `"SW1A 1AA"` for the UK site. The same call works
from the Python client, or straight against the [Apify REST API](https://docs.apify.com/api/v2). The
failure list lives in the `SUMMARY` record in the run's key-value store.

### Related actors

- [Zillow Property Listings Scraper](https://apify.com/usestring/zillow-listings) for the same
  search-to-rows shape on US homes
- [Zillow Property Detail Scraper](https://apify.com/usestring/zillow-detail) when you have specific
  properties rather than a search
- [Realtor.com Listings Scraper](https://apify.com/usestring/realtor-listings) as a second source of
  US residential inventory
- [LoopNet Commercial Listings Scraper](https://apify.com/usestring/loopnet-listings) for commercial
  real estate, another dealer-style marketplace

### FAQ

**How many listings does one search return?**
Up to 100 in the US, which is the ceiling autotrader.com's own results endpoint serves regardless of
what you ask for. The UK returns one page of gateway results per search; append `page=2`, `page=3`
and so on to a UK search URL to walk further.

**Which countries are supported?**
The United States and the United Kingdom, chosen with `market`. Those are the only two AutoTrader
sites the Actor reads. Canadian and Australian AutoTrader sites are separate businesses and are not
covered.

**Does every listing have a VIN?**
US listings carry `vin` whenever AutoTrader publishes it. UK listings never do. The UK results API
returns no VIN, and no fuel type, gearbox or body style either.

**Why does a row have `priceText` but no `price`?**
Because the dealer published no price. `priceText` then carries the dealer's own label, something
like `"Contact Dealer For Price"`, and `price` is `null` rather than zero.

**Are sponsored listings included?**
No. The US market takes only the active search results, so spotlight and boost placements are left
out even though they sit in the same page state. The UK query asks for natural listings only.

**How fresh is the data, and what happens if a search is blocked?**
Every search is fetched live when the run starts; nothing is cached. A search that fails is recorded
under `failures` in the run's `SUMMARY` with its URL and error, and the run carries on with the rest.
If all of them failed, the run exits with an error instead of quietly succeeding with no data.

### Feedback

If a field comes back wrong, a UK filter you need is not carried across, or a search consistently
fails, open an issue from this Actor's **Issues** tab and include the exact input you ran. Field
requests are welcome there too.

# Actor input Schema

## `searches` (type: `array`):

ZIP/postcode, or a full AutoTrader search URL.

## `market` (type: `string`):

Which AutoTrader site to read.

## `maxItems` (type: `integer`):

Global cap on dataset items. Runs started from an Apify free plan stop at 250 requests and 250 results; any paid plan runs the full amount.

## `concurrency` (type: `integer`):

Targets fetched in parallel.

## Actor input object example

```json
{
  "searches": [
    "78701"
  ],
  "market": "us",
  "maxItems": 1000,
  "concurrency": 5
}
```

# Actor output Schema

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

Scrape AutoTrader car listings from a ZIP code, a UK postcode or a search URL you built on the site. Rows carry year, make, model and trim, numeric price and mileage, VIN, body style, fuel and transmission, plus the selling dealer's name, city and state. Covers autotrader.com and autotrader.co.uk.

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

Item count, failure count and every target that failed, with its error.

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

// Run the Actor and wait for it to finish
const run = await client.actor("usestring/autotrader-listings").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 = { "searches": ["78701"] }

# Run the Actor and wait for it to finish
run = client.actor("usestring/autotrader-listings").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 '{
  "searches": [
    "78701"
  ]
}' |
apify call usestring/autotrader-listings --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,usestring/autotrader-listings"
        }
    }
}
```

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/ROnc7SIuFKp6fLhH7/builds/IZJigS6bWG1nRGKBv/openapi.json
