# NHTSA Vehicle Recalls & Complaints (`opendatatools/nhtsa-recalls-complaints`) Actor

Returns every NHTSA safety recall and consumer complaint for a US vehicle, by VIN or by make, model and year. Dates normalized to ISO 8601.

- **URL**: https://apify.com/opendatatools/nhtsa-recalls-complaints.md
- **Developed by:** [Nico Poland](https://apify.com/opendatatools) (community)
- **Categories:**
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $3.00 / 1,000 safety record returneds

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?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## NHTSA Vehicle Recalls & Complaints

Returns every NHTSA safety recall and consumer complaint for a US vehicle,
by VIN or by make, model and year. Dates normalised to ISO 8601 and no
per-run start fee.

### What it does

Give it a VIN, or a make, model and year, and get back every safety
recall campaign and every consumer complaint the US National Highway
Traffic Safety Administration holds for that vehicle, as one row each.

VINs are decoded through NHTSA's own vPIC service first, so "what is wrong
with this car" is a single call rather than three.

**Three things this does that the free API does not:**

1. **Dates come out as ISO 8601.** NHTSA's two endpoints disagree with
   each other: recalls are `DD/MM/YYYY`, complaints are `MM/DD/YYYY`. The
   formats are identical-looking for the first twelve days of any month,
   so merging them naively corrupts dates by up to eleven months while
   still looking plausible. `07/08/2025` is 7 August in a recall and 8 July
   in a complaint.
2. **An empty result explains itself.** NHTSA's two endpoints do not share
   a model vocabulary: recalls accept `F-150`, complaints need
   `F-150 SUPERCREW`. Ask for an F-150 and you get its 14 recalls plus a
   free row telling you which model names its complaints are filed under,
   instead of a silent zero.
3. **No per-run start fee.** Every comparable Actor charges $0.05–$0.25
   just to start, which dwarfs the record cost for a single lookup. This
   one leaves the Actor start event at Apify's default of $0.00005.

**What it does not do.** It does not tell you whether a recall has been
performed on a specific car, NHTSA's public API does not expose that. It
covers US vehicles only.

### Input

Give `vins`, `vehicles`, or both. At least one is required.

| Field | Type | Required | Default | Description |
|---|---|---|---|---|
| `vins` | array of strings | one of | n/a | 17-character VINs. Max 200. |
| `vehicles` | array of objects | one of | n/a | `{"make", "model", "modelYear"}`. Max 200. |
| `dataTypes` | array | no | `["recalls","complaints"]` | Which records to return. |
| `maxResults` | integer | no | `1000` | Stop after this many records. |
| `failOnEmpty` | boolean | no | `false` | Operator health check; leave off. |

```json
{
  "vins": ["1HGCV1F13LA000000"],
  "vehicles": [{ "make": "Honda", "model": "Civic", "modelYear": "2019" }],
  "dataTypes": ["recalls", "complaints"],
  "maxResults": 1000
}
```

### Output

One row per record. A real recall row from a real run:

```json
{
  "record_type": "recall",
  "make": "HONDA",
  "model": "CIVIC",
  "model_year": "2019",
  "campaign_number": "20V314000",
  "manufacturer": "Honda (American Honda Motor Co.)",
  "component": "FUEL SYSTEM, GASOLINE:DELIVERY:FUEL PUMP",
  "reported_on": "2020-05-28",
  "summary": "The low-pressure fuel pump inside the fuel tank may fail.",
  "consequence": "If the fuel pump fails, the engine can stall while driving, increasing the risk of a crash.",
  "remedy": "Honda will notify owners and dealers will replace the fuel pump assembly, free of charge.",
  "park_it": false,
  "park_outside": false,
  "over_the_air_update": false,
  "record_url": "https://www.nhtsa.gov/recalls?nhtsaId=20V314000",
  "source": "NHTSA (US National Highway Traffic Safety Administration)",
  "license": "US Government work, public domain",
  "retrieved_at": "2026-09-06T12:00:00+00:00"
}
```

And a complaint:

```json
{
  "record_type": "complaint",
  "make": "HONDA",
  "model": "CIVIC",
  "model_year": "2019",
  "odi_number": "11675912",
  "component": "UNKNOWN OR OTHER",
  "incident_on": "2025-07-01",
  "reported_on": "2025-07-24",
  "summary": "AIR CONDITIONING EVAPORATOR DIED AT 86,000 MILES.",
  "crash": false,
  "fire": false,
  "injuries": 0,
  "deaths": 0,
  "partial_vin": "2HGFC3B30KH"
}
```

| Field | Type | Description |
|---|---|---|
| `record_type` | string | `recall`, `complaint`, or a free diagnostic row (below). |
| `campaign_number` | string | NHTSA recall ID, what a dealer needs. Recalls only. |
| `odi_number` | string | NHTSA complaint ID. Complaints only. |
| `reported_on` | string | ISO 8601. Recall: date NHTSA received it. Complaint: date filed. |
| `incident_on` | string | ISO 8601 date the incident happened. Complaints only. |
| `park_it` | boolean | **`true` means NHTSA says stop driving the vehicle.** |
| `park_outside` | boolean | `true` means park away from buildings, fire risk. |
| `crash`, `fire` | boolean | Reported by the complainant. |
| `injuries`, `deaths` | integer | Counts. `0` is a real answer, not a missing value. |
| `partial_vin` | string | The truncated 11-character VIN NHTSA publishes. Identifies a vehicle, never a person. |
| `record_url` | string | NHTSA's page for the record, so any row can be checked by hand. |

#### Free diagnostic rows

Three row types explain rather than deliver, and are **never charged for**:

| `record_type` | Meaning |
|---|---|
| `no_records` | NHTSA holds nothing under that model name, with the names it does use. |
| `vin_error` | The VIN could not be used, and why (wrong length, contains I/O/Q, not decodable). |
| `lookup_error` | NHTSA did not respond for that vehicle. Other vehicles in the run still return. |

A run of 50 VINs with two typos returns 48 answers and two explanations,
not a failure.

### Pricing

Pay per event. You are charged **$0.003 per safety record returned**, plus
Apify's standard $0.00005 Actor start event, **no per-run start fee**.

**Example:** a VIN lookup returning 5 recalls costs 5 × $0.003 + $0.00005 =
**$0.015**. A full recalls-and-complaints pull for a popular model (about
350 records) costs **$1.05**.

You are never charged for diagnostic rows, failed runs, or anything beyond
your `maxResults`.

### Limits and refresh cadence

- **Coverage:** US vehicles only, as held by NHTSA.
- **Freshness:** NHTSA adds recalls and complaints continuously. Responses
  are cached for 6 hours; VIN decodes for 30 days, since a VIN's make,
  model and year never change.
- **Throughput:** up to 200 VINs and 200 vehicles per run, 2 concurrent
  requests to each NHTSA host.
- **Model spelling** must match NHTSA's, which differs between its two
  endpoints, hence the `no_records` row. VIN lookup avoids the problem
  entirely and is the more reliable route.
- **Recall status is not per-vehicle.** This tells you a campaign applies
  to that model; it cannot tell you whether a particular car has had the
  work done.
- **NHTSA disclaims accuracy and completeness** for its own data, and so
  do we. This Actor reports what NHTSA holds, unmodified except for date
  normalisation and whitespace.

### Attribution

Data from the [US National Highway Traffic Safety
Administration](https://www.nhtsa.gov/nhtsa-datasets-and-apis), a work of
the US federal government and therefore in the public domain. Source and
retrieval time are stamped on every row.

Complaint summaries are consumer-written text as published by NHTSA. This
Actor passes them through unchanged and makes no attempt to identify
complainants.

This Actor is not affiliated with or endorsed by NHTSA.

### Changelog

See the Changelog tab.

### Issues

Report problems on the Issues tab. Please include the run ID and the
vehicle. Breakage is normally fixed within one working day.

# Actor input Schema

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

17-character Vehicle Identification Numbers. Each is decoded through NHTSA's own vPIC service, then its recalls and complaints are looked up. A VIN that cannot be decoded returns an explanation row, free of charge, without failing the run.

## `vehicles` (type: `array`):

Vehicles by make, model and year, when you do not have a VIN. Each entry needs all three, e.g. {"make": "Honda", "model": "Civic", "modelYear": "2019"}. Spelling must match NHTSA's own, which is why VIN lookup is more reliable.

## `dataTypes` (type: `array`):

Which records to return. Complaints are far more numerous than recalls and are often a leading indicator of one.

## `maxResults` (type: `integer`):

Stop after this many records. A popular model can have hundreds of complaints, so this defaults low. You are never charged for more than you receive.

## `failOnEmpty` (type: `boolean`):

Leave this off for normal use. The daily monitor run turns it on so that 'succeeded but returned nothing' shows up as a failure instead of passing silently.

## Actor input object example

```json
{
  "vins": [
    "1HGCV1F13LA000000"
  ],
  "vehicles": [
    {
      "make": "Honda",
      "model": "Civic",
      "modelYear": "2019"
    }
  ],
  "dataTypes": [
    "recalls"
  ],
  "maxResults": 1000,
  "failOnEmpty": false
}
```

# Actor output Schema

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

Every row this run produced, in the default dataset.

# 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": [],
    "vehicles": [
        {
            "make": "Honda",
            "model": "Civic",
            "modelYear": "2019"
        }
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("opendatatools/nhtsa-recalls-complaints").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": [],
    "vehicles": [{
            "make": "Honda",
            "model": "Civic",
            "modelYear": "2019",
        }],
}

# Run the Actor and wait for it to finish
run = client.actor("opendatatools/nhtsa-recalls-complaints").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": [],
  "vehicles": [
    {
      "make": "Honda",
      "model": "Civic",
      "modelYear": "2019"
    }
  ]
}' |
apify call opendatatools/nhtsa-recalls-complaints --silent --output-dataset

```

## MCP server setup

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

```

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/FbWcOBs7oohTz7r2i/builds/fhtgXvZxL1lilSDso/openapi.json
