# CPSC Product Recalls Scraper (`automation-lab/cpsc-recalls-remedies-monitor`) Actor

Search official CPSC product recalls and export normalized hazards, incidents, remedies, companies, identifiers, images, and source records.

- **URL**: https://apify.com/automation-lab/cpsc-recalls-remedies-monitor.md
- **Developed by:** [Stas Persiianenko](https://apify.com/automation-lab) (community)
- **Categories:** Business
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.61 / 1,000 item extracteds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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

## CPSC Product Recalls Scraper

Search official **CPSC product recalls** and export normalized product, company, hazard, incident, remedy, date, identifier, image, and source records.

The Actor reads the public U.S. Consumer Product Safety Commission recall service. Use it for a one-time safety analysis, exact Recall ID lookup, or a scheduled monitor that returns only records not delivered by earlier runs in the same state scope.

### What does this CPSC recall Actor do?

The Actor turns official CPSC recall responses into integration-ready dataset rows.

It can:

- search an inclusive recall-date range;
- look back a configurable number of days from today;
- retrieve up to 100 exact CPSC Recall IDs;
- filter by any-field, product, company, hazard, or remedy text;
- sort matching notices before applying an output limit;
- include official product images and captions;
- remember emitted Recall IDs for recurring `onlyNew` monitors;
- retain official recall and API source links on every row.

It uses the official SaferProducts.gov JSON service rather than interpreting search-engine snippets or aggregating unofficial notices.

### Who is it for?

**Retail and marketplace compliance teams** can compare newly published recalls against product catalogs.

**Manufacturers and importers** can monitor company, brand, model, and hazard terms relevant to their products.

**Insurance and product-safety analysts** can build structured histories of incidents, hazards, and remedies.

**Data engineers** can send normalized recall rows to a warehouse, spreadsheet, webhook, or review queue.

**Researchers and journalists** can retrieve an exact official record with its identifying details and source URL.

### Why use this Actor?

CPSC records contain useful nested structures that are inconvenient to normalize repeatedly.

This Actor provides:

- stable camelCase field names;
- separate arrays for products, manufacturers, importers, retailers, and distributors;
- convenient flattened product names and image URLs;
- hazard, incident, remedy, and remedy-option fields kept distinct;
- deterministic filtering applied to the normalized official record;
- explicit transient retry limits and input validation;
- state scopes that prevent unrelated recurring monitors from contaminating each other.

No proxy, browser, login, cookie, or private credential is required for the current official API route.

### What CPSC recall data is extracted?

| Field | Meaning |
| --- | --- |
| `recallId` | Stable numeric CPSC Recall ID |
| `recallNumber` | Public recall number |
| `recallDate` | Official recall date |
| `lastPublishDate` | Most recent CPSC publication date |
| `title` | Official recall headline |
| `description` | Product identification and recall description |
| `products` | Product names, models, types, categories, and unit counts |
| `manufacturers` | Named manufacturers and available company IDs |
| `importers` | Named importers |
| `retailers` | Named retailers and sales-channel details |
| `distributors` | Named distributors |
| `manufacturerCountries` | Reported countries of manufacture |
| `productUpcs` | UPC values when CPSC supplies them |
| `hazards` | Official hazard statements |
| `incidents` | CPSC injury or incident-report text |
| `remedies` | Full consumer remedy instructions |
| `remedyOptions` | Labels such as Replace, Repair, or Refund |
| `consumerContact` | Official response contact details |
| `images` | Official image URLs and captions |
| `sourceUrl` | Official CPSC notice page |
| `sourceApiUrl` | Exact official API request for the Recall ID |
| `matchedFilters` | Filters that selected the row |
| `isNew` | Whether the selected monitor state had seen the ID |
| `scrapedAt` | UTC extraction timestamp |

Empty arrays or strings mean the upstream CPSC record did not supply that value.

### Getting started

1. Open the Actor input page.
2. Choose a date scope with `sinceDays`, or enter exact `recallIds`.
3. Add optional safety filters.
4. Set `maxItems` to the largest dataset you need.
5. Keep `includeImages` enabled when image evidence is useful.
6. Run the Actor.
7. Open the **Recall overview** dataset view or export JSON, CSV, Excel, XML, or RSS.
8. For recurring work, schedule the Actor and enable `onlyNew`.

The default input searches the last 30 days and saves up to 100 recalls.

### Input parameters

#### Date or exact-record scope

- `sinceDays` — days before `endDate` or today; from 1 to 3,650.
- `startDate` — optional inclusive `YYYY-MM-DD` start.
- `endDate` — optional inclusive `YYYY-MM-DD` end.
- `recallIds` — optional list of up to 100 numeric Recall ID strings.

When `recallIds` is not empty, date fields are ignored.

#### Safety filters

All supplied filters use case-insensitive substring matching and are combined with AND logic.

- `keyword` searches titles, descriptions, products, companies, hazards, incidents, remedies, countries, and contact text.
- `productKeyword` searches normalized product identity fields.
- `companyKeyword` searches manufacturers, importers, retailers, and distributors.
- `hazardKeyword` searches official hazard statements.
- `remedyKeyword` searches remedy instructions and option labels.

#### Output controls

- `maxItems` limits matching records after sorting.
- `sortBy` is `newest` or `oldest`.
- `includeImages` controls the `images` and `imageUrls` fields.

#### Monitoring controls

- `onlyNew` skips Recall IDs already emitted to the selected state scope.
- `stateKey` gives a monitor a stable independent scope name.

If `stateKey` is empty, the Actor derives a scope from the filters and exact Recall IDs. Date windows and output limits do not change that derived identity, so a rolling scheduled search keeps its history.

### Example inputs

#### Search recent recalls

```json
{
  "sinceDays": 365,
  "maxItems": 25,
  "sortBy": "newest",
  "includeImages": true
}
```

#### Retrieve one official Recall ID

```json
{
  "recallIds": ["10937"],
  "maxItems": 1,
  "includeImages": true
}
```

#### Monitor fire-hazard notices

```json
{
  "sinceDays": 365,
  "hazardKeyword": "fire",
  "onlyNew": true,
  "stateKey": "fire-hazard-compliance",
  "maxItems": 100,
  "sortBy": "newest"
}
```

Schedule the third input with the same key-value store to receive unseen matching IDs on later runs.

### Output example

A direct lookup of Recall ID `10937` produces a row shaped like this:

```json
{
  "recallId": 10937,
  "recallNumber": "26716",
  "recallDate": "2026-08-20",
  "title": "CCM Hockey U.S. Recalls FMHVR Hybrid Visors and ACCHVR Replacement Visor Accessories Due to Risk of Injury from Laceration or Impact Hazards",
  "productNames": [
    "FMHVR Hybrid Visors and ACCHVR Replacement Visor Accessories"
  ],
  "hazards": [
    "The recalled hockey visors and replacement visor accessories can crack upon impact, posing a risk of injury due to laceration or impact hazards."
  ],
  "incidents": ["None reported"],
  "remedyOptions": ["Replace"],
  "manufacturerCountries": ["China"],
  "source": "U.S. Consumer Product Safety Commission (CPSC)",
  "isNew": true
}
```

The full row also contains products, parties, remedy instructions, consumer contact, images, source URLs, and extraction metadata.

### How much does it cost to export CPSC product recalls?

The Actor uses pay-per-event pricing:

- a one-time **$0.0005 start fee** per run;
- one `item` event for each normalized recall row saved.

Per-record prices decrease across Apify pricing tiers:

| Tier | Price per recall |
| --- | ---: |
| Free | $0.003082 |
| Bronze | $0.00268 |
| Silver | $0.0020904 |
| Gold | $0.001608 |
| Platinum | $0.001072 |
| Diamond | $0.0007504 |

At the Bronze tier, 1 result costs about **$0.00318**, 25 results cost about **$0.0675**, and 100 results cost about **$0.269**, including the start fee.

No item fee is charged for filtered-out, duplicate, already-seen, malformed, or failed records.

### Build a recurring product-safety monitor

Create one saved Task per compliance scope.

For example:

1. set `sinceDays` to cover the time between schedules plus a safety buffer;
2. add a company, product, or hazard filter;
3. enable `onlyNew`;
4. choose a durable `stateKey`;
5. schedule daily or weekly runs;
6. connect the dataset to email, Slack, a webhook, Google Sheets, or your warehouse.

The first run emits current matching recalls. Later runs using the same key-value store emit only unseen Recall IDs.

Changing the `stateKey` creates a fresh monitor. Purging or replacing the key-value store also resets history.

### Export and integration workflows

Common workflows include:

- compare `productNames`, models, and UPCs with a catalog;
- route `hazards` and `incidents` into a risk-review queue;
- notify category owners when `remedyOptions` contains Refund or Stop Sale language;
- enrich a compliance case using exact `recallIds`;
- archive official `sourceUrl` and image evidence;
- join company names against vendor master data;
- track changes using `lastPublishDate` in a warehouse.

Apify datasets can be downloaded as JSON, JSONL, CSV, Excel, XML, and RSS.

### Run with the Apify API

Replace `APIFY_TOKEN` with your token.

#### cURL

```bash
curl -X POST \
  "https://api.apify.com/v2/acts/automation-lab~cpsc-recalls-remedies-monitor/runs?token=APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"sinceDays":30,"hazardKeyword":"fire","maxItems":25}'
```

To wait for results in one request:

```bash
curl -X POST \
  "https://api.apify.com/v2/acts/automation-lab~cpsc-recalls-remedies-monitor/run-sync-get-dataset-items?token=APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"recallIds":["10937"],"maxItems":1}'
```

#### JavaScript

```javascript
import { ApifyClient } from 'apify-client';

const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('automation-lab/cpsc-recalls-remedies-monitor').call({
  sinceDays: 365,
  companyKeyword: 'CCM',
  maxItems: 100,
});

const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items);
```

#### Python

```python
from apify_client import ApifyClient
import os

client = ApifyClient(os.environ['APIFY_TOKEN'])
run = client.actor('automation-lab/cpsc-recalls-remedies-monitor').call(
    run_input={
        'sinceDays': 365,
        'remedyKeyword': 'refund',
        'maxItems': 100,
    }
)
items = client.dataset(run['defaultDatasetId']).list_items().items
print(items)
```

### Use with Apify MCP

#### Claude Code MCP setup

Add the Actor to Claude Code:

```bash
claude mcp add --transport http apify \
  "https://mcp.apify.com?tools=automation-lab/cpsc-recalls-remedies-monitor"
```

#### Claude Desktop, Cursor, and VS Code MCP setup

Claude Desktop, Cursor, and VS Code can use this HTTP MCP configuration in the MCP server settings supported by each client:

```json
{
  "mcpServers": {
    "apify": {
      "url": "https://mcp.apify.com?tools=automation-lab/cpsc-recalls-remedies-monitor"
    }
  }
}
```

### Example prompts showing MCP usage

After setup, ask the MCP client to run the Actor with prompts such as:

- “Find CPSC recalls from the last 90 days involving fire hazards.”
- “Export official CPSC Recall ID 10937 and summarize products and remedies.”
- “Run my saved fire-hazard monitor and list only newly seen Recall IDs.”

### Reliability and retry behavior

The official JSON service is called directly with a 30-second request timeout.

Network errors, HTTP 429, and temporary server errors are retried at most twice after the initial request. Backoff includes jitter.

Stable client errors fail immediately. Unexpected HTML or a changed response shape is treated as an upstream error, not as a successful empty dataset.

The Actor intentionally has no automatic residential proxy or browser fallback. The selected official endpoint currently requires neither, and excluding them keeps runtime and transfer cost predictable.

### Limits and data freshness

- Results reflect records returned by the official CPSC service at run time.
- The Actor does not create or verify safety findings independently.
- CPSC can omit a manufacturer, UPC, image, incident, or other field.
- A date query retrieves the official response before local filtering and `maxItems` are applied.
- Exact mode supports up to 100 Recall IDs per run.
- A monitor stores up to 10,000 seen IDs per state scope.
- `onlyNew` compares Recall IDs, not field-level revisions.
- Scheduling, notifications, and downstream comparisons are configured in Apify rather than performed inside one run.

For a complete audit trail, retain dataset rows and compare `lastPublishDate` or the full normalized record between runs.

### Legality

The Actor accesses public official U.S. government recall records without login or personal-data collection. Users remain responsible for how they combine, redistribute, or act on the output and should verify consequential decisions against the current official notice.

### Responsible use

CPSC recall notices are official public U.S. government safety information.

Use the data responsibly:

- follow applicable laws and organizational policies;
- preserve official source links when redistributing records;
- do not present automated matching as legal or safety advice;
- verify high-impact decisions against the current CPSC notice;
- protect any private catalog or supplier data joined downstream.

This Actor does not replace CPSC guidance, legal counsel, product testing, or a formal recall-management process.

### Troubleshooting

#### The dataset is empty

Check the date range and remove filters one at a time. All supplied filters must match the same recall.

An empty exact-ID result can mean the official service does not recognize that ID.

#### A scheduled monitor returned no rows

That can be correct: all matching Recall IDs may already exist in its state. Disable `onlyNew`, change `stateKey`, or use a fresh key-value store to inspect the current full match set.

#### The run says a date is invalid

Use an exact `YYYY-MM-DD` value, such as `2026-08-01`. The start date cannot be after the end date.

#### Why is a company absent?

CPSC may identify an importer or retailer but leave the manufacturer array empty. Check all party arrays and the description.

#### Why are images missing?

Confirm `includeImages` is enabled. Some official records do not provide images.

#### The official service failed

Inspect the run log for status and retry details. Retry later only for a temporary CPSC outage; deterministic input errors require an input correction.

### Related Automation Lab Actors

- [FDA Food Recalls Scraper](https://apify.com/automation-lab/fda-food-recalls-scraper) for U.S. food enforcement and recall records.
- [NHTSA Vehicle Recall Campaigns](https://apify.com/automation-lab/nhtsa-vehicle-recall-campaigns) for make, model, and model-year vehicle recall campaigns.

CPSC covers consumer products. It is not a substitute for FDA food or medical-device recall sources, or NHTSA vehicle campaigns.

### FAQ

#### Does this Actor use official data?

Yes. It reads the public SaferProducts.gov Recall REST service and retains official CPSC notice URLs.

#### Can I query one recall directly?

Yes. Supply its numeric CPSC Recall ID as a string in `recallIds`.

#### Can I search several fields at once?

Yes. Filters use AND logic. For example, `companyKeyword: "CCM"` and `hazardKeyword: "impact"` require both to match.

#### Does `maxItems` reduce the API date range?

No. The official date response is normalized and filtered first, then sorted and limited.

#### Does monitor mode detect changed text?

No. It tracks whether a Recall ID has been emitted. Use `lastPublishDate` and downstream comparison when field-level changes matter.

#### Are filtered or duplicate rows charged?

No. The per-record event is charged only for normalized rows saved to the default dataset.

#### Can I use a proxy?

The current input intentionally does not expose proxy configuration because the official JSON service works directly. This avoids needless transfer cost and configuration complexity.

#### Can I publish alerts directly from the Actor?

Use Apify schedules and integrations to send dataset results to your chosen notification system. The Actor itself produces structured records and monitor state.

# Actor input Schema

## `sinceDays` (type: `integer`):

When startDate is empty, search this many days back from endDate (or today). Ignored when recallIds are supplied.

## `startDate` (type: `string`):

Inclusive recall-date start in YYYY-MM-DD format. Leave empty to use days back.

## `endDate` (type: `string`):

Inclusive recall-date end in YYYY-MM-DD format. Leave empty to use today.

## `recallIds` (type: `array`):

Optional list of up to 100 exact numeric CPSC Recall IDs. When supplied, the date range is ignored.

## `keyword` (type: `string`):

Case-insensitive text required in the recall title, description, product, company, hazard, incident, remedy, country, or contact fields.

## `productKeyword` (type: `string`):

Case-insensitive text required in a product name, description, model, type, category, or unit count.

## `companyKeyword` (type: `string`):

Case-insensitive text required in a manufacturer, importer, retailer, or distributor name.

## `hazardKeyword` (type: `string`):

Case-insensitive text required in the official CPSC hazard statement.

## `remedyKeyword` (type: `string`):

Case-insensitive text required in the official remedy instructions or remedy option.

## `maxItems` (type: `integer`):

Maximum number of matching recall records to save to the default dataset.

## `sortBy` (type: `string`):

Sort matching records by recall date before applying maxItems.

## `onlyNew` (type: `boolean`):

Store emitted Recall IDs in the run key-value store and skip them on later runs using the same storage and state scope.

## `stateKey` (type: `string`):

Optional stable name for an independent monitoring scope (letters, numbers, underscores, and hyphens). Filters define the scope when omitted.

## `includeImages` (type: `boolean`):

Include official CPSC image URLs and captions in each recall record.

## Actor input object example

```json
{
  "sinceDays": 20,
  "recallIds": [],
  "maxItems": 20,
  "sortBy": "newest",
  "onlyNew": false,
  "includeImages": true
}
```

# Actor output Schema

## `dataset` (type: `string`):

Default dataset containing normalized CPSC recall records.

## `monitorState` (type: `string`):

Key-value store containing seen Recall IDs when onlyNew is enabled.

# 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 = {
    "sinceDays": 20,
    "startDate": "",
    "endDate": "",
    "recallIds": [],
    "keyword": "",
    "productKeyword": "",
    "companyKeyword": "",
    "hazardKeyword": "",
    "remedyKeyword": "",
    "maxItems": 20,
    "sortBy": "newest",
    "onlyNew": false,
    "stateKey": "",
    "includeImages": true
};

// Run the Actor and wait for it to finish
const run = await client.actor("automation-lab/cpsc-recalls-remedies-monitor").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 = {
    "sinceDays": 20,
    "startDate": "",
    "endDate": "",
    "recallIds": [],
    "keyword": "",
    "productKeyword": "",
    "companyKeyword": "",
    "hazardKeyword": "",
    "remedyKeyword": "",
    "maxItems": 20,
    "sortBy": "newest",
    "onlyNew": False,
    "stateKey": "",
    "includeImages": True,
}

# Run the Actor and wait for it to finish
run = client.actor("automation-lab/cpsc-recalls-remedies-monitor").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 '{
  "sinceDays": 20,
  "startDate": "",
  "endDate": "",
  "recallIds": [],
  "keyword": "",
  "productKeyword": "",
  "companyKeyword": "",
  "hazardKeyword": "",
  "remedyKeyword": "",
  "maxItems": 20,
  "sortBy": "newest",
  "onlyNew": false,
  "stateKey": "",
  "includeImages": true
}' |
apify call automation-lab/cpsc-recalls-remedies-monitor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,automation-lab/cpsc-recalls-remedies-monitor"
        }
    }
}

```

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/opmJXoVDqL6JPfN7k/builds/PHxj7dhnJjhVBwwb0/openapi.json
