NHTSA VIN Decoder API — Batch vPIC VIN Lookup
Pricing
from $2.75 / 1,000 results
NHTSA VIN Decoder API — Batch vPIC VIN Lookup
Batch-decode VINs via NHTSA vPIC into compact, normalized rows: make, model, year, body class, drivetrain, engine, GVWR, and plant country. One clean row per VIN. Built for fleet, auto-insurance underwriting, and used-car marketplace enrichment. Keyless government data.
Pricing
from $2.75 / 1,000 results
Rating
0.0
(0)
Developer
Kyle Maloney
Maintained by CommunityActor stats
0
Bookmarked
1
Total users
0
Monthly active users
3 days ago
Last modified
Share
Decode a batch of VINs into clean, normalized rows using the official NHTSA vPIC database (keyless, free, US government source). Every VIN returns one row with a stable 125-field schema — make, model, year, body class, drivetrain, engine, transmission, plant, occupant protection and the full NHTSA ADAS/active-safety field set — ready to join straight into your fleet, underwriting, or marketplace pipeline.
VIN decoder API for bulk vehicle lookups — make, model, year, body class, drivetrain, engine, GVWR, plant, safety systems, normalized and batchable.
Who it's for
- Fleet & telematics teams — enrich vehicle rosters from just the VIN.
- Auto insurers & underwriting — standardized vehicle attributes plus the safety-equipment fields that drive rating.
- Used-car marketplaces & dealership tools — auto-fill listing specs at scale.
- Warranty & lending providers — verify class, drivetrain and weight rating.
- Data teams — a stable-schema VIN feed you can decode thousands at a time.
Decode confidence — read this before you trust a row
NHTSA's ErrorCode is the entire correctness contract of a VIN decode, and
it is a closed vocabulary of 15 published values. vPIC returns combined
codes, and 0 genuinely co-occurs with warnings.
Measured live on 2026-08-01, on this actor's own example VIN:
/decodevinvalues/1HGCM82633A004352?modelyear=2005-> ErrorCode "0,12" Make=HONDA Model=Accord ModelYear=2005/decodevinvalues/1HGCM82633A004352?modelyear=1999-> ErrorCode "0,12,14" Make=HONDA Model="" ModelYear=1999
That VIN is a 2003 Accord. Code 12 is "Model Year Warning — the model year
entered for decoding does not match the model year based on the 10th position in
VIN. Decoded data may not be accurate." Earlier versions of this actor reported
both rows as decode_valid: true.
So decode_valid now means exactly one thing:
decode_valid | Meaning |
|---|---|
true | vPIC returned ErrorCode exactly "0" — decoded clean, check digit correct. |
false | vPIC answered, and the decode is not clean. Read decode_status, error_codes and additional_error_text. |
null | vPIC did not answer. A transport failure is not a statement about the VIN. |
decode_status gives the full picture: clean, clean_with_warnings
(vPIC decoded it but flags the data as possibly inaccurate), partial (some
vehicle data alongside error codes — an incomplete VIN still returns make and
model), invalid, unavailable, or unknown.
Other guarantees:
- The closed vocabulary is asserted live on every run. If NHTSA adds or
removes an
ErrorCodevalue, the run fails rather than classifying rows by guesswork. - A positive canary and a negative control run before anything is billed. A
known-good VIN must decode clean; a VIN containing
I,OandQ(letters that cannot appear in a VIN) must not. If the decoder ever starts answering0for everything, the run fails instead of publishing a fleet of confident false decodes. - Truncation is never silent. VINs dropped by
maxVinsare logged and counted invins_truncatedon every row. - If vPIC answers for no VIN in the run, the run fails and bills nothing.
Example input
{"vins": ["1HGCM82633A004352","JH4KA7561PC008269",{ "vin": "5UXWX7C5XBA000000", "modelYear": 2011 }],"extended": false,"maxVins": 10000}
Each item is a plain VIN string, or { "vin": "...", "modelYear": 2013 } to help
vPIC disambiguate older VINs. Supplying a modelYear that conflicts with
position 10 of the VIN produces ErrorCode 12 and model_year_warning: true —
which is exactly the case this actor now reports honestly.
A * can stand in for the check digit or unknown positions; a partial VIN
decodes with decode_status: "partial" (measured: 5UXWX7C5*BA returns
BMW X3 2011 with ErrorCode 6).
Output fields
Every row carries the same 125 fields; a field vPIC did not populate is null.
Identity and status
| Field | Description |
|---|---|
vin | The VIN as requested. |
decode_valid | true only when ErrorCode is exactly "0". null when vPIC did not answer. |
decode_status | clean, clean_with_warnings, partial, invalid, unavailable, unknown. |
error_code | The raw vPIC ErrorCode, e.g. "0", "0,12", "1,7,400". |
error_codes | The same value split into tokens. |
error_text | vPIC's own ErrorText. |
error_code_meanings | Each token expanded from NHTSA's published vocabulary. |
additional_error_text | vPIC's free-text explanation, e.g. "Invalid character(s): 1:I, 2:O, 3:Q.". |
suggested_vin | vPIC's corrected VIN, ! marking each rejected position, e.g. "1G1YY22!965105693". |
has_decode_warnings | True when any "data may be wrong" code (2, 3, 4, 8, 11, 12, 14) was returned. |
model_year_warning | True when ErrorCode includes 12. |
check_digit_valid | False when ErrorCode includes 1. |
requested_model_year | The modelYear you supplied, if any. |
vpic_status | ok or unavailable. |
vpic_error | Transport error behind unavailable. |
extended_decode | Whether the extended endpoint was used. |
decoded_field_count | How many fields vPIC actually populated (45 for the example Accord, 70 for a 2018 Tesla Model 3, 4 for an unregistered manufacturer). |
vins_truncated | VINs dropped by maxVins and therefore not decoded. |
retrieved_at | ISO timestamp of the decode. |
Vehicle
make, model, model_year, manufacturer, manufacturer_id, make_id,
model_id, vehicle_type, body_class, series, series_2, trim, trim_2,
vehicle_descriptor, doors, gvwr, gvwr_to, curb_weight_lb,
ncsa_body_type, ncsa_make, ncsa_model, base_price_usd, note.
Engine and drivetrain
engine_cylinders, displacement_l, displacement_cc, displacement_ci,
engine_hp, engine_hp_to, engine_model, engine_manufacturer,
engine_configuration, valve_train_design, fuel_injection_type, turbo,
cooling_type, other_engine_info, fuel_type_primary, fuel_type_secondary,
drive_type, transmission_style, transmission_speeds, axles, wheels,
wheel_base_short, wheel_base_type, wheel_size_front,
wheel_size_rear, steering_location, brake_system_type, brake_system_desc,
top_speed_mph.
Electrification
electrification_level, ev_drive_unit, battery_type, battery_kwh.
Body configuration
bed_type, body_cab_type, seats, seat_rows,
entertainment_system, trailer_type, trailer_body_type, trailer_length_ft,
bus_type, bus_floor_config_type, custom_motorcycle_type,
motorcycle_chassis_type, motorcycle_suspension_type. vPIC answers
"Not Applicable" for categories that do not apply to the vehicle; that is
vPIC's own answer and is preserved rather than nulled.
Occupant protection and active safety
air_bag_loc_front, air_bag_loc_side, air_bag_loc_curtain,
air_bag_loc_knee, air_bag_loc_seat_cushion, seat_belts_all,
other_restraint_system_info, pretensioner, abs, esc, traction_control,
tpms, forward_collision_warning, cib, pedestrian_aeb,
blind_spot_monitoring, blind_spot_intervention, lane_departure_warning,
lane_keep_system, lane_centering_assistance, adaptive_cruise_control,
park_assist, rear_visibility_system, rear_cross_traffic_alert,
rear_automatic_emergency_braking, daytime_running_light, keyless_ignition,
dynamic_brake_support, auto_reverse_system,
automatic_pedestrian_alerting_sound, semiautomatic_headlamp_beam_switching,
adaptive_driving_beam, active_safety_sys_note.
Manufacturing
plant_country, plant_state, plant_city, plant_company_name.
Populating the optional columns. Coverage is genuinely vehicle-dependent —
NHTSA's own response says a missing value means "NHTSA does not have data on the
specific variable", not that the feature is absent. Measured 2026-08-01:
a 2003 Honda Accord populates 45 fields, a 2018 Tesla Model 3 populates 66
(including electrification_level and the ADAS set), a 2014 Peterbilt 388
populates 37, and an unregistered manufacturer populates 4.
additional_error_text and suggested_vin populate on VINs with errors (the
example above with IOQ1234567890ABCD). The sparse fields all have a verified
populating VIN: ncsa_* on 29 of 33 VINs sampled, plant_company_name on 19,
engine_manufacturer and brake_system_type on a 2013 Ford F-150
(1FTFW1ET5DFC10312), battery_kwh on a 2016 Nissan Leaf (1N4BZ0CP0GC300000),
trailer_length_ft and cooling_type on a trailer VIN (4X4TSMH23FS000000),
and blind_spot_intervention, lane_centering_assistance and
rear_automatic_emergency_braking on a 2023 Tesla Model Y
(7SAYGDEE0PF600000). Five fields that never populated across 47 diverse VINs
were removed rather than shipped as permanently empty columns. The remaining
sparse fields also have a recorded populating VIN from the same census:
series and series_2 on a 2017 Toyota Camry (4T1BF1FK5HU123456) and a 2018
Hyundai Tucson (KM8J3CA46JU622173), wheel_base_type, top_speed_mph and
brake_system_desc on the Camry, engine_hp_to on a Mack truck
(1M2AX07C2FM020000), wheel_size_front, wheel_size_rear,
curb_weight_lb and entertainment_system on a 2017 Toyota RAV4
(JTMWFREV0HD100000), active_safety_sys_note on the Tucson, and
air_bag_loc_seat_cushion on the RAV4. vpic_error is
null on a healthy run — that is good news, not a dead column.
Use as an MCP tool
Exposed to AI agents via mcp.apify.com as a "decode these VINs" tool. The
three-state contract matters here: an agent must not read decode_valid: null
as "invalid VIN", and must not treat decode_valid: false on a
clean_with_warnings row as "no data" — the vehicle fields are populated, they
are just caveated by NHTSA.
FAQ
Why is decode_valid false on a row that clearly decoded? Because vPIC
returned a warning code alongside 0 — almost always code 12, a model-year
mismatch. Check decode_status, error_code_meanings and model_year_warning.
The vehicle data is there; NHTSA is telling you it may not be accurate.
What is the batch limit? This actor decodes serially so one bad VIN cannot
take down the rest of the batch. NHTSA's own DecodeVINValuesBatch endpoint
caps at 50 VINs per request (measured: 50 returns Count: 50; 51 and 100
both return Count: 0).
Does extended return more fields? It returns the same 154 field names but
populates roughly three more of them per VIN (measured on three VINs,
2026-08-01).
Is this a determination? No. It decodes the manufacturer's VIN submission to NHTSA. It is not a title, odometer, accident or recall check.
Data source (keyless, no anti-bot)
https://vpic.nhtsa.dot.gov/api/vehicles/decodevinvalues/{vin}(anddecodevinvaluesextended).https://vpic.nhtsa.dot.gov/api/vehicles/GetVehicleVariableValuesList/Error Code— the publishedErrorCodevocabulary, asserted live on every run.
Pricing (Pay Per Result)
Billed per dataset record returned: one row per VIN, including VINs that vPIC reports as invalid (a verified negative is an answer). Runs that fail a drift assertion, or lose vPIC entirely, emit nothing and bill nothing.