US NHTSA Vehicle Recall Monitor
Pricing
$4.00 / 1,000 result items
US NHTSA Vehicle Recall Monitor
Query and monitor official NHTSA vehicle safety recalls by vehicle or campaign.
Pricing
$4.00 / 1,000 result items
Rating
0.0
(0)
Developer
hugo liu
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
5 hours ago
Last modified
Categories
Share
Query and monitor official U.S. National Highway Traffic Safety Administration (NHTSA) vehicle recalls by campaign number or vehicle identity. Get normalized, traceable recall rows with manufacturer, affected component, remedy, report date, safety flags, and an official source URL.
Use it for fleet and dealer checks, vehicle-safety research, compliance feeds, automotive data products, and scheduled recall monitoring. It is a focused wrapper around NHTSA's structured APIs: easy to run, predictable to integrate, and explicit about what a vehicle-level recall lookup can—and cannot—prove.
Before you run
- For a one-off API call, use
lookuporexport.monitoris stateful and emits only new or changed rows after the monitor snapshot is established. - Actor usage costs $0.004 per result, equivalent to $4 per 1,000
results, under Pay Per Event pricing. Runs with zero results have no
result-itemusage charge. See the Pricing tab for the current terms. - Data is returned from NHTSA at fetch time. This Actor does not provide a real-time freshness guarantee or an SLA for upstream publication delays.
- Start with an exact
campaignNumberor a specificmake+model+modelYearand a smallmaxResults. Amake+modelYearquery first enumerates models and then queries them serially;maxResults: 1does not avoid model enumeration, and an empty sweep may still contact every model.maxResults: 0can fan out across all enumerated models and is not an unlimited historical archive. - Successful runs have a per-run Dataset. This Actor does not automatically rename it; retain the returned Dataset ID or name/copy important results before relying on your account's default retention policy.
What this Actor does
- Looks up an exact NHTSA campaign number.
- Looks up recalls for one
make+model+modelYearvehicle line. - Discovers NHTSA-recognized models for a
make+modelYear, then queries each model with the same bounded result limit. - Filters normalized records by campaign number and inclusive report-date windows.
- Normalizes dates, vehicle identity, booleans, missing values, and source URLs into a stable Dataset contract.
- Supports current lookup, bounded export, and incremental monitor modes.
- Emits
CURRENT,ADDED, orUPDATEDrows withchangedFields, a content hash, and a stable idempotency key.
Why teams use it
NHTSA recall data is most useful when campaign details and operational flags are available in a single, automation-ready row. This Actor removes repetitive API plumbing and preserves the official context needed for a fleet dashboard, customer workflow, research dataset, or AI agent.
Common use cases:
- Check the current recall campaigns for a make, model, and model year.
- Retrieve one campaign for a compliance or service workflow.
- Export a historical report-date window for research.
- Schedule a stable vehicle scope and alert only when a record is new or changed.
Data source and lookup scope
The Actor uses the official NHTSA vehicle safety APIs:
| Input shape | Official endpoint | Behavior |
|---|---|---|
campaignNumber | /recalls/campaignNumber | Exact campaign lookup; takes precedence over vehicle fields |
make + model + modelYear | /recalls/recallsByVehicle | One recall query for the exact vehicle line |
make + modelYear | /products/vehicle/models, then /recalls/recallsByVehicle | Enumerates NHTSA-recognized models and queries each one |
NHTSA is a structured lookup API. This Actor does not provide arbitrary
full-text recall search, manufacturer-text search, VIN decoding, ownership
history, or a VIN-level determination that a particular vehicle is affected.
A make/year query can create multiple upstream requests; start with a specific
model or campaign and a small maxResults.
Request and resource notes
- An exact
campaignNumberlookup makes one campaign request. An exactmake+model+modelYearlookup makes one vehicle request. - A
make+modelYearlookup makes one model-enumeration request followed by one recall request per returned model, serially. WithmaxResults > 0, the Actor can stop after enough normalized rows; with no matches it may query all enumerated models. maxResultslimits normalized rows after source filtering. It is not a request-count, latency, or cost guarantee, andmaxResults: 0removes only the Actor-side row cap.sourceRecordIdincludes campaign, make, model, and model year. The same campaign found through different query shapes can therefore have a different row identity; for cross-call deduplication prefercampaignNumber, or use it with normalized vehicle fields when vehicle scope matters.- The boolean safety fields are normalized with strict source semantics:
falsemeans the source value was nottrue; it is not confirmation that a vehicle is safe or that no precaution is needed.
Run modes
| Mode | What it returns | State behavior |
|---|---|---|
lookup | Matching current records as CURRENT | Does not read or change monitor state |
export | A bounded current-source date-window result as CURRENT | Does not read or change monitor state |
monitor | New and changed records as ADDED or UPDATED | Reads and updates the named Key-Value Store |
Use lookup for a focused check, export for a defined report, and monitor
for recurring change detection. The default mode is monitor, although a
campaign or vehicle scope is still required.
Quick start
Apify Console
- Open the Actor and select Input.
- Enter either
campaignNumber, ormakeplusmodelYear(with optionalmodel). - Choose
lookup,export, ormonitor. - Add a report-date window and keep
maxResultssmall for the first run. - Click Start, then inspect the Dataset or download JSON, CSV, or Excel from the Output tab.
Apify CLI
After installing and authenticating the Apify CLI, look up one campaign:
apify call <ACTOR_ID> \--input '{"mode":"lookup","campaignNumber":"26V123000","maxResults":1}' \--output-dataset
Or query one vehicle line:
apify call <ACTOR_ID> \--input '{"mode":"lookup","make":"Honda","model":"Civic","modelYear":"2023","maxResults":10}' \--output-dataset
<ACTOR_ID> can be the Actor ID or an authorized Actor name. A valid campaign
or vehicle query with no matches completes successfully with zero Dataset items.
REST API
Start a run with a JSON request body:
curl -X POST \-H "Authorization: Bearer $APIFY_TOKEN" \-H "Content-Type: application/json" \--data '{"mode": "lookup","make": "Honda","model": "Civic","modelYear": "2023","maxResults": 25}' \"https://api.apify.com/v2/acts/<ACTOR_ID>/runs?waitForFinish=60"
Read the returned defaultDatasetId through the Dataset API:
GET https://api.apify.com/v2/datasets/<DATASET_ID>/items?format=json&clean=trueGET https://api.apify.com/v2/datasets/<DATASET_ID>/items?format=csv&clean=true&attachment=trueGET https://api.apify.com/v2/datasets/<DATASET_ID>/items?format=xlsx&clean=true&attachment=true
Use limit and offset for pagination. Keep $APIFY_TOKEN in an environment
variable; never put it in Actor input, source code, logs, or Dataset records.
API run lifecycle
The POST request starts an Apify run; it does not return Dataset rows directly.
If waitForFinish=60 returns a non-terminal status such as RUNNING, keep the
returned runId and poll GET /v2/actor-runs/<RUN_ID> or use a Webhook. Read
defaultDatasetId after the run reaches SUCCEEDED. A successful empty Dataset
is valid; in monitor mode it can mean that no recall changed, not that NHTSA
had no matching recall.
Input API reference
The input is a JSON object. The ./.actor/input_schema.json is the machine-readable contract used by the Console and API.
| Field | Type / default | Description |
|---|---|---|
mode | enum, "monitor" | monitor, lookup, or export. |
campaignNumber | string | NHTSA campaign in the form two digits, one letter, six digits, for example 23V769000. When present, it overrides vehicle lookup. Punctuation and letter case are normalized for validation. |
make | string | Vehicle make, used with modelYear. |
model | string | Optional vehicle model. Omit it to enumerate models for the make/year. |
modelYear | four-digit string | Model year from 1900 through 2100, used with make. |
recalledSince | YYYY-MM-DD | Inclusive lower bound for NHTSA ReportReceivedDate. |
recalledUntil | YYYY-MM-DD | Inclusive upper bound for ReportReceivedDate. |
maxResults | integer, 500 | Maximum emitted rows. Range: 0–25000; 0 removes the Actor-side cap after source queries and filtering, but does not limit make/year fan-out. |
emitInitialSnapshot | boolean, true | In monitor, emit first-seen records as ADDED; set false to seed state without emitting the initial snapshot. |
monitorId | string | Optional stable namespace for separate monitors sharing a state store. |
stateStoreName | string, "us-nhtsa-monitor-state" | Named Apify Key-Value Store used for monitor fingerprints. |
Query behavior and validation
- Provide
campaignNumber, or providemakeandmodelYear. A model is optional for a whole-make/model-year sweep. - Dates must be real calendar dates in
YYYY-MM-DD; invalid dates such as2026-02-30are rejected. recalledSincecannot be afterrecalledUntil.campaignNumberis validated against the NHTSA campaign shape, such as23V769000.- Filtering is applied after source normalization and before
maxResults. - For make/year sweeps, model enumeration and upstream recall requests still
occur according to the lookup scope even when
maxResultsis small. - Records without a campaign number are discarded because they cannot provide a stable source identity.
- A valid query with no matches returns
SUCCEEDEDwith an empty Dataset. Invalid input, malformed API JSON, or an unrecoverable HTTP error fails the run with an explanatory message.
Example inputs
Monitor one campaign
{"mode": "monitor","campaignNumber": "26V123000","maxResults": 1,"monitorId": "campaign-26V123000"}
Look up one current vehicle line
{"mode": "lookup","make": "Honda","model": "Civic","modelYear": "2023","maxResults": 10}
Export a historical vehicle-recall window
{"mode": "export","make": "Ford","modelYear": "2022","recalledSince": "2015-01-01","recalledUntil": "2015-12-31","maxResults": 250}
Valid empty result and invalid input
An exact lookup for a campaign with no NHTSA rows is valid and returns an empty Dataset:
{"mode": "lookup","campaignNumber": "26V658000","maxResults": 1}
An input such as {"make":"Honda"} is rejected because modelYear is
required for a vehicle lookup. An input such as
{"campaignNumber":"not-a-campaign"} is rejected before the API is called.
For abnormal upstream behavior, the Actor retries bounded transient failures
such as 429, 5xx, network errors, and timeouts. Malformed API JSON and other
unrecoverable responses fail the run with an explanatory error; they are not
silently converted to an empty Dataset.
Output API reference
Each Dataset item is one normalized NHTSA recall record. Empty source values are
represented by empty strings, false booleans, or null dates according to the
field contract.
Representative historical recall output
This trimmed example is based on a real NHTSA recall record. Hash values and timestamps are placeholders for the values generated by the run; the complete row contains every field listed below.
{"source": "nhtsa","sourceRecordId": "recall:15V123000:KIA:SOUL:2014","recordType": "recall","campaignNumber": "15V123000","actionNumber": "","manufacturer": "Kia Motors America","make": "KIA","model": "SOUL","modelYear": "2014","component": "VEHICLE SPEED CONTROL:ACCELERATOR PEDAL","potentialUnitsAffected": "208858","summary": "Kia Motors America is recalling certain model year 2014-2015 Soul vehicles; a section of the accelerator pedal may bend and fracture.","consequence": "A bent or broken accelerator pedal may make it difficult to accelerate, increasing the risk of a crash.","remedy": "Kia will notify owners and dealers will add a supporting rubber underneath the pedal stopper, free of charge.","reportReceivedDate": "2015-03-02","doNotDrive": false,"parkOutside": false,"overTheAirUpdate": false,"sourceUrl": "https://www.nhtsa.gov/recalls?nhtsaId=15V123000","changeType": "CURRENT","changedFields": [],"detectedAt": "2026-09-02T00:00:00.000Z","contentHash": "<sha256>","idempotencyKey": "<sha256>"}
The three boolean flags are source indicators, not a VIN-level safety
assessment. For monitor, the same content fields are accompanied by ADDED
or UPDATED; changedFields lists normalized fields that changed since the
prior snapshot. CURRENT is used by lookup and export.
Identity and monitor metadata
| Field | Type | Description |
|---|---|---|
source | string | Always nhtsa. |
sourceRecordId | string | Stable identity for a vehicle-scoped row in the form recall:<campaign>:<make>:<model>:<modelYear>. For cross-query deduplication, prefer campaignNumber because the same campaign can appear with different vehicle scope. |
recordType | string | Always recall. |
changeType | string | ADDED, UPDATED, or CURRENT. |
changedFields | string[] | Normalized fields changed since the previous monitor snapshot; empty for ADDED and CURRENT. |
detectedAt | ISO timestamp | Time this Actor produced the row. |
contentHash | string | SHA-256 hash of the normalized source snapshot, excluding derived monitor metadata. |
idempotencyKey | string | Stable key for monitor scope, source record, and content version. Use it to deduplicate retries. |
Recall fields
| Field | Type | Description |
|---|---|---|
campaignNumber | string | Official NHTSA campaign number. |
actionNumber | string | NHTSA action number when supplied. |
manufacturer | string | Manufacturer named by NHTSA. |
make | string | Vehicle make. |
model | string | Vehicle model. |
modelYear | string | Vehicle model year. |
component | string | Affected vehicle component. |
potentialUnitsAffected | string | Reported potentially affected units. |
summary | string | Recall summary. |
consequence | string | Reported safety consequence. |
remedy | string | Reported remedy. |
notes | string | Additional NHTSA notes. |
reportReceivedDate | string or null | Normalized NHTSA report date in YYYY-MM-DD. |
doNotDrive | boolean | NHTSA parkIt safety flag. |
parkOutside | boolean | NHTSA parkOutSide safety flag. |
overTheAirUpdate | boolean | Whether an over-the-air update is indicated. |
sourceUrl | string | Official NHTSA recall page for the campaign. |
Dataset and output links
The Actor pushes structured JSON rows only. Apify generates these views from the same Dataset:
- JSON:
.../items?format=json&clean=true - CSV:
.../items?format=csv&clean=true&attachment=true - Excel:
.../items?format=xlsx&clean=true&attachment=true
Successful non-empty runs have their own Dataset ID. If long-term retention is required, name or copy the Dataset after the run; this Actor does not merge separate runs into a shared output Dataset. Dataset lifetime follows the retention rules of your Apify account and plan; do not treat an unnamed per-run Dataset as a permanent archive.
Monitoring and delivery semantics
In monitor mode:
- Records are normalized and deduplicated by
sourceRecordId. - The Actor compares normalized content with the snapshot in the named Key-Value Store.
- New records become
ADDED; changed records becomeUPDATEDwithchangedFields. - Dataset delivery completes before the checkpoint is written.
This is safe at-least-once delivery. If Dataset delivery succeeds but the
checkpoint write fails, a later run may emit the same event again; downstream
consumers should deduplicate with idempotencyKey. Records absent from a later
source response are not emitted as REMOVED, because absence may reflect model
enumeration, filtering, upstream coverage, or source-window behavior rather than
an official withdrawal.
For scheduled monitoring, keep the same monitorId, stateStoreName, and
query scope so later runs compare against the same snapshot.
The HTTP layer starts requests serially within one process, waits one second by
default between request starts, retries transient network errors, 429, and
5xx responses with bounded exponential backoff and jitter, and honors
Retry-After when supplied. These locks and limits are process-local; they do
not provide account-wide rate limiting or cross-container exactly-once
delivery.
Reliability and limitations
- NHTSA endpoints can change fields, throttle requests, or have maintenance windows. The Actor retries transient failures within a finite budget.
- A make/year query depends on the model names currently returned by NHTSA; spelling changes or incomplete model enumeration can affect coverage.
- A recall is reported by NHTSA for a make/model/year scope. It is not proof of eligibility for a particular VIN, and this Actor does not verify repair completion or ownership.
falseindoNotDrive,parkOutside, oroverTheAirUpdateis not a safety clearance; it means the normalized source flag was nottrue.- The Actor reports what NHTSA publishes. It does not independently verify defect claims, remedy effectiveness, or legal status.
- A local process lock is not a distributed lock. Strict cross-container coordination would require a shared transactional store and global limiter.
Local development
Requirements: Node.js 20 or newer.
npm installnpm testnpm run buildapify validate-schemanpm run test:real
npm test uses deterministic fixtures and injected failures, including
malformed JSON, 429/Retry-After, 5xx, timeout, rate limiting, state
ordering, and delivery failure. The bounded real smoke script checks a current
campaign, a historical campaign, a valid empty result, and output identity/date
fields; it is not an unbounded vehicle-recall export.
Attribution
This Actor consumes public NHTSA data. Review the current NHTSA API terms,
availability, and usage guidance before operating at scale. Preserve
sourceUrl and campaignNumber when passing records downstream so users can
inspect the authoritative recall notice.