VIN Decoder & Recalls
Decode VINs in bulk and get open US safety recalls on the same row: make, model, year, trim, engine, plant, airbags, plus recall component and remedy.
How it works
- 1Open it on Apify
Hit Run on Apify — it opens the tool in the cloud, no install.
- 2Set the inputs
Adjust
vins,includeRecalls,maxItems(sensible defaults are pre-filled). - 3Click Run
The tool runs on Apify’s cloud and collects the data for you.
- 4Export the results
Download as JSON, CSV or Excel, or pipe straight into your app, Google Sheets, or an AI agent.
Pricing
$0.0009 per VIN decoded = $0.9 per 1,000
| You are charged for | When | Price |
|---|---|---|
| VIN decoded | One vehicle decoded from its VIN, with any open safety recalls. VINs that cannot be decoded are never charged. | $0.0009 |
Pay-per-event pricing: you are billed per result, not per subscription. Billing is handled by Apify on your own account. These are the live Apify store prices, in effect since 2026-09-20, and they are what you are actually charged.
Inputs
| Field | What it does | Type |
|---|---|---|
vins | One or more 17-character Vehicle Identification Numbers. Up to 1,000 per run. Dashes and spaces are stripped, letter case does not matter, and duplicates are dropped before anything is charged. A VIN identifies a vehicle, not a person - this Actor looks up no owner, registration or title data. | array |
includeRecalls | On by default. Each decoded vehicle gets its open US safety recall campaigns attached - component, summary, consequence and the manufacturer's remedy. Recall lookups are cached per make, model and year inside the run, so a list of the same few models costs very little extra time. Turn it off if you only want the specification decode; the price per VIN is the same either way. | boolean |
maxItems | A hard stop on how many of the VINs above are decoded, so a long pasted list cannot run away with your budget. Keep it low while you are testing - you pay per decoded vehicle. Hard ceiling 1,000 per run. | integer |
proxyUrls | Leave this empty for a normal run. Fill it in only if you want the traffic to leave through proxy servers you already pay for, one URL per line, in the form http://user:pass@host:port. | array |
What you get
A structured dataset — each result includes fields like:
vinmakemodelmodelYeartrimbodyClassvehicleTypedriveTypefuelTypePrimaryrecallLookuprecallCountExport every run as JSON, CSV or Excel, or send it to your app, a database, Google Sheets, or an AI agent.
Related tools in Developer & Research Tools
Other ready-to-run tools in the same category — all pay-per-use on the Apify cloud.
GitHub Scraper
Search GitHub repos and users: stars, forks, language, topics, licence, plus user bio, company and followers. No token needed. $0.90 per 1,000 rows.
Stack Overflow / Stack Exchange Scraper
Search Stack Overflow and Stack Exchange by keyword or tag. Score, answer count, views, reputation and body text. $2 per 1,000 questions.
Package Registry Scraper (npm + PyPI)
Get npm and PyPI package metadata as JSON. Version, license, author, repo, keywords and npm monthly downloads. $2 per 1,000 packages.
arXiv Scraper
Search arXiv papers by title, author, abstract or category. Get full abstracts, authors, categories, DOI, dates and PDF links. $2 per 1,000 papers.
OpenAlex Scholarly Works Scraper
Search 250M+ OpenAlex papers with no API key. Get titles, authors, venue, year, citations, DOI, OA links and full abstracts. $2.00 per 1,000 papers.
Crossref Scholarly Works Scraper
Search 150M+ papers on Crossref: DOI, title, authors, journal, publisher, date, citations and abstract. No API key. $1.00 per 1,000 works.
Where this tool sits
- Categories
- Developer & Research Tools
VIN Decoder & Recalls API: decode VINs in bulk, with open NHTSA recalls on each row
Paste up to 1,000 VINs and each one comes back as a row describing the vehicle the way the US federal record has it: make, model, year, trim, engine, body, assembly plant and safety equipment. Every open US safety recall filed against that make, model and year sits on the same row, with the fault, what it can lead to and the fix the manufacturer owes. It is not a history report, though: nothing about crashes, titles, mileage or owners, and no way to see whether a recall was already repaired on that particular car.
| Input | 17-character VINs, one per line |
| Output | One row per decoded vehicle, with its open recalls attached |
| Ceiling | 1,000 VINs per run |
| Account needed | None |
| Price | $0.90 per 1,000 vehicles, flat on every plan |
🔍 What VIN Decoder & Recalls API does
Each VIN is decoded against NHTSA's own vehicle record, the specification the manufacturer filed for that car.
Recalls are matched on make, model and year, because that is the level NHTSA publishes them at. So a campaign that only covers some build dates, one plant or one engine still shows up on every car of that model year. The summary names the range.
Model names do not always line up. The decoder calls a truck "Silverado" while the recall list files it as "SILVERADO 1500", "2500" and "3500". When the plain name finds nothing, the run tries the names NHTSA itself lists for that make and year, preferring the one that carries the VIN's own series, so a 1500 never picks up a 3500's recalls. recallModelMatched tells you which name matched.
And sometimes NHTSA's recall lookup returns nothing for a model its own index lists as recalled. In a check of 45 common US vehicles that happened on 5. Those rows say recallLookup: "unavailable" instead of claiming zero, so an unknown never passes for a clean record.
📥 What you give it
{
"vins": ["1HGCM82633A004352", "3GCUKREC5JG123456", "5YJ3E1EA7JF006588"],
"includeRecalls": true,
"maxItems": 25
}
| Field | If you leave it out | What it is |
|---|---|---|
vins | a free sample row, no lookup | Up to 1,000 VINs. Case, dashes and spaces do not matter, and duplicates are dropped before anything is charged. |
includeRecalls | on | Attach open recalls. Turn it off for the specification alone; the price per vehicle is the same. |
maxItems | 25 | How many VINs from the list get decoded, 1 to 1,000. The form starts at 25, so raise it when you paste more. |
proxyUrls | empty | Optional, and only if you want the requests to go out through servers of your own, as http://user:pass@host:port. Leave it empty for a normal run. |
📤 What you get back
A real row from a real run, with the recall list cut to the first of its seven campaigns and the remedy text shortened:
{
"ok": true,
"charged": true,
"recordType": "vehicle",
"vin": "3GCUKREC5JG123456",
"make": "CHEVROLET",
"model": "Silverado",
"modelYear": 2018,
"trim": "LT",
"bodyClass": "Pickup",
"vehicleType": "TRUCK",
"driveType": "4WD/4-Wheel Drive/4x4",
"fuelTypePrimary": "Gasoline",
"recallLookup": "ok",
"recallCount": 7,
"recalls": [
{
"campaignNumber": "19V645000",
"reportReceivedDate": "2019-09-06",
"component": "SERVICE BRAKES, HYDRAULIC:POWER ASSIST:VACUUM",
"summary": "General Motors LLC (GM) is recalling certain 2015-2017 Cadillac Escalade, 2014-2018 Chevrolet Silverado, GMC Sierra, 2015-2018 Chevrolet Suburban, Tahoe, GMC Yukon vehicles. The amount of vacuum created by the vacuum pump may decrease over time.",
"consequence": "As the vacuum level drops, the brake assist decreases, increasing braking effort, extending the distance required to stop the vehicle, thereby increasing the risk of a crash.",
"remedy": "GM will notify owners, and dealers will reprogram the Electronic Brake Control Module, free of charge. The recall began October 8, 2019. ...",
"notes": "Owners may also contact the National Highway Traffic Safety Administration Vehicle Safety Hotline at 1-888-327-4236 (TTY 1-800-424-9153), or go to www.safercar.gov.",
"manufacturer": "General Motors LLC",
"parkIt": false,
"parkOutSide": false,
"overTheAirUpdate": false
}
],
"series": "1500",
"doors": 4,
"engineCylinders": 8,
"displacementL": 5.3,
"engineHorsepower": null,
"electrificationLevel": null,
"transmissionStyle": null,
"transmissionSpeeds": null,
"manufacturer": "GENERAL MOTORS LLC",
"plantCountry": "MEXICO",
"plantCity": "SILAO",
"plantState": null,
"gvwr": "Class 2F: 7,001 - 8,000 lb (3,175 - 3,629 kg)",
"abs": null,
"esc": null,
"tpms": "Direct",
"airBagLocFront": "1st Row (Driver and Passenger)",
"airBagLocSide": "1st Row (Driver and Passenger)",
"airBagLocCurtain": "All Rows",
"seatBeltsAll": "Manual",
"recallModelMatched": "SILVERADO 1500",
"nhtsaErrorCodes": "1",
"nhtsaErrorText": "1 - Check Digit (9th position) does not calculate properly",
"vehicleDescriptor": "3GCUKREC*JG",
"scrapedAt": "2026-09-30T02:37:59.642Z"
}
| Field | What it is |
|---|---|
recallLookup | Read this before recallCount. ok: the recall list answered and the campaigns are attached. none: it answered and has no campaign for this vehicle. unavailable: the count is unknown, not zero. skipped: you turned recalls off. |
recallCount, recalls | How many campaigns apply, and each one in full: campaign number, date reported, component, summary, consequence, remedy, and the "park it" and "park outside" warnings as parkIt and parkOutSide. |
recallModelMatched | The model name the recall list matched. Usually the same as model. |
modelYear | The model year, which is not always the year the car was built. |
trim | Sometimes a slash-separated list, when one VIN pattern covers several trims. |
nhtsaErrorCodes, nhtsaErrorText | Whatever the decoder flagged. Code 1, a check digit that does not add up, is common on VINs that decode perfectly well. |
abs, esc, tpms, airBagLocFront, airBagLocSide, airBagLocCurtain | Safety equipment as the manufacturer filed it. |
Any field the manufacturer never filed comes back as null. Older and low-volume vehicles have more of those than a recent mass-market car, and running them again does not change that.
🧾 Reading the output
| Row | How to spot it | Charged |
|---|---|---|
| A vehicle | charged: true, recordType: "vehicle" | yes |
| The sample row | _sample: true, charged: false. Only when the run had no VINs at all | no |
| A diagnostic row | _diagnostic: true, charged: false, and an errorCode | no |
The sample row carries recordType: "vehicle" as well, so filter on charged, not on recordType, to keep only the vehicles you paid for.
errorCode | What happened |
|---|---|
BAD_INPUT | The value is not 17 characters, or it contains I, O or Q, which no VIN does. |
NO_RESULTS | NHTSA holds no vehicle for that VIN, which is common for cars never sold in the US, or it read the VIN as incomplete. |
RECALL_LOOKUP_FAILED | The vehicle decoded but its recalls could not be fetched. The whole vehicle is in the row anyway, free. Run that VIN again later for its recalls. |
NETWORK | The decoder did not answer for that group of VINs. |
TIME_BUDGET | The run hit its time limit before it reached that VIN. |
On a long list of bad VINs, the first 50 failures get a row each and the rest are collected in one NO_RESULTS row whose skipped list names every VIN and its reason. If 150 VINs in a row produce no vehicle at all, the run stops and says so, since the list is clearly not VINs.
▶️ How to run it
1. Open VIN Decoder & Recalls API and click Try for free. 2. Paste your VINs into VINs, one per line. 3. Set Maximum VINs to process to at least the number of VINs you pasted. 4. Leave Attach open safety recalls ticked, unless the specification is all you want. 5. Click Start, then export the dataset as CSV, JSON or Excel, filtered on charged.
💰 How much does it cost?
$0.90 per 1,000 vehicles, flat on every Apify plan. That is $0.0009 per decoded vehicle, with recalls or without.
Not charged: the sample row, values that are not VINs, VINs NHTSA has no vehicle for, duplicates in your list, and a vehicle whose recall lookup failed, which arrives free. A list of 400 VINs that all decode comes to $0.36.
💡 What people use it for
- A lot full of trade-ins, where an open airbag or fuel-pump campaign should turn up before the car is listed, not after a buyer finds it.
- A fleet checked every week, where only the new campaigns matter: compare
recallCountand the campaign numbers against the last run. - A listings feed where sellers type the model any way they like, and the specification should come from the VIN instead.
- A book of VINs for claims or rating work that needs make, model, year, body and safety equipment without anyone retyping them.
🚧 What it does not do
- No history. No accidents, titles, salvage brands, odometer readings, thefts or service records. None of that is in the federal record.
- No owners. Nothing about who owns or registered the car, and no field that would ask for it.
- No per-car recall status. A campaign that applies is not the same as a repair still owed. Whether the work was done is known only to the manufacturer and its dealers.
- US vehicles only. A car never certified for US sale decodes partly or not at all, and has no recall record here.
- Nothing before 1981. Older VINs are not 17 characters and are refused.
- Only federally filed recalls. Recalls issued outside the US, and service campaigns never filed with NHTSA, are not included.
- At most 60 campaigns per row, and 1,000 VINs per run. Split longer lists across runs.
- Not instant on mixed lists. Recalls are fetched once per make, model and year, so a list of the same few models is quick and hundreds of different models take minutes.
🧭 Which vehicle data scraper do you need?
| If you want | Use |
|---|---|
| The factory specification and open US recalls for a VIN | This one |
| Used-car listings in eight European countries | AutoScout24 Scraper |
| Car listings in Brazil, priced against the FIPE table | Webmotors Scraper |
| Pump prices at UK filling stations | UK Fuel Prices Scraper |
❓ Questions people ask
Is this a vehicle history report? No, and it cannot be made into one. If the car's past is what you need, buy a history report.
Does a recallCount of 0 mean the car is clean? Only when recallLookup says none. When it says unavailable, the honest answer is that nobody knows yet.
Why does a row say the check digit does not calculate? That is the decoder's code 1, and it is common on VINs that decode perfectly well. It often means one character was copied wrong, so read the VIN again, but the row is still a real decode.
What if a VIN is wrong or made up? You get one free row saying why, and the run carries on with the others.
Can I run it on a schedule? Yes. Nothing is kept between runs, so the same list every week is safe, and comparing campaign numbers shows what is new.
Do I need an API key or an account? No. Paste the VINs and start.
🆘 If something breaks
Open the Issues tab on the actor page. Include the run ID and the VINs that went wrong, with the errorCode from their rows.