# FDA Recalls Scraper & openFDA API: Food, Drug & Device Recalls (`manageable_gully/fda-recalls-scraper`) Actor

Search FDA recalls (enforcement reports) for food, drugs and medical devices via the official openFDA API: keyword, firm, Class I/II/III, status, state, dates. Brand names, NDC, lot codes, FDA link. Recall alerts. $0.50 per 1,000 recalls.

- **URL**: https://apify.com/manageable_gully/fda-recalls-scraper.md
- **Developed by:** [WebIntel Tools](https://apify.com/manageable_gully) (community)
- **Categories:** Lead generation, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.50 / 1,000 recall records

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?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
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.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## 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.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## FDA Recalls Scraper & openFDA API: Food, Drug & Medical Device Recalls with Alerts

Get **FDA recall data as clean JSON, CSV or Excel** from the **official openFDA enforcement report API**: search **food, dietary supplement, cosmetic, drug and medical device recalls** by **keyword, recalling firm, Class I/II/III, status, US state, country and dates**, and get one flat row per recall with **product, reason for recall, lot/code info, quantity, distribution, firm, dates, risk level, brand/generic names, NDC codes and an FDA link**. Schedule it as a **daily or weekly recall alert**.

No browser, no login, no API key, no proxy. **$0.50 per 1,000 recalls.**

### What you can use it for

- **Food safety & retail compliance:** every Listeria, Salmonella, undeclared allergen or foreign-material recall that touches your products, suppliers or states.
- **Pharmacy & hospital recall monitoring:** drug recalls with brand and generic names, NDC codes, lot numbers and Class I alerts.
- **Medical device quality & regulatory teams:** device recalls by firm, product code and device class, for vigilance, supplier audits and competitor tracking.
- **Recall alerts:** schedule it with **Only new recalls** and send new recalls to Slack, e-mail, Google Sheets or your QMS (Make, Zapier, n8n, webhooks).
- **Supplier risk & due diligence:** recall history of a company before you buy from, invest in or partner with it.
- **Research, journalism, analytics and AI agents:** normalised recall data for dashboards, trend analysis, LLMs and RAG.

### How to use it

1. Pick **categories** (food, drug, device; all three by default) and optionally enter **keywords** (`listeria`, `peanut`, `metformin`, `insulin pump`) or **recalling firms**.
2. Optional filters: **classification** (Class I = most serious), **status** (ongoing, completed, terminated), **US states**, **countries**, **voluntary vs FDA-mandated**, **report date** and **recall initiation date** (absolute or relative like `30 days`), or an advanced **openFDA query**.
3. Click **Start**. Export to CSV/Excel/JSON or connect it to your tools. For alerts, turn on **Only new recalls** and schedule it.

### Why this FDA recall scraper

- **Official source only:** the U.S. FDA's public openFDA enforcement report APIs (food, drug, device). No HTML scraping that breaks when a website changes.
- **All three recall databases in one run**, each tagged with its category, with the same clean columns.
- **Every filter that matters:** keywords across product description, recall reason and lot codes; firm; Class I/II/III; status; state; country; voluntary/mandated; report and initiation date ranges; raw openFDA queries for anything else.
- **Clean, flat output:** recall number, event ID, classification + plain-English risk level, status, product type, product description, reason for recall, recalling firm, city/state/country, voluntary/mandated, notification method, distribution pattern, quantity, lot/code info, initiation / classification / report / termination dates, days since initiation and an FDA recall-event link. Drug and device rows add **brand names, generic names, manufacturer, NDC codes, substances, routes, application numbers, device names, device class and product codes** when openFDA has them.
- **No 25,000-record ceiling:** pages with openFDA's `search_after` cursor, so full exports (100k+ recalls) work.
- **Alerts built in:** **Only new recalls** remembers what you already received (per State key); already-seen recalls are free.
- **Fast and light:** up to 1,000 recalls per API page, thousands per minute, 256 MB memory.
- **Privacy by design:** recall-level data about products and companies only. The firm's street address and postal code are not included (city, state and country are), and firm names that look like an individual person are withheld.
- **Cheapest per record:** $0.50 per 1,000 recalls, $0.0003 per run start.

### Input examples

Class I food recalls for Listeria reported in the last 90 days:

```json
{ "categories": ["food"], "searchTerms": ["listeria"], "classifications": ["Class I"], "reportedFrom": "90 days" }
```

Weekly alert: any new drug or device recall from California firms:

```json
{ "categories": ["drug", "device"], "states": ["CA"], "reportedFrom": "30 days", "onlyNew": true, "stateKey": "ca-weekly", "maxItems": 0 }
```

Recall history of a company:

```json
{ "firms": ["Medtronic"], "categories": ["device"], "maxItems": 0 }
```

Ongoing oral drug recalls (advanced openFDA query):

```json
{ "categories": ["drug"], "statuses": ["Ongoing"], "rawQuery": "openfda.route:\"ORAL\"" }
```

### Output (one row per recall, shortened)

```json
{
  "category": "food", "recallNumber": "H-0092-2027", "eventId": "99966",
  "classification": "Class I", "riskLevel": "high", "status": "Ongoing", "productType": "Food",
  "productDescription": "Deano's Pasta; Pear and Pecorino Triangoli Ravioli, 1lb. ...",
  "reasonForRecall": "Undeclared Lobster",
  "recallingFirm": "DEANO'S PASTA", "city": "Somerville", "state": "MA", "country": "United States",
  "voluntaryMandated": "Voluntary: Firm initiated", "initialFirmNotification": "Two or more of the following: Email, Fax, Letter, Press Release, Telephone, Visit",
  "distributionPattern": "MA, NH", "productQuantity": "78lbs", "codeInfo": "lot codes 090126126, 082526126,081826126, and 073126126",
  "recallInitiationDate": "2026-09-23", "centerClassificationDate": "2026-10-15", "reportDate": "2026-10-21",
  "terminationDate": null, "daysSinceInitiation": 35,
  "eventUrl": "https://www.accessdata.fda.gov/scripts/ires/index.cfm?Event=99966",
  "brandNames": [], "genericNames": [], "productNdc": [], "deviceClass": null,
  "scrapedAt": "2026-10-28T08:21:35Z"
}
```

A run summary (query, matching and saved recalls per category, already seen) is stored in the key-value store as `OUTPUT`.

### Pricing

Pay per event, no subscription:

| Event | Price |
|---|---|
| Recall saved | $0.0005 ($0.50 per 1,000) |
| Actor start | $0.0003 |

| Example | Cost |
|---|---|
| 100 recalls | about $0.05 |
| 1,000 recalls | about $0.50 |
| Daily alert, ~30 new recalls a day for 30 days | about $0.46 |

Set **Max cost per run** in the run options and the Actor stops cleanly at that budget.

### API, integrations and AI agents (MCP)

Run it from your own code with the [Apify API](https://docs.apify.com/api/v2):

```bash
curl -X POST "https://api.apify.com/v2/acts/manageable_gully~fda-recalls-scraper/run-sync-get-dataset-items?token=<YOUR_APIFY_TOKEN>" \
  -H "Content-Type: application/json" -d '{"categories": ["food"], "searchTerms": ["salmonella"], "maxItems": 50}'
```

```python
from apify_client import ApifyClient
run = ApifyClient("<YOUR_APIFY_TOKEN>").actor("manageable_gully/fda-recalls-scraper").call(run_input={"categories": ["drug"], "classifications": ["Class I"]})
```

- **No-code:** use the Apify app in **n8n, Make or Zapier**, or send results to Google Sheets, Slack or a webhook.
- **AI agents (MCP):** add `https://mcp.apify.com?tools=manageable_gully/fda-recalls-scraper` to Claude, Cursor, VS Code or any MCP client.

### FAQ

**Where does the data come from?** The FDA's openFDA enforcement report endpoints (`/food/enforcement`, `/drug/enforcement`, `/device/enforcement`). openFDA data is public domain (CC0). openFDA updates these weekly; recalls appear once the FDA classifies them.

**Does it cover cosmetics and dietary supplements?** Yes, the FDA files them in the food enforcement database (category `food`).

**Do I need an openFDA API key?** No. The optional key only raises openFDA's daily request limit for very large repeated exports.

**Is this medical advice?** No. As the FDA notes, openFDA data is unvalidated; check the official FDA recall notice before acting.

**Need another field or source (e.g. FDA warning letters, adverse events)?** Open an issue on the Actor page.

This is an independent tool, not affiliated with or endorsed by the U.S. FDA; every row links back to the FDA recall event.

### More tools from WebIntel Tools

- [ClinicalTrials.gov Scraper](https://apify.com/manageable_gully/clinical-trials-scraper): clinical trials search with new-trial alerts
- [arXiv & PubMed Paper Search](https://apify.com/manageable_gully/arxiv-pubmed-paper-search): research papers and abstracts from the official APIs
- [CVE Vulnerability Scraper](https://apify.com/manageable_gully/cve-vulnerability-scraper): NVD CVEs with CISA KEV and EPSS
- [EU Tenders Scraper (TED)](https://apify.com/manageable_gully/ted-eu-tenders-scraper): EU public procurement notices and tender alerts

See [all WebIntel Tools Actors](https://apify.com/manageable_gully).

*Made by WebIntel Tools. This Actor was built and is maintained with AI assistance. Report issues on the Issues tab; they are monitored daily.*

# Actor input Schema

## `categories` (type: `array`):

FDA enforcement report databases to search. Food also covers dietary supplements, cosmetics and animal food. Leave empty for all three.

## `searchTerms` (type: `array`):

Words or phrases matched in the product description, recall reason and lot/code info, e.g. `listeria`, `peanut`, `insulin pump`, `metformin`. Several values are combined with OR.

## `firms` (type: `array`):

Company names, e.g. `Teva`, `Medtronic`. Several values are combined with OR.

## `classifications` (type: `array`):

Class I = serious health risk or death, Class II = temporary or reversible harm, Class III = unlikely to cause harm. Leave empty for all.

## `statuses` (type: `array`):

Leave empty for all statuses.

## `states` (type: `array`):

2-letter codes, e.g. `CA`, `NY`, `TX`.

## `countries` (type: `array`):

e.g. `United States`, `China`, `India`, `Canada`.

## `voluntaryMandated` (type: `string`):

Filter by who initiated the recall. Leave empty for any.

## `reportedFrom` (type: `string`):

Enforcement report date. YYYY-MM-DD, YYYY-MM or relative (`7 days`, `3 months`, `1 year`).

## `reportedTo` (type: `string`):

YYYY-MM-DD, YYYY-MM, relative or `today`.

## `initiatedFrom` (type: `string`):

Date the firm started the recall. YYYY-MM-DD, YYYY-MM or relative.

## `initiatedTo` (type: `string`):

YYYY-MM-DD, YYYY-MM, relative or `today`.

## `rawQuery` (type: `string`):

Optional openFDA search expression added with AND, e.g. `openfda.route:"ORAL"` or `distribution_pattern:"nationwide"`. See open.fda.gov/apis/query-syntax.

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

Order of the results within each category.

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

Stop after this many recalls in each category. Empty = 1,000. 0 = no limit (all ~100k records; use filters).

## `includeProductCodes` (type: `boolean`):

Add brand/generic names, NDC codes, substances, routes, application numbers (drugs) and device names/class/product codes when openFDA has them.

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

Remember recalls already delivered (per State key) and return only new ones on the next run. Already-seen recalls are free. Schedule daily or weekly for recall alerts.

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

Separate alert memory per saved search.

## `apiKey` (type: `string`):

Not needed. A free openFDA key (open.fda.gov/apis/authentication) raises the daily request limit for very large exports.

## Actor input object example

```json
{
  "categories": [
    "food",
    "drug",
    "device"
  ],
  "searchTerms": [
    "listeria"
  ],
  "reportedFrom": "90 days",
  "sortBy": "newest",
  "maxItems": 100,
  "includeProductCodes": true,
  "onlyNew": false,
  "stateKey": "default"
}
```

# Actor output Schema

## `results` (type: `string`):

One row per recall: category, recall number, classification and risk level, status, product, reason, recalling firm, city/state/country, distribution, quantity, lot codes, dates, openFDA product codes and FDA link.

## `summary` (type: `string`):

Query used, matching and saved recalls per category, already-seen recalls skipped.

# 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 = {
    "categories": [
        "food",
        "drug",
        "device"
    ],
    "searchTerms": [
        "listeria"
    ],
    "reportedFrom": "90 days",
    "maxItems": 100
};

// Run the Actor and wait for it to finish
const run = await client.actor("manageable_gully/fda-recalls-scraper").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 = {
    "categories": [
        "food",
        "drug",
        "device",
    ],
    "searchTerms": ["listeria"],
    "reportedFrom": "90 days",
    "maxItems": 100,
}

# Run the Actor and wait for it to finish
run = client.actor("manageable_gully/fda-recalls-scraper").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 '{
  "categories": [
    "food",
    "drug",
    "device"
  ],
  "searchTerms": [
    "listeria"
  ],
  "reportedFrom": "90 days",
  "maxItems": 100
}' |
apify call manageable_gully/fda-recalls-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,manageable_gully/fda-recalls-scraper"
        }
    }
}
```

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/9CemfZFsLEYV5iWhI/builds/cJFWAHOdiz9oXhgaa/openapi.json
