# VIN Decoder — NHTSA vPIC Make, Model, Year & Specs (`keyman98/vin-decoder-nhtsa`) Actor

Decode VINs in bulk into make, model, model year, trim, body, engine, fuel type and plant using NHTSA's official vPIC database. Up to thousands of VINs per run, partial VINs with \* accepted. Pay only for VINs that decode to a model.

- **URL**: https://apify.com/keyman98/vin-decoder-nhtsa.md
- **Developed by:** [KeyMan98](https://apify.com/keyman98) (community)
- **Categories:** Automation, Developer tools, E-commerce
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.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.

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

## VIN Decoder — NHTSA vPIC Make, Model, Year & Specs

Decode any VIN (Vehicle Identification Number) into make, model, year, trim, body class, engine, and dozens of other specs — through NHTSA's own free **vPIC** API (**vpic.nhtsa.dot.gov**). No API key, no HTML scraping, no login.

### What you get (output fields)

For each VIN, one dataset row with:

- `vin` — the VIN as given, trimmed and uppercased.
- `valid` — `true` only for a fully clean decode (no NHTSA warnings); `false` for a partial decode, an unresolved VIN, or an error row.
- `errorCode` / `errorText` — NHTSA's diagnostic code(s), e.g. `"0"` for clean, `"6"` ("Incomplete VIN") for partial. Null if the row never reached vPIC.
- `make`, `model`, `modelYear`, `trim`, `series`, `vehicleType`, `bodyClass`, `doors`, `driveType` — identity, body, configuration.
- `engineCylinders`, `displacementL`, `fuelTypePrimary`, `transmissionStyle`, `manufacturer`, `plantCountry`, `plantCity` — engine, drivetrain, and where it was built.
- `gvwr` — Gross Vehicle Weight Rating, as NHTSA's own descriptive range (e.g. `"Class 1C: 4,001 - 5,000 lb"`), not one exact number.
- `electrificationLevel` — for hybrids/EVs, e.g. `"BEV (Battery Electric Vehicle)"`.
- `allFields` — only when "Include all vPIC fields" is on: every other non-empty field NHTSA returned (150+ possible), under NHTSA's own names.
- `sourceUrl` — the public vPIC API URL for this VIN, to check the raw answer yourself.
- `error` — set only when a row was never decoded (invalid VIN, duplicate, or fetch failure); every other field is null on those rows.

### Who it's for

- **Dealers, marketplaces, classifieds** — auto-fill make/model/year/trim from a typed VIN.
- **Fleet and insurance tools** — engine, body, weight-class data for many vehicles at once.
- **Import/export and parts businesses** — confirm what a VIN is before quoting parts or shipping.
- **Data and research projects** — batch-decode VINs without a manual lookup page per VIN.

### How to use

1. **VINs** — one or more, 17 characters each. Unknown positions marked `*` are accepted too (e.g. `5UXWX7C5*BA`), as long as the first 3 characters (the manufacturer code) are known and at least 3 characters overall are known — vPIC decodes what it can and reports the rest as incomplete.
2. **Model year (optional)** — set once for every VIN in this run, if known; helps vPIC resolve an ambiguous model-year character. Leave empty if your VINs cover different years.
3. **Include all vPIC fields** — off by default (clean fields only). Turn on for every other non-empty field vPIC has.
4. **Run the Actor.** Each VIN becomes one row.

### Input example (JSON)

```json
{
  "vins": ["1HGCM82633A004352", "5UXWX7C5*BA", "1FTFW1ET5DFC10312"],
  "modelYear": null,
  "includeAllFields": false
}
```

### Output example (JSON)

```json
{
  "vin": "1HGCM82633A004352",
  "valid": true,
  "errorCode": "0",
  "make": "HONDA",
  "model": "Accord",
  "modelYear": 2003,
  "trim": "EX-V6",
  "vehicleType": "PASSENGER CAR",
  "bodyClass": "Coupe",
  "doors": 2,
  "engineCylinders": 6,
  "displacementL": 2.998832712,
  "fuelTypePrimary": "Gasoline",
  "transmissionStyle": "Automatic",
  "manufacturer": "AMERICAN HONDA MOTOR CO., INC.",
  "plantCountry": "UNITED STATES (USA)",
  "plantCity": "MARYSVILLE",
  "gvwr": "Class 1C: 4,001 - 5,000 lb (1,814 - 2,268 kg)",
  "sourceUrl": "https://vpic.nhtsa.dot.gov/api/vehicles/DecodeVinValues/1HGCM82633A004352?format=json",
  "error": null
}
```

(`series`, `driveType`, `electrificationLevel`, and `allFields` are also in every row — null here since this VIN has no value for them.)

### If a VIN can't be decoded

Every VIN gets exactly one row, and the run never fails because of a bad VIN:

- **Locally invalid** (wrong length, disallowed characters, or uses I/O/Q) — rejected before contacting vPIC. `error` set, no charge.
- **Duplicate** — the same VIN listed twice (case/whitespace-insensitive) is decoded and charged only once; later copies are skipped.
- **vPIC could not resolve a model** (valid format, maybe even a valid make, but no matching model — e.g. a made-up VIN with a real manufacturer code) — a normal row, `errorCode`/`errorText` explain why, `model` null, no charge.
- **vPIC or the network unreachable** after retries — `error` set, no charge, the rest of your VINs keep processing.

### Pricing

Pay only for VINs vPIC actually decoded something for. Pricing model: **pay-per-event**.

| Event | When it's charged | Price |
| --- | --- | --- |
| `vin-decoded` | vPIC returned a **model** for this VIN, full or partial decode | 0.0015 USD |

Not charged: locally invalid VINs, duplicates, network/API failures, and VINs vPIC could not match to a model — a make alone (a real manufacturer code with no matching model) is not enough to charge.

### Limitations

- vPIC is a **US-market** database: VINs for vehicles never sold in the US often decode poorly or not at all, even with a valid format.
- Data comes from manufacturer submissions to NHTSA; a missing field means no data, not that the vehicle lacks that feature.
- `gvwr` is a descriptive weight-class range, not one exact number.
- A partial VIN (`*`) only resolves what the known characters allow — exact trim/engine detail is often still missing even when make/model/year are found.
- Up to 50 VINs go to vPIC per request; larger inputs run as sequential batches, so a large list takes longer.
- `allFields` exposes NHTSA's raw field names, not cleaned like the main fields.

### FAQ

#### Am I charged for a VIN vPIC can't decode at all?

No. Only VINs vPIC returns a **model** for are charged — clean or partial decode, both count; a make alone (no model) is free.

#### Can I decode a partial VIN with unknown characters?

Yes, use `*` for any unknown position (e.g. `5UXWX7C5*BA`). vPIC decodes what it can, a normal partial decode, not an error.

#### What's the difference between `valid: false` and an `error`?

`valid` is vPIC's own diagnosis of the VIN. `error` means the row never got a real decode at all (bad format, duplicate, fetch failure).

#### How do I get details like airbags, ABS, or EV battery specs?

Turn on "Include all vPIC fields" — everything else NHTSA has for that VIN comes back in `allFields`.

#### Does this work for VINs outside the US?

Only if the vehicle was also sold in the US and is in NHTSA's database; coverage elsewhere is generally poor.

#### Can I use this through the Apify API or an MCP server?

Yes, like any Apify Actor — the standard Apify API, or the Apify MCP server with Claude, Cursor, or another MCP client.

### Export

Results can be downloaded from the Apify dataset as JSON, CSV, or Excel, or accessed via the Apify API. Underlying data is NHTSA's own public vPIC database (US government, public domain); `sourceUrl` on every row links to NHTSA's own answer for that VIN.

# Actor input Schema

## `vins` (type: `array`):

One or more VINs (17 characters). A VIN with unknown positions marked "*" is also accepted (e.g. "5UXWX7C5*BA") - NHTSA decodes what it can from the known characters.

## `modelYear` (type: `integer`):

Model year for every VIN above, if you know it. Helps NHTSA disambiguate VINs whose model-year character is otherwise ambiguous. Leave empty if unknown or if your VINs cover different years.

## `includeAllFields` (type: `boolean`):

Off (default): only the clean, commonly-used fields (make, model, engine, body, ...). On: also include every other non-empty field NHTSA returns (150+ possible fields, e.g. airbags, ABS, battery specs on EVs) in an "allFields" object.

## Actor input object example

```json
{
  "vins": [
    "1HGCM82633A004352",
    "5UXWX7C5*BA",
    "1FTFW1ET5DFC10312"
  ],
  "includeAllFields": false
}
```

# Actor output Schema

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

All decoded VINs in the default dataset (JSON, CSV, Excel).

# 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 = {
    "vins": [
        "1HGCM82633A004352",
        "5UXWX7C5*BA",
        "1FTFW1ET5DFC10312"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("keyman98/vin-decoder-nhtsa").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 = { "vins": [
        "1HGCM82633A004352",
        "5UXWX7C5*BA",
        "1FTFW1ET5DFC10312",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("keyman98/vin-decoder-nhtsa").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 '{
  "vins": [
    "1HGCM82633A004352",
    "5UXWX7C5*BA",
    "1FTFW1ET5DFC10312"
  ]
}' |
apify call keyman98/vin-decoder-nhtsa --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,keyman98/vin-decoder-nhtsa"
        }
    }
}
```

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/aVDKfq8nCjyZq8GUs/builds/ffna2ckV7UOxeopqy/openapi.json
