# VIN Decoder API (`prodiger/vin-decoder`) Actor

Decode VINs against the free NHTSA databases. Structured output (identification, engine, body, safety, ADAS, EV, manufacturing), optional active recalls and NCAP safety ratings, VIN structural breakdown with check-digit validation. Pay-per-event tiered pricing.

- **URL**: https://apify.com/prodiger/vin-decoder.md
- **Developed by:** [Arnas](https://apify.com/prodiger) (community)
- **Categories:** AI, Agents, Automation
- **Stats:** 9 total users, 3 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: 5.00 out of 5 stars

## Pricing

from $0.50 / 1,000 vin decodeds

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/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

## VIN Decoder API

**Decode VINs at scale**, structured into clean categories, with optional **active recalls** and **NCAP safety ratings** attached. Powered by the free [NHTSA](https://vpic.nhtsa.dot.gov/api/) databases — no API key, no monthly fee. Pay only for what you ask for: tiered pay-per-event pricing.

### What does VIN Decoder API do?

This actor takes one or many 17-character VINs and returns:

- A **structured decode** — 70-130+ NHTSA fields bucketed into `identification`, `body`, `engine`, `drivetrain`, `electric`, `safety`, `advancedDriverAssistance`, `manufacturing`, `diagnostics`. No more digging through a flat blob.
- A **VIN structural breakdown** — WMI / VDS / VIS / check digit / model year char / plant code, plus a check-digit validity flag (ISO 3779).
- **Optional active recalls** — every NHTSA recall campaign for the decoded vehicle, including the consequence, remedy, and "Park Outside / Stop Driving" advisories.
- **Optional NCAP safety ratings** — overall, frontal, side, and rollover star ratings for every NHTSA-rated trim of the vehicle, plus complaint and investigation counts.

Try it from the **Input** tab with the prefilled example VINs, or call it from any HTTP client via the [Apify API](https://docs.apify.com/api/v2). Apify gives you scheduling, webhooks, integrations, retries, monitoring, and per-run datasets out of the box.

### Why use VIN Decoder API?

- **Car dealerships and marketplaces** — enrich listings with structured attributes from a VIN scan, plus surface open recalls right at the point of sale.
- **Insurance and risk** — confirm reported make/model/year against the manufacturer record and roll recall/safety data into underwriting.
- **Fleet management** — bulk-decode tens of thousands of VINs and trigger remediation when a recall lands.
- **Vehicle history products** — combine the decode with NCAP ratings, NHTSA recalls, and your own title/accident sources.
- **AI/ML pipelines** — clean, categorized vehicle features for downstream models without writing a vPIC field-name dictionary.

### How to use VIN Decoder API

1. Open the Actor on Apify Console and click **Try for free**.
2. Paste your VINs into the **VIN codes** field.
3. (Optional) Pick **Extended decode mode** for ~30% more fields per VIN; turn on **Include recalls** and/or **Include safety ratings** for the enrichment data.
4. Click **Start**. The actor batches up to 50 VINs per upstream decode call (basic mode), so a list of 1000 VINs finishes in roughly 30-60 seconds without enrichment.
5. Open the **Output** tab to view, filter, and export decoded records as JSON, CSV, Excel, or HTML.

### Input

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `vinCodes` | array | yes | 17-character VINs. VINs are uppercased, trimmed, deduplicated; entries containing `,` or `;` are split. |
| `decodeMode` | string | no | `basic` (default, batched) or `extended` (per-VIN, more fields). |
| `includeRecalls` | boolean | no | Fetch active NHTSA recalls per make/model/year. Default `false`. |
| `includeSafetyRatings` | boolean | no | Fetch NCAP star ratings per make/model/year. Default `false`. |
| `maxVinsPerRun` | integer | no | Hard cap on VINs processed. Default `1000`, `0` for unlimited. |
| `maxRequestRetries` | integer | no | Retry attempts per failed upstream call. Default `3`. |

Example input:

```json
{
  "vinCodes": ["4JGDA6EB8JB018467", "4JGDA6DB1GA739858"],
  "decodeMode": "extended",
  "includeRecalls": true,
  "includeSafetyRatings": true
}
```

### Output

One record per VIN lands in the run's default dataset. NHTSA fields keep their original PascalCase names within each category, so existing NHTSA tooling keeps working — you just don't have to filter through them.

```json
{
  "vin": "4JGDA6EB8JB018467",
  "valid": true,
  "errors": [],
  "scrapedAt": "2026-04-29T14:23:11.482Z",
  "decodeMode": "extended",
  "structure": {
    "wmi": "4JG",
    "vds": "DA6EB8",
    "vis": "JB018467",
    "checkDigit": "8",
    "modelYearChar": "J",
    "plantCode": "B",
    "sequentialNumber": "018467",
    "checkDigitValid": true
  },
  "identification": {
    "Make": "MERCEDES-BENZ",
    "Model": "GLE-Class",
    "ModelYear": "2018",
    "ManufacturerName": "DAIMLER AG",
    "VehicleType": "MULTIPURPOSE PASSENGER VEHICLE (MPV)",
    "Trim": "AMG GLE 43"
  },
  "body": { "BodyClass": "SUV/MPV", "Doors": "4", "GVWR": "Class 1D" },
  "engine": { "DisplacementL": "3.0", "EngineCylinders": "6", "FuelTypePrimary": "Gasoline", "Turbo": "Yes" },
  "drivetrain": { "DriveType": "AWD", "TransmissionStyle": "Automatic" },
  "safety": { "ABS": "Standard", "ESC": "Standard", "TPMS": "Direct" },
  "advancedDriverAssistance": { "AdaptiveCruiseControl": "Optional", "BlindSpotMon": "Standard" },
  "manufacturing": { "PlantCountry": "UNITED STATES (USA)", "PlantCity": "TUSCALOOSA" },
  "recalls": [
    {
      "campaignNumber": "20V725000",
      "component": "ELECTRICAL SYSTEM",
      "summary": "Mercedes-Benz USA, LLC ...",
      "consequence": "...",
      "remedy": "...",
      "parkIt": false,
      "parkOutside": false,
      "reportReceivedDate": "2020-11-19T00:00:00.000Z"
    }
  ],
  "safetyRatings": [
    {
      "vehicleId": 12345,
      "vehicleDescription": "2018 Mercedes-Benz GLE 4 DR AWD",
      "overallRating": "5",
      "overallFrontCrashRating": "5",
      "overallSideCrashRating": "5",
      "rolloverRating": "4",
      "complaintsCount": 12,
      "recallsCount": 3,
      "investigationCount": 0
    }
  ]
}
```

You can download the dataset in various formats such as JSON, HTML, CSV, or Excel.

#### Data table

| Field | Description |
| --- | --- |
| `vin` | The 17-character VIN that was decoded (uppercased). |
| `valid` | `true` if the VIN passed shape validation; `false` if it was flagged. Invalid records still appear in the output with empty category buckets. |
| `errors` | Array of validation messages for invalid VINs. |
| `decodeMode` | Echoes which decode endpoint produced this record. |
| `structure` | WMI/VDS/VIS breakdown plus check-digit validity. |
| `identification` | Make, model, year, manufacturer, trim, vehicle type. |
| `body` | Body class, doors, weights, wheelbase, top speed, base price. |
| `engine` | Displacement, cylinders, HP/kW, fuel type(s), turbo, valvetrain. |
| `drivetrain` | Drive type, transmission style/speeds, axle config. |
| `electric` | EV battery chemistry, capacity, voltage, charger level (only populated for hybrids/EVs). |
| `safety` | ABS, ESC, traction control, TPMS, airbag locations, anti-theft. |
| `advancedDriverAssistance` | ACC, blind-spot, lane-keep, AEB, park assist, etc. |
| `manufacturing` | Plant city, country, state, company. |
| `diagnostics` | NHTSA's own decode error/note fields. |
| `other` | Anything NHTSA returns that isn't bucketed elsewhere. New NHTSA fields land here automatically. |
| `recalls` | Active NHTSA recall campaigns (only when `includeRecalls`). |
| `safetyRatings` | NCAP ratings per trim (only when `includeSafetyRatings`). |

### Pricing

This actor uses **tiered pay-per-event** pricing — there is no monthly subscription. You pay only for the events you trigger:

| Event | Fires when |
| --- | --- |
| `apify-actor-start` | Run starts (synthetic, automatic). |
| `vin-decoded` | A VIN was successfully decoded and written to the dataset. |
| `recalls-fetched` | Recalls were fetched for a VIN (only when `includeRecalls`). |
| `safety-rating-fetched` | NCAP ratings were fetched for a VIN (only when `includeSafetyRatings`). |
| `invalid-vin` | A VIN failed shape validation (length / forbidden chars). Recommended free tier — gives you observability without a billing cost. |

Failures (network errors, retries exhausted, NHTSA outages) are **never** charged — events only fire after the corresponding work has been written to the dataset. Recalls and safety ratings are also deduplicated per make+model+year within a run, so 50 VINs of the same model trigger only one upstream call each (but each VIN still gets its own `recalls-fetched` charge — buyer-friendly predictability).

You can cap spend per run via Apify's standard "Max cost" run option. The actor honors `eventChargeLimitReached` and stops decoding once the cap is hit.

### Tips and advanced options

- **Want every field NHTSA has?** Set `decodeMode: extended`. Trade-off: extended decode is per-VIN (NHTSA does not expose a batch extended endpoint), so a 1000-VIN run takes ~5x longer than basic.
- **Recalls without ratings, or vice versa.** The two enrichment toggles are independent — turn on only what you need.
- **Need only specific fields?** Each category is a plain object. Read `record.identification.Make` and skip the rest. The dataset's flat-table view in the Apify Console flattens nested categories into individual columns.
- **Bad VINs in your input?** Length and forbidden-character violations are flagged in `errors[]` and emit an `invalid-vin` event for visibility — the run does not fail. VINs whose check-digit math fails (common for non-North-American VINs) still get fully decoded; the math result is reported under `structure.checkDigitValid`.

### FAQ

**Do I need an API key?** No. NHTSA's vPIC, recalls, and SafetyRatings APIs are free and public; the actor proxies them with batching, deduplication, retries, and structured output.

**Will it work for non-US VINs?** Many — NHTSA covers vehicles imported to the US and a meaningful share of global production. Coverage is best for 1981+ vehicles. Unknown VINs return empty category buckets but the structural breakdown still works.

**Why does my non-US VIN show `checkDigitValid: false`?** The check-digit algorithm is mandatory in North America but not enforced globally. A `false` here doesn't mean the VIN is fake — it just means the math doesn't match. The VIN is still decoded normally.

**Is this legal?** Yes. NHTSA APIs are US government public datasets. This actor only reads from them.

**Where do I report issues or request a feature?** Open an issue on the **Issues** tab of this Actor. Custom variants (extra fields, third-party VIN sources, post-processing) are also available — message the maintainer.

# Actor input Schema

## `vinCodes` (type: `array`):

List of 17-character VINs to decode. VINs are uppercased, trimmed, and deduplicated. Entries containing commas or semicolons are split (so pasting 'VIN1,VIN2' as a single item works).

## `decodeMode` (type: `string`):

basic = NHTSA's batch decode (50 VINs/request, ~70-100 fields). extended = per-VIN extended decode with ~30% more fields including extra ADAS, EV battery, and plant metadata. Extended mode is slower for large lists because NHTSA does not expose a batch extended endpoint.

## `includeRecalls` (type: `boolean`):

Fetch active NHTSA recalls for each decoded vehicle (by make/model/year). Recall fetches are deduplicated per make+model+year within the run. Charged as 'recalls-fetched' events.

## `includeSafetyRatings` (type: `boolean`):

Fetch NHTSA NCAP star ratings for each decoded vehicle. Two upstream calls per unique make+model+year. Charged as 'safety-rating-fetched' events.

## `maxVinsPerRun` (type: `integer`):

Hard cap on how many VINs the actor will process. Excess VINs are dropped before any upstream call. Set to 0 for unlimited.

## `maxRequestRetries` (type: `integer`):

Retry attempts per failed upstream call (5xx, network errors). Applies to decode, recalls, and safety-ratings calls.

## Actor input object example

```json
{
  "vinCodes": [
    "4JGDA6EB8JB018467",
    "4JGDA6DB1GA739858",
    "1HGCM82633A123456"
  ],
  "decodeMode": "basic",
  "includeRecalls": false,
  "includeSafetyRatings": false,
  "maxVinsPerRun": 1000,
  "maxRequestRetries": 3
}
```

# Actor output Schema

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

One record per VIN with all available NHTSA fields under vehicleInfo.

# 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 = {
    "vinCodes": [
        "4JGDA6EB8JB018467",
        "4JGDA6DB1GA739858",
        "1HGCM82633A123456"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("prodiger/vin-decoder").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 = { "vinCodes": [
        "4JGDA6EB8JB018467",
        "4JGDA6DB1GA739858",
        "1HGCM82633A123456",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("prodiger/vin-decoder").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 '{
  "vinCodes": [
    "4JGDA6EB8JB018467",
    "4JGDA6DB1GA739858",
    "1HGCM82633A123456"
  ]
}' |
apify call prodiger/vin-decoder --silent --output-dataset

```

## MCP server setup

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

```

## OpenAPI specification

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