Vehicle Data API & Scraper
The Vehicle Data API decodes VINs and returns vehicle specs as clean JSON.
🤖 Using an AI assistant? Copy this link into ChatGPT / Claude / Cursor — it reads every endpoint and parameter instantly and tells you if this API fits your use case.
The primary vin_decode endpoint returns a VIN's make, model, year, trim, engine, transmission, drivetrain, weight and plant, and you can batch, get a flat shape, pull fuel_economy, fuel_prices and Canadian specs. It is built for automotive, insurance and marketplace tools that need vehicle data from a VIN. One ReefAPI key, one shared credit pool, the standard envelope.
Types and units that are not what they look like
This API joins two US federal datasets with different conventions, and the seams show. Every value below is from a measured response — a VIN decode of 1HGCM82633A004352 and an EPA lookup on a 2021 Honda Accord. Read this before you write a schema.
| Field | Measured value | What it actually is |
|---|---|---|
| vehicle.* on a VIN decode | "2003", "6", "240", "2" | strings, all of them — model year, cylinder count, horsepower and door count included. The upstream vPIC catalog is untyped; casting is your job. |
| engine.displacementL | "2.998832712" | unrounded litres. Display it as 3.0 L yourself; do not match on the raw string. |
| weight.gvwr | "Class 1C: 4,001 - 5,000 lb (1,814 - 2,268 kg)" | a GVWR class label carrying a range, not a weight. There is no single number to parse out. |
| decode.errorCode | "0" | "0" means the VIN decoded clean and the 9th-position check digit is correct; anything else is explained in errorText. |
| decode.vehicleDescriptor | "1HGCM826*3A" | the VIN with the serial positions masked. Safe to log or store when you do not want to keep a full VIN. |
| mpg.city / highway / combined | 30 / 38 / 33 | integers, US miles per gallon. EV and hybrid rows report MPGe on the same keys. |
| co2GramsPerMile | 268.0 | grams of CO2 per mile, float |
| annualFuelCostUsd | 1850 | US dollars per year, integer, on EPA's own driving assumptions |
| fuelEconomyScore / ghgScore | 7 and 7.0 | EPA's 1–10 scales; note one comes back int and the other float |
| fuel_prices.regular | "4.1" | a quoted decimal string, USD per US gallon |
| fuel_prices.electric | "0.15" | USD per kWh — the one entry in that object that is not per gallon |
The two halves of this API type their numbers differently: a VIN decode returns everything as strings, while an EPA fuel-economy row returns real ints and floats. Same request, two conventions, because they are two different government datasets. Normalize at your boundary rather than trusting the shape.
Real request and response JSON
Captured from the indexed primary action, vin_decode, on .
{
"method": "POST",
"url": "https://api.reefapi.com/vehicle/v1/vin_decode",
"headers": {
"x-api-key": "$REEF_KEY",
"content-type": "application/json"
},
"body": {
"vin": "1HGCM82633A004352"
}
}{
"ok": true,
"meta": {
"api": "vehicle",
"endpoint": "vin_decode",
"mode": "live",
"latency_ms": 2353.8,
"record_count": 1,
"bytes": 3921,
"cache_hit": false,
"completeness_pct": 83.33
},
"data": {
"vin": "1HGCM82633A004352",
"vehicle": {
"make": "HONDA",
"model": "Accord",
"modelYear": "2003",
"trim": "EX-V6",
"bodyClass": "Coupe",
"vehicleType": "PASSENGER CAR",
"doors": "2",
"manufacturer": "AMERICAN HONDA MOTOR CO., INC.",
"engine": {
"cylinders": "6",
"displacementL": "[redacted-phone]",
"displacementCc": "[redacted-phone]",
"displacementCi": "183",
"horsepower": "240",
"model": "J30A4",
"configuration": "V-Shaped",
"fuelPrimary": "Gasoline",
"valveTrain": "Single Overhead Cam (SOHC)"
},
"transmission": {
"style": "Automatic",
"speeds": "5"
},
"weight": {
"gvwr": "Class 1C: 4,001 - 5,000 lb (1,814 - 2,268 kg)",
"gvwrTo": "Class 1: 6,000 lb or less (2,722 kg or less)"
},
"plant": {
"city": "MARYSVILLE",
"state": "OHIO",
"country": "UNITED STATES (USA)"
},
"ids": {
"makeId": "474",
"modelId": "1861",
"manufacturerId": "988"
}
},
"decode": {
"errorCode": "0",
"errorText": "0 - VIN decoded clean. Check Digit (9th position) is correct",
"vehicleDescriptor": "1HGCM826*3A"
}
}
}What the Vehicle Data API does
| Action | Description | Concrete use case | Key params |
|---|---|---|---|
| vin_decode | decode a VIN → make/model/year/trim/engine/specs (vPIC) | Ops teams call vin_decode to get decode a VIN → make/model/year/trim/engine/specs (vPIC). | vin, modelyear, raw |
| vin_decode_batch | decode up to 50 VINs in one call (vPIC batch) | Developer tools call vin_decode_batch to get decode up to 50 VINs in one call (vPIC batch). | vins, raw |
| vin_decode_flat | per-variable VIN decode — one row per NHTSA variable with its label (the long-form companion to vin_decode) | Validation workflows call vin_decode_flat to get per-variable VIN decode. | vin, modelyear |
| fuel_economy | EPA fuel economy — MPG/MPGe (city/highway/combined), CO2, annual fuel cost, EV range. By year+make+model (auto-resolves trims) or EPA id | Data-quality teams call fuel_economy to get ePA fuel economy. | id, year, make, model |
| fuel_economy_options | list EPA trims (each → an id for fuel_economy) for a year+make+model | Ops teams call fuel_economy_options to list EPA trims (each → an id for fuel_economy) for a year+make+model. | year, make, model |
| fuel_prices | current US national average fuel prices (regular/midgrade/premium/diesel/e85/electric/cng/lpg) | Developer tools call fuel_prices to get current US national average fuel prices (regular/midgrade/premium/diesel/e85/electric/cng/lpg). | none |
| canadian_specs | dimensional & weight specs (length, width, height, wheelbase, curb weight, track) from NHTSA's Canadian vehicle database | Validation workflows call canadian_specs to get dimensional & weight specs (length, width, height, wheelbase, curb weight, track) from NHTSA'…. | year, make, model |
| recalls | safety recalls by make+model+modelYear, or by campaignNumber | Data-quality teams call recalls to get safety recalls by make+model+modelYear, or by campaignNumber. | make, model, modelYear, campaignNumber |
| safety_ratings | NCAP star ratings + crash-test media; by vehicleId, or year+make+model (auto-resolves variants), or drill-down | Ops teams call safety_ratings to get nCAP star ratings + crash-test media; by vehicleId, or year+make+model (auto-resolves variant…. | vehicleId, modelYear, make, model |
| complaints | consumer complaints by make+model+modelYear | Developer tools call complaints to get consumer complaints by make+model+modelYear. | make, model, modelYear |
| models | models for a make (optionally a modelYear / vehicleType) | Validation workflows call models to get models for a make (optionally a modelYear / vehicleType). | make, modelYear, vehicleType |
| makes | all makes, or makes for a vehicleType (car/truck/mpv/motorcycle/...) | Data-quality teams call makes to get all makes, or makes for a vehicleType (car/truck/mpv/motorcycle/...). | vehicleType |
| manufacturers | all manufacturers (paged) or details for one | Ops teams call manufacturers to get all manufacturers (paged) or details for one. | manufacturer, page |
| wmi_decode | decode a 3-char WMI to its manufacturer | Developer tools call wmi_decode to get decode a 3-char WMI to its manufacturer. | wmi |
| manufacturer_wmis | all WMIs registered to a manufacturer | Validation workflows call manufacturer_wmis to get all WMIs registered to a manufacturer. | manufacturer |
| vehicle_types | vehicle types produced by a make | Data-quality teams call vehicle_types to get vehicle types produced by a make. | make |
| product_options | recall/complaint enumeration tree (modelYears → makes → models; issueType=r|c) | Ops teams call product_options to get recall/complaint enumeration tree (modelYears → makes → models; issueType=r|c). | issueType, modelYear, make |
| plant_codes | equipment (tire) plant codes for a year | Developer tools call plant_codes to get equipment (tire) plant codes for a year. | year, equipmentType, reportType |
Call vin_decode from your stack
curl -X POST https://api.reefapi.com/vehicle/v1/vin_decode \
-H "x-api-key: $REEF_KEY" \
-H "content-type: application/json" \
-d '{"vin":"1HGCM82633A004352"}'import requests
r = requests.post(
"https://api.reefapi.com/vehicle/v1/vin_decode",
headers={"x-api-key": REEF_KEY},
json={
"vin": "1HGCM82633A004352"
},
)
print(r.json()["data"])const res = await fetch("https://api.reefapi.com/vehicle/v1/vin_decode", {
method: "POST",
headers: {
"x-api-key": process.env.REEF_KEY,
"content-type": "application/json",
},
body: JSON.stringify({
"vin": "1HGCM82633A004352"
}),
});
const { ok, data, meta, error } = await res.json();Ask your MCP-connected assistant: call reefapi.vehicle.vin_decode with {"vin":"1HGCM82633A004352"}.Who uses this API and why
- Marketplaces call vin_decode to auto-fill a vehicle listing from a VIN.
- Insurance tools use vin_decode for underwriting and quoting.
- Apps use fuel_economy and fuel_prices to estimate running costs.
Questions developers ask before integrating
Why does the VIN decoder return numbers as strings?
Because the NHTSA vPIC catalog behind it is a flat attribute table with no type information — every cell is text. A measured decode of 1HGCM82633A004352 returned modelYear "2003", cylinders "6", horsepower "240" and doors "2", all quoted. We pass them through rather than guessing at conversions, since a bad cast on an ambiguous field is worse than an honest string. Cast at your own boundary and expect empty strings where the catalog has no value.
Can I decode a partial VIN?
Yes — use * for the positions you do not know, and pass modelyear to disambiguate. A VIN is 1–17 characters of A–Z and 0–9 with I, O and Q excluded from the alphabet entirely (they look too much like 1 and 0), so a VIN containing any of those three is malformed rather than unknown. The response's decode.errorText tells you exactly what was and was not resolvable, and decode.suggestedVin appears when NHTSA can propose a correction.
How do I confirm a VIN decoded correctly rather than partially?
Read decode.errorCode, not the presence of fields. A measured clean decode returned errorCode "0" with errorText "0 - VIN decoded clean. Check Digit (9th position) is correct" — that is the 9th character validating the other sixteen arithmetically, which catches transcription errors before you store them. meta.completeness_pct on the same call was 83.3, meaning some catalog fields were empty for that vehicle; that is normal for older cars and is not a decode failure.
What is vehicleDescriptor and why would I store it instead of the VIN?
It is the VIN with the individual serial masked out — measured: 1HGCM826*3A for 1HGCM82633A004352. It still identifies the make, model, body and engine family, but not the specific car. If you are caching decode results, keying on the descriptor gives you a cache hit across every vehicle of that configuration and keeps a personally-identifying VIN out of your logs.
How do I get fuel economy for a specific trim?
Call fuel_economy_options with year, make and model to list the EPA trims and their ids, then call fuel_economy with the id you want. Passing year, make and model straight to fuel_economy auto-resolves and returns one row per trim in vehicles[] — a measured 2021 Honda Accord lookup returned count 1 with id 43361, trim "Automatic (variable gear ratios)", vehicleClass "Large Cars", 30/38/33 MPG and annualFuelCostUsd 1850. EPA coverage starts at 1984.
What unit is the electric price in fuel_prices?
USD per kilowatt-hour, while every other key in that object is USD per US gallon. A measured call returned regular 4.1, midgrade 4.68, premium 5.07, diesel 5.31, e85 2.63, cng 2.96, lpg 3.42 and electric 0.15 — and that last figure is only coherent as a per-kWh rate. All eight arrive as quoted strings. These are US national averages at the time you call, not regional prices, so do not use them for a local cost estimate.
How do I decode a lot of VINs at once?
vin_decode_batch takes up to 50 per call and is flexible about the input shape: a 'VIN,year;VIN,year' string, an array of bare VIN strings, an array of [VIN, year] pairs, or an array of {vin, modelyear} objects. Each result carries its own vin, vehicle and decode block, so a VIN that fails to decode does not affect the other 49 — check each row's decode.errorCode individually.
What is vin_decode_flat for, and what does raw add?
vin_decode_flat returns one row per NHTSA variable — variable name, its label, the value, plus variableId and valueId — instead of the tidied nested vehicle object. Use it when you want a field the curated shape does not surface, or when you need NHTSA's own numeric ids to join against another government dataset. raw: true on vin_decode is the middle ground: you keep the nested object and additionally get the full flat attribute row (around 130 fields) under attributes.
What is the Vehicle Data API?
Vehicle Data API is a ReefAPI endpoint group for vehicle data It returns live JSON through POST requests under /vehicle/v1.
Is the Vehicle Data API free to try?
Yes. ReefAPI starts with 1,000 free credits, no card required. Vehicle Data calls use the same shared credit balance as every other ReefAPI engine.
Do I need a Vehicle Data login or account?
No login to Vehicle Data is needed for the API response. You call ReefAPI with your x-api-key header, and the playground can run live examples before you create a production key.
How fresh is the Vehicle Data data?
The page example is captured from a live vin_decode call, and production requests fetch live data through ReefAPI rather than a static sample.
How many credits does the Vehicle Data API use?
Vehicle Data actions currently cost 1-2 credits per successful call. Failed or blocked calls are free, and all APIs draw from one credit pool.
Can I call Vehicle Data from an AI assistant or MCP client?
Yes. Connect ReefAPI once through MCP and your assistant can call vehicle actions with the same key, credit pool and JSON envelope used by normal REST requests.