CPSC Recalls Scraper & API — UPC, brand & retailer monitor
Pricing
from $3.50 / 1,000 results
CPSC Recalls Scraper & API — UPC, brand & retailer monitor
Search official U.S. CPSC product recalls (saferproducts.gov API) by product, brand, UPC, retailer or date. Returns one JSON row per recall: number, date, title, products, hazards, remedies, retailers, UPCs, CPSC link. Use it to check if a product was recalled. Not affiliated with CPSC.
Pricing
from $3.50 / 1,000 results
Rating
0.0
(0)
Developer
Michael Rice
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
13 days ago
Last modified
Categories
Security
Limited permissionsShare
CPSC Recalls Scraper & API — product recall monitor by UPC, brand & retailer
Query the official U.S. CPSC saferproducts.gov Recalls REST API and get one normalized dataset item per product recall. Filter by UPC, manufacturer/brand, hazard, retailer, remedy, recall number, title, country, importer, and date range — ideal for compliance monitoring and product-safety research.
Not affiliated with the U.S. CPSC. Public API data only. Verify every recall on the official CPSC page before taking action.
Features
- Official CPSC recalls API — HTTP
GETto saferproducts.gov; no browser, no Crawlee - Rich filters — product name, manufacturer/brand, hazard, remedy, retailer, UPC, recall number, title, manufacturer country, importer, in-conjunction URL, recall date range
- Normalized output — stable fields (
recallNumber,recallDate,title,manufacturers,products,hazards,remedies,retailers,upc,url, …) ready for pipelines and dashboards - Safety by default — empty input auto-applies a ~90-day date window (or set filters /
allowUnfiltered: truefor a capped full dump) - Bounded & resilient —
maxItems(default 100, hard cap 5000), retry/backoff on HTTP 429 / 5xx, clear User-Agent - Optional raw payload — attach the original CPSC JSON under
rawwhenincludeRawis true - AI-agent ready — works as a tool in Apify's MCP server, LangChain, CrewAI and the OpenAI Agents SDK; opt-in
outputFormat: "compact"for small, LLM-friendly rows (see Use with AI agents / MCP) - Opt-in “Only new since last run” — for schedules:
onlyNewSinceLastRun: truereturns only recalls you haven’t received yet (watermark kept in your own Apify account)
Who is it for
- Retail & marketplace compliance teams tracking recalls by brand, UPC, or retailer
- Consumer-product manufacturers / importers monitoring hazard and remedy language
- Insurance, legal, and QA workflows that need machine-readable product recall data
- Researchers and journalists extracting CPSC recall history for analysis
- Developers who want a ready-made Apify Actor instead of hand-rolling the saferproducts.gov client
How to scrape / extract CPSC product recall data
- Open this Actor on Apify and set at least one filter (e.g.
productName,upc,hazard,manufacturer, or a date range). - Optionally set
maxItems,includeRaw, anddescriptionSnippetMaxLength. - Run the Actor. It calls
GET https://www.saferproducts.gov/RestWebServices/Recall?format=json&…
with only documented official parameter names (unknown keys can cause the API to return all recalls). - Read results from the default dataset — one row per recall — or download via the dataset API URL shown in the run output.
Tips: Prefer filtered queries over unfiltered dumps. There is no pagination; the API returns the full match set and this Actor truncates client-side with maxItems. There is no free-text InConjunctionWith parameter — use inconjunctionUrl (InconjunctionURL).
Official docs: CPSC Recalls API Information.
Input example
{"recallDateStart": "2025-01-01","recallDateEnd": "2026-12-31","maxItems": 50,"includeRaw": false,"descriptionSnippetMaxLength": 400,"allowUnfiltered": false}
Store Try / first-run uses a similar date window + modest maxItems so an unedited run succeeds. Other useful filters: productName, manufacturer, retailer, upc, recallNumber. Prefer those over hazard today — see FAQ (upstream Hazard filter currently returns empty). If you clear all filters, the Actor auto-applies a ~90-day date window (unless allowUnfiltered: true).
| Field | Maps to API | Notes |
|---|---|---|
productName | ProductName | e.g. crib |
manufacturer | Manufacturer | Brand / maker |
hazard | Hazard | Official param kept; upstream currently returns 0 for all tried values — filter hazards[] client-side (see FAQ) |
remedy | Remedy | |
retailer | Retailer | |
upc | UPC | |
recallNumber | RecallNumber | |
recallTitle | RecallTitle | |
manufacturerCountry | ManufacturerCountry | |
importer | Importer | |
inconjunctionUrl | InconjunctionURL | |
recallDateStart / recallDateEnd | RecallDateStart / RecallDateEnd | Prefer YYYY-MM-DD |
maxItems | (client) | Default 100, max 5000 |
includeRaw | (client) | Attach original JSON under raw |
descriptionSnippetMaxLength | (client) | Default 400 |
allowUnfiltered | (client) | Default false — empty input auto-applies ~90-day dates; set true only for intentional full dumps |
onlyNewSinceLastRun | (client) | Default false — for scheduled runs: push only recalls newer than the last run’s watermark (see below) |
outputFormat | (client) | full (default, all fields) or compact (key fields only, texts ≤ 200 chars — for AI agents; same price per row) |
Only new since last run (delta mode, opt-in)
Built for scheduled / recurring runs, so you are not re-charged for recalls you already received.
{ "manufacturer": "Graco", "maxItems": 50, "onlyNewSinceLastRun": true }
How it works:
- First run with the flag = baseline. It behaves exactly like a normal run (your full filtered window, newest first, capped by
maxItems) and then saves a watermark: the newestrecallDateit pushed plus therecallIds already pushed on that date (andmaxRecallIdfor reference). - Later runs query CPSC from the watermark date onward and push only recalls with a newer
recallDate, or the same date but an unseenrecallId. Zero new recalls → the run still SUCCEEDS with an empty dataset (OUTPUT.message = "No new recalls since last run"). - The watermark is updated only after items were pushed successfully. A failed run does not move it.
Where the state lives: a named key-value store cpsc-recalls-monitor-state in the Apify account that runs the Actor (yours, not the developer’s). It has one record per filter combination (WATERMARK-<hash of your filters>), so two schedules with different filters never share a watermark. Changing any filter starts a new baseline. To reset, delete that record (Console → Storage → Key-value stores). Turning the flag off does not delete it; it is simply ignored while off.
Run OUTPUT (default key-value store) includes onlyNewSinceLastRun, watermarkKey, baselineRun, watermarkBefore, watermarkAfter, skippedAlreadySeen, newAvailable.
Honest limitations:
- “New” means a newer recall date (or an unseen recall ID on the watermark date). If CPSC edits an older recall later (
lastPublishDatechanges), it is not re-emitted. - If more new recalls exist than
maxItems, the oldest new ones are returned first and the rest arrive on the next run. RaisemaxItemsif you want everything at once. - Caveat for empty-filter schedules: if
maxItemsis below the number of new recalls per run (or a schedule is paused for a long time), the backlog keeps growing, and anything older than the rolling ~90-day window is never backfilled. RaisemaxItemsor narrow the filters if you seeOUTPUT.truncated = truerun after run. - Your fixed
recallDateStart/recallDateEndstill apply. A schedule whoserecallDateEndis in the past will eventually return nothing new. With empty filters the rolling ~90-day window is used, and the watermark key stays stable across days. - Watermarks are per Apify account (and per filter set). Runs from a different account, organization, or a local machine keep their own state. Two runs with identical filters started at the same time can both return the same recalls.
- Off by default. Existing inputs and schedules behave exactly as before.
Output example
{"recallId": 10904,"recallNumber": "26669","recallDate": "2026-08-06","title": "Play Yard and Crib Mattresses Recalled …","manufacturers": [],"products": ["Voomf Play Yard and Crib Mattresses"],"hazards": ["The recalled mattresses violate the mandatory safety standard…"],"remedies": ["Consumers should stop using the mattresses immediately…"],"remedyOptions": ["Refund"],"retailers": ["Online at Amazon.com from January 2026 through May 2026…"],"importers": ["Shanghaiyuejiuyaoguojimaoyiyouxiangongsi … dba Voomf, of China"],"distributors": [],"manufacturerCountries": ["China"],"upc": [],"url": "https://www.cpsc.gov/Recalls/2026/…","descriptionSnippet": "This recall involves Voomf-branded play yard mattresses…","consumerContact": "Voomf by email at …","lastPublishDate": "2026-08-07","source": "cpsc-saferproducts-gov"}
Use with AI agents / MCP
This Actor works as a ready-made tool for AI agents: an agent passes filters and gets back one JSON row per recall.
Apify MCP server. Add the Actor as a tool by listing it in the tools parameter of the hosted server (https://mcp.apify.com):
https://mcp.apify.com?tools=brightish_ascent/cpsc-product-recalls-monitor
MCP client config (Claude Desktop, Cursor, VS Code and other MCP clients). You sign in to Apify with OAuth on first connect:
{"mcpServers": {"apify": {"url": "https://mcp.apify.com?tools=brightish_ascent/cpsc-product-recalls-monitor"}}}
- The tool is named
brightish_ascent--cpsc-product-recalls-monitor. Its arguments are the input fields above. - A call returns the run status and a
datasetId. The agent then reads the rows with theget-dataset-itemstool (limit,offset,fields). - With the default tool set, an agent can also run it via
call-actorwithactor: "brightish_ascent/cpsc-product-recalls-monitor". - Local stdio server:
npx @apify/actors-mcp-server --tools brightish_ascent/cpsc-product-recalls-monitor, withAPIFY_TOKENset.
Agent frameworks.
- LangChain:
ApifyActorsTool("brightish_ascent/cpsc-product-recalls-monitor")fromlangchain-apify. - CrewAI:
ApifyActorsTool(actor_name="brightish_ascent/cpsc-product-recalls-monitor")fromcrewai_tools. - OpenAI Agents SDK:
MCPServerStreamableHttpwith the MCP URL above and anAuthorization: Bearer <APIFY_TOKEN>header. - LlamaIndex:
ApifyActor(token).load_data(actor_id="brightish_ascent/cpsc-product-recalls-monitor", run_input={...}, dataset_mapping_function=...).
The LangChain and CrewAI tools return every dataset row inline, so keep maxItems small.
Example agent prompt:
Were any strollers recalled in the U.S. since 2024? Use the CPSC recalls tool with
productName: "stroller",recallDateStart: "2024-01-01",maxItems: 10,outputFormat: "compact", then list each recall's date, title, hazard and CPSCurl.
Cost per call. You pay $0.00005 per run plus $0.0035 per returned recall:
maxItems | Max cost per call |
|---|---|
| 10 | ≈ $0.035 |
| 25 | ≈ $0.088 |
| 100 (default) | ≈ $0.35 |
Zero matches cost only the start fee. With call-actor, you can also cap spend with maxTotalChargeUsd in callOptions.
Tips for agents:
- Always set at least one filter (
upc,manufacturer,productName,retaileror a date range) plus a smallmaxItems(5–20). With no filters, the last ~90 days are returned. - Use
outputFormat: "compact"to keep rows short. LeaveincludeRawoff. - Don't use
hazard. The official API currently returns 0 results for it, so filter on thehazardsfield in the results instead. - For "check again later" tasks, set
onlyNewSinceLastRun: trueso repeat runs return only new recalls. - Cite the official
urlfor each recall. Data is public CPSC data and should be verified there.
Pricing
Live Store pricing (PAY_PER_EVENT) — locked Console PPE:
| Event | Price (USD) | Notes |
|---|---|---|
Actor start (apify-actor-start) | $0.00005 | One-time per run (memory-scaled per Apify; min one event) |
Dataset item (apify-default-dataset-item) | $0.0035 | Per normalized recall row — from $3.50 / 1,000 results |
Example: 100 items ≈ $0.00005 + 100 × $0.0035 ≈ $0.35.
You are charged for these events only — not for separate platform compute usage under this monetization model.
Rate limits & ToS
- Public, no API key. Be a good citizen: descriptive User-Agent, avoid tight polling, prefer filtered queries.
- No published hard rate limit found in the public guide; this Actor still retries with backoff on 429 / 5xx.
- Always verify critical decisions against the official recall page in
url.
FAQ / disclaimer
Is this official CPSC software? No. Not affiliated with, endorsed by, or operated by the U.S. CPSC.
What happens if I set no filters? The Actor auto-applies a ~90-day recallDateStart / recallDateEnd window so Store Try / first runs succeed without dumping the full catalog. Pass explicit filters for precision, or set allowUnfiltered: true for an intentional full dump (still capped by maxItems).
Is the data complete? Dataset items are convenience transforms of public API data and may be incomplete, delayed, or truncated (descriptionSnippet). Verify every recall on the official CPSC page before consumer, retail, or compliance action.
Is this legal advice? No.
How do I schedule this Actor for ongoing recall monitoring? In Apify Console open Schedules → Create new, pick a cron expression (e.g. 0 13 * * * for daily, or 0 13 * * 1 for weekly on Mondays — times are in the schedule’s timezone), then add this Actor with the input you want saved (UPC, brand/manufacturer, retailer, etc.). Each scheduled run writes a fresh dataset; combine with Apify integrations / webhooks (Slack, email, Make, Zapier, your own endpoint) to get a notification when a run finishes. You can also start runs from the Apify API or client libraries on your own cron.
Easiest for recurring runs: turn on onlyNewSinceLastRun. Each scheduled run then returns only recalls you haven’t received yet (see Only new since last run above). The rolling-window tip below still works if you prefer to manage dates yourself.
Tip — use a rolling date window for recurring runs. Fixed dates like 2025-01-01–2026-12-31 are fine for a one-off pull, but a schedule that keeps them will re-pull the same old recalls every time (and you pay per dataset item). For ongoing monitoring, keep the window short and recent, e.g. the last 7–30 days, with maxItems sized to that window. This Actor has no relative-date input, so either (a) leave all filters empty and let it auto-apply its ~90-day rolling window, (b) compute recallDateStart / recallDateEnd when you trigger the run via the API or an integration, or (c) periodically update the dates saved on the schedule. Dedupe downstream on recallNumber if windows overlap.
Is this Actor affiliated with the CPSC? No — reminder: this is an independent tool built on the public saferproducts.gov API. It is not affiliated with, endorsed by, or operated by the U.S. Consumer Product Safety Commission. Always confirm recalls on the official CPSC page in url.
Why does hazard return 0 recalls? The Actor correctly maps hazard → official API Hazard. As of 2026-09-23 probing, saferproducts.gov returns an empty array for every Hazard= value tried — including short words that appear in live Hazards[].Name text (fire, entrapment, choking, …), multi-word fragments, a verbatim Name string, and the Programmer’s Guide example RecallTitle=stroller&Hazard=pinch (115 hits without Hazard, 0 with it). This is not case-sensitivity or a missing vocab list: Hazards[].Name is long narrative prose, and HazardType / HazardTypeID on sampled records were empty. Do not invent alternate query keys (Hazards, HazardName, …) — unknown params make the API return all recalls. Correct usage today: filter with working fields (productName, retailer, manufacturer, remedy, recallTitle, dates, …), then substring-match the dataset’s hazards array client-side. The hazard input is retained so a future API fix works without an Actor change.
License
MIT (Actor scaffold). Upstream recall content remains subject to CPSC / U.S. government public-information terms.