# Kelley Blue Book Scraper: KBB Used Car Values & Price Range (`superslowsloth/kbb-values`) Actor

Kelley Blue Book (KBB) used car values for a fleet or dealer inventory list: paste make/model/year lines, get one row per vehicle with KBB's USD price range, Fair Purchase Price, original MSRP, trims, ratings and specs. Run monthly to track depreciation.

- **URL**: https://apify.com/superslowsloth/kbb-values.md
- **Developed by:** [Superslow Sloth](https://apify.com/superslowsloth) (community)
- **Categories:** E-commerce, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.95 / 1,000 vehicle valueds

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?

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

## Kelley Blue Book Scraper: KBB Used Car Values & Price Range

Paste a fleet list or a dealer inventory list of vehicles (make, model, year)
and get one row per vehicle from [Kelley Blue Book](https://www.kbb.com) (KBB):
KBB's **price range in USD**, the **Fair Purchase Price**, the certified
pre-owned price, the **original MSRP**, every trim with its own Fair Purchase
Price, KBB's expert and owner ratings, how many are for sale, and the main
specs. Run it on a schedule (monthly) and every row carries the date it was
read, so the dataset becomes a **used-car value and depreciation tracker**.

No account, no API key, no login, no browser. One request per vehicle.

### Input

| Field | Notes |
|---|---|
| `vehicles` | One vehicle per line, as a spreadsheet or fleet system pastes them: `2019 Toyota Camry`, `Toyota Camry 2019`, `2019,Toyota,Camry` (comma- or tab-separated, any order, one cell the year), KBB slugs `toyota/camry/2019`, or a kbb.com year page `https://www.kbb.com/toyota/camry/2019/`. Names become KBB's URL slugs: `3 Series` is `3-series`, `F-150` is `f-150`, `CR-V` is `cr-v`; `Land Rover`, `Alfa Romeo`, `Aston Martin`, `Mercedes Benz` and `Rolls Royce` are read as two-word makes. The same vehicle given twice is valued and charged once. |
| `maxItems` | Value at most this many vehicles, in list order (default 100, up to 2,000). |
| `proxyConfiguration` | Apify **datacenter** proxy, the default. **Do not choose the residential group**: kbb.com refused the Apify residential proxy with HTTP 403 on every request when this actor was built. |

Example input:

```json
{
  "vehicles": [
    "2019 Toyota Camry",
    "2020,Honda,Civic",
    "https://www.kbb.com/ford/f-150/2021/",
    "tesla/model-3/2022"
  ],
  "maxItems": 100
}
```

A line that is not a vehicle (no four-digit year at its start or end, no make
and model) stops the run **before anything is charged**, with the line named.

### What the price range is (and is not)

`price_min` and `price_max` are the range KBB publishes in the page's
structured data for that model year. Measured on 22 KBB year pages on
2026-10-18:

- **The page never prints or labels these two numbers.** The full 2019 Toyota
  Camry page (1.06 MB) has no "$16,450" or "$19,950" anywhere in its text.
- KBB's own page data tags the same pair `buyused` (the price to **buy** the
  car used; `buynew` for a model year still sold new), and the low end is the
  default trim's national **list price** at default equipment and mileage,
  before you enter a ZIP code, mileage, options or condition. `price_basis`
  carries that tag as sent.
- **It is not the Fair Purchase Price.** KBB's Fair Purchase Price (what KBB
  says people typically pay, the figure the page does print) was below
  `price_min` on 22 of 22 pages: 2019 Camry $15,950 against $16,450. It is in
  its own column, `fair_purchase_price`, and per trim in `trims`.
- **It is not a trade-in or private-party value.** Nothing on the page
  labels the range that way (the numbers are not in its text at all), and
  KBB's data tags it `buyused`. Trade-in and private-party values are for one
  specific car, in KBB's separate "My Car's Value" tool, which this actor
  does not use.
- The page does not say what bounds the top end; the per-trim list is in
  `trims`.

Use `price_min`/`price_max` and `fair_purchase_price` as a consistent,
national, model-level signal tracked over time, not as the value of one
specific car.

### Output

| Field | Notes |
|---|---|
| `query`, `make_slug`, `model_slug`, `year`, `source_url` | The line you gave, the KBB slugs and year read from it, and the kbb.com page that was read. |
| `name`, `make`, `model` | As KBB names them: `2019 Toyota Camry`, `Toyota`, `Camry`. |
| `vehicle_url` | KBB's page for what it valued. Usually `source_url`; KBB values a model with several body styles by its default one (`/ford/f-150/2021/` was valued as `/ford/f150-regular-cab/2021/`), and the log says so. |
| `body_type`, `condition` | `Sedan`, `SUV`, `Pickup`...; `used`, or `new` for a model year still sold new. |
| `currency` | `USD` on every page measured. |
| `price_min`, `price_max` | KBB's price range for the year, see above. Equal when KBB lists one trim. |
| `price_basis` | KBB's tag for that range: `buyused` or `buynew`. |
| `fair_purchase_price` | KBB's Fair Purchase Price for `base_trim`. |
| `certified_price` | KBB's certified pre-owned price for `base_trim`. **Null when KBB gives none** (it sends 0, e.g. the 2019 BMW 3 Series). |
| `original_msrp` | `base_trim`'s MSRP when new. |
| `base_trim` | KBB's default trim for the page (`LE Sedan 4D`), the trim `price_min` is the list price of. Not always the trim with the lowest Fair Purchase Price. |
| `trims_model`, `trims` | Every trim KBB lists for the year: `{"name", "fair_purchase_price", "original_msrp"}`, and the model (body style) that list is for. On a market-model page (2020 GMC Sierra 1500) the list can be one body style's (Regular Cab) while the range is the model's. |
| `kbb_category` | KBB's class, e.g. `Mid-size Car`. |
| `expert_rating` | KBB's expert rating out of 5. Null when the page has no expert review (2019 Mazda CX-5). |
| `consumer_rating`, `consumer_review_count` | Owners' average out of 5 and the review count. KBB pools these over the model's **generation**, not the one year. |
| `listings_for_sale` | How many of these KBB showed as for sale. |
| `fuel_type`, `drivetrain`, `transmission`, `seating_capacity`, `mpg_combined` | From KBB's structured data. `fuel_type` and `mpg_combined` are null for electric cars. |
| `image_url` | The first photo KBB lists. |
| `fetched_at` | When the page was read (UTC). The page carries no "as of" date of its own. |

Any field KBB did not send is **null, never 0**: a zero would read as a
measured price.

Example row (real values, 2026-10-18; `trims` shortened):

```json
{
  "query": "2019 Toyota Camry",
  "make_slug": "toyota",
  "model_slug": "camry",
  "year": 2019,
  "source_url": "https://www.kbb.com/toyota/camry/2019/",
  "name": "2019 Toyota Camry",
  "make": "Toyota",
  "model": "Camry",
  "vehicle_url": "https://www.kbb.com/toyota/camry/2019/",
  "body_type": "Sedan",
  "condition": "used",
  "currency": "USD",
  "price_min": 16450.0,
  "price_max": 19950.0,
  "price_basis": "buyused",
  "fair_purchase_price": 15950.0,
  "certified_price": 16950.0,
  "original_msrp": 25555.0,
  "base_trim": "LE Sedan 4D",
  "trims_model": "Camry",
  "trims": [
    {"name": "LE Sedan 4D", "fair_purchase_price": 15950.0, "original_msrp": 25555.0},
    {"name": "XSE Sedan 4D", "fair_purchase_price": 19000.0, "original_msrp": 30680.0}
  ],
  "kbb_category": "Mid-size Car",
  "expert_rating": 4.6,
  "consumer_rating": 3.9,
  "consumer_review_count": 351,
  "listings_for_sale": 696,
  "fuel_type": "Regular",
  "drivetrain": "FrontWheelDrive",
  "transmission": "Automatic, 8-Spd w/Sequential Shift",
  "seating_capacity": 5,
  "mpg_combined": 32.0,
  "image_url": "https://file.kelleybluebookimages.com/kbb/base/evox/CP/13080/2019-Toyota-Camry-front_13080_032_1833x720_2QQ_cropped.png",
  "fetched_at": "2026-10-18T05:00:00Z"
}
```

### Vehicles KBB does not have

Reported in the run log, one line each, **not charged**; the rest of the list
is still valued. Measured answers:

- A year, make or model KBB does not know (`/toyota/camry/1965/`,
  `/notamake/camry/2019/`): HTTP 404.
- A model slug KBB does not use (`/ram/1500/2019/`; KBB's page is
  `/ram/1500-crew-cab/2019/`): KBB redirects to its Car Finder.
- A year KBB has no page for yet (`/toyota/camry/2031/`): KBB redirects to the
  model page for the current year. The actor checks the year on the page it
  got and refuses it rather than return a 2026 price as a 2031 one.

### Pricing

Pay per event: **$0.00195 per vehicle valued** plus **$0.002 per run start**.
100 vehicles cost $0.197. A vehicle KBB has no page for, a duplicate line, or a
line past `maxItems` is not charged.

### How it fetches

It reads the structured data (`application/ld+json`) and the page data that
kbb.com's own year page embeds, one page per vehicle. kbb.com is behind
Akamai. Measured 2026-10-18: Apify datacenter addresses answered 20 of 20 year
pages with HTTP 200 over 35 minutes; the Apify residential proxy and the machine
this actor was built on got HTTP 403 "Access Denied". A refusal (403, 429, 5xx), a 200 that
is not a KBB page, or a dropped connection is treated as the address being
blocked: the actor rotates to a fresh datacenter address and retries.

Limits worth knowing:

- Values are KBB's **national** figures for the default equipment; the actor
  does not enter a ZIP code, mileage, options or condition.
- One row per make/model/year page, not per trim; the trims are in `trims`.

If KBB changes its page data, the run fails with a message instead of
returning empty rows.

# Actor input Schema

## `vehicles` (type: `array`):

One vehicle per line, as a fleet or inventory list pastes: a name with the year first or last (2019 Toyota Camry, Toyota Camry 2019), a spreadsheet row of year, make and model separated by commas or tabs (2019,Toyota,Camry), KBB slugs (toyota/camry/2019), or a kbb.com year page URL (https://www.kbb.com/toyota/camry/2019/). Model names become KBB's slugs: 3 Series is 3-series, F-150 is f-150. The same vehicle given twice is valued once. A vehicle KBB has no page for is reported and not charged.

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

Value at most this many vehicles from the list, in order. The rest are not read or charged.

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

Use Apify's automatic datacenter proxy (the default). Do not pick the residential group: kbb.com (Akamai) refused the Apify residential proxy with HTTP 403 on every request when this actor was built, while datacenter addresses answered 20 of 20 over 35 minutes. A refused request is retried from a fresh address.

## Actor input object example

```json
{
  "vehicles": [
    "2019 Toyota Camry",
    "2020 Honda Civic",
    "2021 Ford F-150"
  ],
  "maxItems": 100,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `items` (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 = {
    "vehicles": [
        "2019 Toyota Camry",
        "2020 Honda Civic",
        "2021 Ford F-150"
    ],
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("superslowsloth/kbb-values").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 = {
    "vehicles": [
        "2019 Toyota Camry",
        "2020 Honda Civic",
        "2021 Ford F-150",
    ],
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("superslowsloth/kbb-values").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 '{
  "vehicles": [
    "2019 Toyota Camry",
    "2020 Honda Civic",
    "2021 Ford F-150"
  ],
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call superslowsloth/kbb-values --silent --output-dataset

```

## MCP server setup

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

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/GD2COE8PHTbeMAbGg/builds/7JgCtcDQp9a2mQJWD/openapi.json
