CPSC Product Recalls API — US Consumer Product Recall Watch
Pricing
from $1.00 / 1,000 recall returneds
CPSC Product Recalls API — US Consumer Product Recall Watch
US product recalls from the CPSC database by product words and date, or only new and updated ones: products, hazards, injuries, remedy, firms and the recall page; failed or unchanged rows are never charged. Not affiliated with or endorsed by the U.S. Consumer Product Safety Commission (CPSC).
Pricing
from $1.00 / 1,000 recall returneds
Rating
0.0
(0)
Developer
COMPASS DEV
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
a day ago
Last modified
Share
Returns US consumer product recalls from the CPSC recall database, filtered by product words and recall date, or only new and updated recalls since your last run: recall number and date, products, hazards, injuries, remedy, firms and the recall page; failed or unchanged rows are never charged.
Give product words (helmet, power bank, crib, a model number) or none, and a window; get one flat row per recall of the U.S. Consumer Product Safety Commission (CPSC): the title, what the recall covers, the products and their types, the units recalled, the hazard, the injuries reported, the remedy (refund, replace, repair), the manufacturers, importers, distributors and retailers, where it was sold, the country of manufacture, photo links and the recall page on cpsc.gov. Built for retailers, marketplaces, importers, compliance and product-safety teams, newsrooms and AI agents that need US product recalls without polling cpsc.gov. Not affiliated with or endorsed by the U.S. Consumer Product Safety Commission (CPSC).
What it does
- Export mode: every recall dated in the window (default: the last 90 days) whose title, product names, models, product types or description hold every word of an entry, newest first, one flat row per recall. No words: every recall of the window.
- Watch mode (give a watch list name in
stateName): remembers every recall it returned and gives only:baseline: the first run of the list;new: a recall the list did not have;changed: CPSC updated the notice (its last publish date, title, products, hazard, remedy, units, injuries or firms;changedFieldsandpreviousValuessay what and from what);- unchanged recalls are free and left out (
includeUnchanged: truereturns them as free rows). - A watch run with nothing new or updated returns exactly one free
no_datarow that says so.
- No contacts, no personal data: the firms' phone numbers and email addresses are never returned (the notice's
ConsumerContactis not read into any row, and a phone number or email address inside a text becomes "[phone on the recall page]" or "[email on the recall page]"; the recall page inurlhas them). A firm whose name is, or may be, a person's (for example a sole trader trading under their own name) is left out of the recall's fields:firmNamesOmittedistrue, the name is removed from every text, a text that still holds a word of it isnull, and a title that named it becomes a neutral title such as "Recall: Table Lamps". When in doubt, the name is removed. The recall itself is returned and charged like any other. - One read per run: the window is read once (one request; a window over a year, one request per year) and every entry is matched in it. A recall that matches two entries is returned and charged once, under the first.
- You are never charged for failed results: failed, no_data and unchanged rows are free.
Quick start
Bike helmet recalls of the last 90 days:
{ "queries": ["helmet"] }
Watch every new or updated recall (the first run is the baseline; later runs return only new and updated recalls; run it daily with an Apify schedule):
{ "stateName": "cpsc-recalls", "sinceDays": 30 }
Recalls of power banks, cribs and space heaters in the first half of 2026:
{ "queries": ["power bank", "crib", "space heater"], "recalledFrom": "2026-01-01", "recalledTo": "2026-06-30" }
Input
| Field | Type | Default | Description |
|---|---|---|---|
queries | list of strings | — (prefilled helmet) | Product words, one entry per line: the recalls whose title, product names, models, product types or description hold every word of the entry (word starts, any case: helmet finds "Helmets"). Empty: every recall of the window. Never a URL |
sinceDays | integer 1–3,650 | 90 | Recalls dated in the last N days, today included |
recalledFrom | date YYYY-MM-DD | — | A fixed window instead: the first recall date (then sinceDays is not used) |
recalledTo | date YYYY-MM-DD | today | The last recall date of the window |
mode | watch or export | — | Empty: watch when stateName is given, otherwise export. An explicit mode wins |
stateName | string | — (prefilled cpsc-recalls) | Watch list name. Watch mode without a name uses the list default |
includeUnchanged | boolean | false | Watch: also return unchanged recalls (free) |
maxItems | integer 1–100,000 | 1000 | Most charged recalls per run; in watch mode the rest come in the next run |
Changing the product words of a watch list starts a new baseline; changing sinceDays does not (the window moves with each
run).
Output
{"status": "ok","attempts": 1,"error": null,"input": "helmet","mode": "export","watchList": null,"dropReason": null,"recallNumber": "26789","recallId": 10992,"recallDate": "2026-09-24","lastPublishDate": "2026-09-24","title": "5Color Recalls Children’s Bicycle Helmet and Pads Sets Due to Risk of Serious Injury or Death from Head Injury; Violate Mandatory Standard for Bicycle Helmets","description": "This recall involves 5Color-branded bicycle helmet and pads sets. …","productNames": "5Color Children’s Bike Helmet and Pads Sets","productTypes": "Helmets & Helmet Accessories","models": null,"numberOfUnits": "About 324","hazards": "The helmets in the recalled sets violate the mandatory safety standard for bicycle helmets … posing a serious risk of injury or death due to head injury.","injuries": "None reported","remedies": "Consumers should stop using the helmets immediately and contact 5Color for a full refund of the set. … email a photo of the destroyed helmet to [email on the recall page]. …","remedyOptions": "Refund","manufacturers": null,"importers": null,"distributors": null,"retailers": "Hengqin Guangwei Consulting Co., Ltd., dba. 5Color, of China","whereSold": "Sold Online At: Amazon.com in May 2026 for between $25 and $26.","manufacturerCountries": "China","upcs": null,"imageUrls": "https://cpsc.gov/s3fs-public/5Color1.jpg?VersionId=… | https://cpsc.gov/s3fs-public/5Color2.jpg?VersionId=…","jointRecallUrls": null,"firmNamesOmitted": false,"changeType": null,"changedFields": null,"previousValues": null,"url": "https://cpsc.gov/Recalls/2026/5Color-Recalls-Childrens-Bicycle-Helmet-and-Pads-Sets-Due-to-Risk-of-Serious-Injury-or-Death-from-Head-Injury-Violate-Mandatory-Standard-for-Bicycle-Helmets","source": "CPSC Recalls API (U.S. Consumer Product Safety Commission). Source: CPSC (cpsc.gov), public information.","license": "Public information of a U.S. federal agency (CPSC): free to copy and distribute, credit CPSC","licenseUrl": "https://www.cpsc.gov/About-CPSC/Policies-Statements-and-Directives/Privacy-Policy","scrapedAt": "2026-10-04T18:40:00.000Z"}
| Status | Meaning | Charged? |
|---|---|---|
ok | A recall returned | Export: yes. Watch: baseline, new and changed yes; unchanged no |
no_data | No recall in the window matches the entry, or nothing new since the last run | No |
failed | An invalid entry (a URL, no letters or digits), or no answer from CPSC after retries (error says why) | No |
The key-value store holds RUN_REPORT (counts, charged and free rows, stop reason) and, when something fails, the raw
response without contacts (SNAPSHOT_*).
Output fields
Output fields
| Field | Type | Description |
|---|---|---|
status | string (or null) | ok = recall returned (charged in export mode and for baseline, new and changed rows; free when unchanged); no_data = nothing to return (no recall in the window matches the entry, or nothing new since the last run) (free); failed = invalid input or no answer (free) |
attempts | integer (or null) | Requests made for this row (retries included) |
error | string (or null) | Why a row is no_data or failed; null on ok rows |
input | string (or null) | The entry of product words this row came from ("all recalls" when no words were given), or the input that failed |
mode | string (or null) | watch or export |
watchList | string (or null) | Watch list name (watch mode); null in export mode |
dropReason | string (or null) | Always null for recalls: a firm name that may be a person's is left out of the recall's fields and the recall is kept (firmNamesOmitted) |
recallNumber | string (or null) | CPSC recall number |
recallId | integer (or null) | CPSC recall database ID |
recallDate | string (or null) | Date of the recall notice (YYYY-MM-DD) |
lastPublishDate | string (or null) | Date the notice was last published or updated (YYYY-MM-DD) |
title | string (or null) | Title of the recall notice (a neutral title when the original named a firm that may be a person) |
description | string (or null) | What the recall covers: products, models, labels and dates |
productNames | string (or null) | Recalled product names, joined with " / " |
productTypes | string (or null) | CPSC product types, joined with " / " |
models | string (or null) | Model numbers given in the product list, joined with " / " (often only in the description) |
numberOfUnits | string (or null) | Number of units recalled, as CPSC writes it (e.g. "About 324") |
hazards | string (or null) | The hazard, joined with " / " when there are several |
injuries | string (or null) | Incidents and injuries reported (counts and kinds; no names) |
remedies | string (or null) | What consumers should do (contacts replaced by "[email on the recall page]" or "[phone on the recall page]") |
remedyOptions | string (or null) | Refund, Replace, Repair …, joined with " / " |
manufacturers | string (or null) | Manufacturers as " |
importers | string (or null) | Importers as " |
distributors | string (or null) | Distributors as " |
retailers | string (or null) | Retailer firms as " |
whereSold | string (or null) | Where, when and for how much the product was sold |
manufacturerCountries | string (or null) | Countries of manufacture, joined with " / " |
upcs | string (or null) | Product UPC codes, joined with " / " |
imageUrls | string (or null) | Links to the recall's product photos on cpsc.gov, joined with " / " |
jointRecallUrls | string (or null) | Pages of the same recall elsewhere (e.g. Health Canada), joined with " / " |
firmNamesOmitted | boolean (or null) | True when a firm name that may be a person's was left out of every field of this recall (people filter) |
changeType | string (or null) | Watch mode: baseline (first run of the list), new, changed or unchanged; null in export mode |
changedFields | string (or null) | Watch mode: the tracked fields that changed, comma-separated |
previousValues | string (or null) | Watch mode: the changed fields' previous values, as JSON |
url | string (or null) | The recall notice as CPSC links it, on cpsc.gov (it carries the firm's contacts); null when the record has no usable link (the recall is still returned) |
source | string (or null) | The data source and its credit line |
license | string (or null) | The terms of the data |
licenseUrl | string (or null) | Where the terms are published |
scrapedAt | string (or null) | When the row was made (ISO 8601) |
Pricing
Pay per event: one recall event per returned recall (export: every recall; watch: baseline, new and changed rows).
| Plan | Price per recall | Per 1,000 recalls |
|---|---|---|
| Free (no discount) | $0.0015 | $1.50 |
| Bronze | $0.0013 | $1.30 |
| Silver | $0.00115 | $1.15 |
| Gold (and Platinum, Diamond) | $0.0010 | $1.00 |
- Never charged: failed rows (an invalid entry, no answer from CPSC), no_data rows (no match, nothing new) and unchanged rows. You are never charged for failed results.
- Apify also charges its small per-run start event. There are no usage fees on top, so the actor is eligible for x402 agent payments.
Use it from AI agents
One clear main input, queries (product words; empty for every recall); every row has status, error, recallNumber
and scrapedAt, and url (the recall page) whenever CPSC gives one. Call it through the Apify API, the Apify MCP server
(mouadapi/cpsc-product-recalls) or x402 agentic payments. Copy-paste call (your Apify token in place of
YOUR_APIFY_TOKEN):
$curl -X POST "https://api.apify.com/v2/acts/mouadapi~cpsc-product-recalls/run-sync-get-dataset-items?token=YOUR_APIFY_TOKEN" -H "Content-Type: application/json" -d '{"queries": ["power bank"], "sinceDays": 365}'
import { ApifyClient } from 'apify-client';const client = new ApifyClient({ token: 'YOUR_APIFY_TOKEN' });const run = await client.actor('mouadapi/cpsc-product-recalls').call({ queries: ['crib', 'stroller'], stateName: 'baby-products' });const { items } = await client.dataset(run.defaultDatasetId).listItems();
Limits
- One request at a time, at most one a second: CPSC publishes no rate limit, so this actor keeps well under any reasonable
use. If the API answers HTTP 429, the run pauses 60, 120 and 240 seconds on the same connection, then stops with free
failedrows. No other IP or proxy is ever tried. - The window is read by recall date: an update to a recall dated before the window is not seen. At most 5,000 recalls are read per run (CPSC publishes a few hundred a year).
- Product words are matched in the recall's own text, by word starts (
cribalso finds "cribs"): a recall that names the product differently is not found. Leavequeriesempty to get every recall of the window. - US recalls by CPSC only (consumer products). Food, drugs, medical devices, cars and boats are recalled by other agencies (FDA, NHTSA, USCG) and are not here.
Known issues
- CPSC's API sometimes answers with its own error ("Error retrieving Recalls: The underlying provider failed on Open.",
HTTP 200; seen on 2 October 2026). The actor tries again after 1 and 2 seconds, then each entry is a free
failedrow that quotes it. - How names are handled: a firm trading under a person's name, and a firm name shaped like a person's name, are left out of
the recall's fields (
firmNamesOmitted: true; the test leans towards removing, so some company trading names are left out too). Such a recall can have a neutral title andnullin a text field that repeated the name.RUN_REPORTcounts these recalls (firmNamesOmitted) and the fields set to null (textFieldsNulled), never the names. - A few recalls have no usable page link in the API: such a recall is still returned (and charged), with
urlnull. A relative cpsc.gov path gets the site's address, and a link on another host is kept as CPSC gives it.RUN_REPORTcounts them (pageLinks).
FAQ
Does it include every CPSC recall? Every recall notice the CPSC Recalls API returns for the window. Use the recall page
(url) for the firm's contact details and the full notice.
Why did a watch run return one no_data row? Nothing was new or updated since the last run of the watch list; the row
says how many recalls were unchanged. It is free.
Data and licence
- Source: the CPSC Recalls API (www.saferproducts.gov/RestWebServices), documented at https://www.cpsc.gov/Recalls/CPSC-Recalls-Application-Program-Interface-API-Information.
- Terms: CPSC's Privacy and Security Notice, "Copyright": web page text "is public information. You may freely distribute,
copy, or link to any of this information. However, the information may not be used in a way that states or implies CPSC
endorsement. If you distribute, copy or link to any of this information, please credit CPSC." Every row credits CPSC in
source. - This actor is not affiliated with, endorsed by or provided by the U.S. Consumer Product Safety Commission. It returns the recalls as published; always check the linked recall page before acting on it.