CPSC Recalls Scraper & API — UPC, brand & retailer monitor avatar

CPSC Recalls Scraper & API — UPC, brand & retailer monitor

Pricing

from $3.50 / 1,000 results

Go to Apify Store
CPSC Recalls Scraper & API — UPC, brand & retailer monitor

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

Michael Rice

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

13 days ago

Last modified

Security

Limited permissions

Share

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 GET to 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: true for 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 raw when includeRaw is 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: true returns 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

  1. Open this Actor on Apify and set at least one filter (e.g. productName, upc, hazard, manufacturer, or a date range).
  2. Optionally set maxItems, includeRaw, and descriptionSnippetMaxLength.
  3. 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).
  4. 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).

FieldMaps to APINotes
productNameProductNamee.g. crib
manufacturerManufacturerBrand / maker
hazardHazardOfficial param kept; upstream currently returns 0 for all tried values — filter hazards[] client-side (see FAQ)
remedyRemedy
retailerRetailer
upcUPC
recallNumberRecallNumber
recallTitleRecallTitle
manufacturerCountryManufacturerCountry
importerImporter
inconjunctionUrlInconjunctionURL
recallDateStart / recallDateEndRecallDateStart / RecallDateEndPrefer 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:

  1. 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 newest recallDate it pushed plus the recallIds already pushed on that date (and maxRecallId for reference).
  2. Later runs query CPSC from the watermark date onward and push only recalls with a newer recallDate, or the same date but an unseen recallId. Zero new recalls → the run still SUCCEEDS with an empty dataset (OUTPUT.message = "No new recalls since last run").
  3. 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 (lastPublishDate changes), 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. Raise maxItems if you want everything at once.
  • Caveat for empty-filter schedules: if maxItems is 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. Raise maxItems or narrow the filters if you see OUTPUT.truncated = true run after run.
  • Your fixed recallDateStart / recallDateEnd still apply. A schedule whose recallDateEnd is 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 the get-dataset-items tool (limit, offset, fields).
  • With the default tool set, an agent can also run it via call-actor with actor: "brightish_ascent/cpsc-product-recalls-monitor".
  • Local stdio server: npx @apify/actors-mcp-server --tools brightish_ascent/cpsc-product-recalls-monitor, with APIFY_TOKEN set.

Agent frameworks.

  • LangChain: ApifyActorsTool("brightish_ascent/cpsc-product-recalls-monitor") from langchain-apify.
  • CrewAI: ApifyActorsTool(actor_name="brightish_ascent/cpsc-product-recalls-monitor") from crewai_tools.
  • OpenAI Agents SDK: MCPServerStreamableHttp with the MCP URL above and an Authorization: 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 CPSC url.

Cost per call. You pay $0.00005 per run plus $0.0035 per returned recall:

maxItemsMax 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, retailer or a date range) plus a small maxItems (5–20). With no filters, the last ~90 days are returned.
  • Use outputFormat: "compact" to keep rows short. Leave includeRaw off.
  • Don't use hazard. The official API currently returns 0 results for it, so filter on the hazards field in the results instead.
  • For "check again later" tasks, set onlyNewSinceLastRun: true so repeat runs return only new recalls.
  • Cite the official url for each recall. Data is public CPSC data and should be verified there.

Pricing

Live Store pricing (PAY_PER_EVENT) — locked Console PPE:

EventPrice (USD)Notes
Actor start (apify-actor-start)$0.00005One-time per run (memory-scaled per Apify; min one event)
Dataset item (apify-default-dataset-item)$0.0035Per 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.