# Product Recalls & Safety Alerts Monitor — ANZ, US & EU (`datadeltas/recalls-monitor`) Actor

Unified product recall and safety alert feed across Australia, New Zealand, the US and the EU: ACCC Product Safety, TGA, Medsafe, MPI food recalls, US CPSC, openFDA food/drug/device enforcement and EU Safety Gate (RAPEX). Regions default to ANZ.

- **URL**: https://apify.com/datadeltas/recalls-monitor.md
- **Developed by:** [Daniel Matthee](https://apify.com/datadeltas) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $20.00 / 1,000 recall detecteds

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

## Product Recalls & Safety Alerts Monitor — ANZ, US & EU

One unified, normalised feed of official product recalls and safety alerts
across **Australia, New Zealand, the United States and the European Union**,
refreshed on every scheduled run. Nine government sources, one consistent
record shape, and only **new** recalls are emitted — so every dataset item is
an actionable event, not a re-scrape.

Most recall scrapers cover a single agency, which leaves you stitching
together CPSC, FDA, Safety Gate and the ANZ regulators yourself, each with its
own field names and dedupe problem. This actor is the unified feed: pick your
regions, get one schema.

**Sources:**

| Source | `source` | Region | Coverage |
|---|---|---|---|
| ACCC Product Safety (productsafety.gov.au) | `accc` | AU | Consumer products — toys, appliances, vehicles, electronics |
| TGA safety alerts (tga.gov.au) | `tga` | AU | Medicines, medical devices, supplements |
| Medsafe recall actions (medsafe.govt.nz) | `medsafe` | NZ | Medicines and medical devices |
| MPI / NZ Food Safety (mpi.govt.nz) | `mpi` | NZ | Food recalls |
| CPSC (SaferProducts.gov) | `cpsc` | US | Consumer products — the US counterpart to ACCC |
| FDA enforcement reports (openFDA) | `fda-food` | US | Food, beverages, supplements, animal feed |
| FDA enforcement reports (openFDA) | `fda-drug` | US | Human and veterinary medicines |
| FDA enforcement reports (openFDA) | `fda-device` | US | Medical devices and diagnostics |
| EU Safety Gate / RAPEX (ec.europa.eu) | `eu-safetygate` | EU | Dangerous non-food products across all EU/EEA member states |

All nine sources are official government open data — no ToS risk in your
compliance chain, and no API keys required. (An optional openFDA key is
supported if you run very frequently; see the input table.)

**Regions default to ANZ.** Set `regions` to `["ANZ", "US", "EU"]` — or pick
`sources` explicitly — to widen coverage. Nothing changes for existing runs
unless you ask for it.

### Example output record

```json
{
  "source": "accc",
  "sourceId": "c09b530a-0353-4de5-8669-b2a29adcade3",
  "region": "AU",
  "title": "Basco BFO-15671 oil filter for diesel engines",
  "productNames": ["Basco BFO-15671 oil filter for diesel engines"],
  "brand": null,
  "hazard": "Risk of death, serious injury or property damage (including to other road users) from an accident if the filter loosens or comes off the engine while the vehicle is being driven...",
  "recallDate": "2026-08-27",
  "url": "https://www.productsafety.gov.au/search-consumer-product-recalls/basco-bfo-15671-oil-filter-for-diesel-engines",
  "categories": ["Car parts and accessories"],
  "detectedAt": "2026-08-31T01:22:44Z"
}
```

Notes on the shape: `sourceId` is stable per source (dedupe key),
`productNames` lists every product covered by one recall action (Medsafe
recalls often span several products), and `recallDate` is `null` for MPI
records because the MPI listing publishes dates only on detail pages —
`detectedAt` always tells you when the monitor first saw the recall.

Per-source specifics worth knowing:

- **CPSC** — `sourceId` is the CPSC `RecallID`; `brand` comes from the recall's
  manufacturer when CPSC publishes one (about a fifth of recalls), and
  `categories` is empty because CPSC currently ships its product-type field
  blank.
- **FDA** — `sourceId` is the FDA recall number, `recallDate` is openFDA's
  `report_date`, and `categories` is `[product type, classification]`, e.g.
  `["Food", "Class I"]`. openFDA has no per-recall notice page, so `url` is the
  openFDA permalink for that recall number. Enforcement reports published
  before FDA assigns a recall number ("Not Yet Classified") are held back until
  the number exists, because it is the dedupe key — they arrive a few weeks
  later rather than twice.
- **EU Safety Gate** — `sourceId` is the Safety Gate alert id and `url` links
  the official alert page. Safety Gate publishes one report every Friday, so
  `recallDate` is that week's publication date — the export carries no
  per-alert date. `categories` is `[product category, risk type]`, e.g.
  `["Jewellery", "Chemical"]`.

### Input options

| Field | Type | Default | Description |
|---|---|---|---|
| `sources` | array | four ANZ | Which sources to monitor: `accc`, `tga`, `medsafe`, `mpi`, `cpsc`, `fda-food`, `fda-drug`, `fda-device`, `eu-safetygate` |
| `regions` | array | `["ANZ"]` | Region shortcut — `ANZ`, `US`, `EU`. Ignored when `sources` is set |
| `keywords` | array | `[]` | Case-insensitive filter on title + product names; empty = everything |
| `sinceDays` | integer | `30` | First-run backfill window in days |
| `maxItems` | integer | `500` | Cap on records emitted per run (overflow emits next run) |
| `fdaApiKey` | string (secret) | empty | Optional. The FDA sources work keyless within openFDA's limits (240 req/min, 1,000/day per IP); a free key raises the daily ceiling to 120,000 |

A global run is higher volume than an ANZ-only one — a 30-day backfill across
all nine sources returns several hundred records, most of them FDA device and
EU Safety Gate alerts. Raise `maxItems` for the first backfill, or narrow with
`keywords`.

### How to use it

Schedule the actor (daily or every few hours). The first run backfills the
last `sinceDays` days; every later run emits only recalls it has never seen
before, so you can wire the dataset straight into Zapier/Make, a Slack
webhook, or your own ingestion without any dedupe logic on your side.

### Use cases

- **Compliance & product safety teams** — "global recall monitoring": one
  scheduled feed replaces manually checking nine government sites across three
  jurisdictions; filter with `keywords` for your brands or ingredient names.
- **Insurers & underwriters** — "product recall alerts insurance": early
  signal on hazards (fire, injury, undeclared allergens) affecting insured
  product categories, with the official hazard wording attached.
- **Marketplaces & retailers** — "screen listings recalled products": match
  `productNames` and `brand` against your catalogue to pull recalled stock
  before regulators or customers find it. A product pulled by CPSC or Safety
  Gate is usually on your ANZ listings too.
- **Importers & supply chain** — a product recalled in the US or EU is a
  leading indicator for the same SKU in AU/NZ; watching all three regions gives
  you weeks of warning instead of none.

### Failure handling & update promise

- One source being down or redesigned never kills a run: the source is
  logged as degraded and every other source still delivers.
- Schema drift is logged with the exact missing field, never a crash.
- Source markup is re-checked and fixtures refreshed on a regular cadence;
  parser fixes ship as patch releases.

### Pricing events

| Event | Price | Charged |
|---|---|---|
| `actor-start` | $0.005 | once per run |
| `recall-detected` | $0.02 | per NEW recall emitted |

Low volume by design — you pay for coverage, not bulk. A typical quiet day
across the four ANZ sources is a handful of events; a global run sees more,
so set `maxItems` to the ceiling you are comfortable paying for.

### Changelog

- **0.2** (2026-08-31) — global expansion: US CPSC, US FDA
  (`fda-food`/`fda-drug`/`fda-device`) and EU Safety Gate (RAPEX) added behind
  the `regions` input, plus an optional `fdaApiKey`. Additive only — the
  default input still runs the four ANZ sources and the record shape is
  unchanged.
- **0.1** (2026-08-31) — initial release: ACCC, TGA, Medsafe, MPI; monitor
  state in a named key-value store; keyword filter, backfill window,
  per-run item cap.

# Actor input Schema

## `sources` (type: `array`):

Which recall sources to monitor. Defaults to all ANZ sources; pick US or EU sources here, or use the 'Regions' shortcut.

## `regions` (type: `array`):

Region shortcut instead of picking sources one by one. Defaults to ANZ; add US and/or EU for global coverage. Ignored when 'Sources' is set.

## `keywords` (type: `array`):

Optional case-insensitive filter. A recall is emitted only if any keyword appears in its title or product names. Leave empty for all recalls.

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

On the first run, emit recalls published up to this many days back. Later runs only emit recalls not seen before.

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

Safety cap on records emitted in one run (keeps test runs cheap). Items beyond the cap are emitted on the next run.

## `fdaApiKey` (type: `string`):

Optional. The US FDA sources work without a key within openFDA's keyless limits (240 requests/minute, 1,000/day per IP) — a free key from open.fda.gov raises the daily ceiling to 120,000. Leave empty unless you are running very frequently.

## Actor input object example

```json
{
  "sources": [
    "accc",
    "tga",
    "medsafe",
    "mpi"
  ],
  "regions": [
    "ANZ"
  ],
  "keywords": [],
  "sinceDays": 30,
  "maxItems": 500
}
```

# Actor output Schema

## `records` (type: `string`):

No description

# 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 = {
    "sources": [
        "accc",
        "tga",
        "medsafe",
        "mpi"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("datadeltas/recalls-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 = { "sources": [
        "accc",
        "tga",
        "medsafe",
        "mpi",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("datadeltas/recalls-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 '{
  "sources": [
    "accc",
    "tga",
    "medsafe",
    "mpi"
  ]
}' |
apify call datadeltas/recalls-monitor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,datadeltas/recalls-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/qxv25c7VcMrA5FrBK/builds/q6XSgsX5q57ABPzw4/openapi.json
