# FDA Scraper - Recalls, Adverse Events & Device Data (`scrapesage/fda-scraper`) Actor

Scrape the U.S. FDA (openFDA): drug, device & food recalls, adverse events (FAERS/MAUDE/CAERS), 510(k) & PMA device clearances, drug labels/approvals/NDC, and medical-device manufacturer leads. Keyless, no browser, monitor mode + analytics.

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

## Pricing

from $2.20 / 1,000 recall scrapeds

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/platform/actors/running/actors-in-store#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

## FDA Scraper — Recalls, Adverse Events, Device Clearances & Manufacturer Leads (openFDA)

Extract **complete U.S. FDA regulatory data** from the official [openFDA](https://open.fda.gov) API in one actor: **drug, device & food recalls**, **adverse-event reports** (FAERS, MAUDE, CAERS), **510(k) clearances & PMA approvals**, **device classification & UDI**, **drug labels, Drugs@FDA approvals & the NDC directory** — plus ready-to-contact **medical-device manufacturer leads** (firm, contact name, phone, address) and built-in **analytics**.

Most FDA scrapers do **one** thing — drug recalls *or* device recalls *or* 510(k)s. This one covers **all of openFDA** with a single input, ships the **richest normalized record in the category**, adds a **risk score** to every recall and a **lead score** to every manufacturer, and supports a **monitor mode** for recall & safety alerts.

No login, no API key required, no browser — fast JSON extraction straight from the FDA's own API.

### Why this FDA scraper?

| Capability | Typical FDA scrapers | This actor |
|---|---|---|
| Drug **and** device **and** food recalls | one only | ✅ all three |
| Adverse events: FAERS (drug) + MAUDE (device) + CAERS (food) | rarely | ✅ all three |
| 510(k), PMA, classification, UDI | one endpoint | ✅ all device endpoints |
| Drug labels, Drugs@FDA approvals, NDC directory | rarely | ✅ |
| Recall **risk level** (Class I/II/III → Critical/Serious/Low) | ❌ | ✅ |
| Device-manufacturer **leads** (contact + phone + address + lead score) | ❌ | ✅ |
| Full openFDA harmonization block (RxCUI, UNII, pharm class, FEI…) | partial | ✅ |
| **Analytics** (top firms, recalls by state, top reactions) | ❌ | ✅ |
| **Monitor mode** — only new/changed records | ❌ | ✅ |
| API key required | sometimes | ❌ keyless |

### Use cases

- **Recall & safety monitoring** — schedule daily/weekly runs with **monitor mode** to catch new Class I drug, device or food recalls the moment the FDA posts them; push to Slack, email or your CRM.
- **Pharmacovigilance & post-market surveillance** — pull FAERS/MAUDE/CAERS adverse-event reports for a drug, device or food product; aggregate top reactions and seriousness.
- **Regulatory & competitive intelligence** — track competitors' **510(k) clearances** and **PMA approvals**, new **drug approvals** (Drugs@FDA), label changes and NDC listings.
- **Product-liability & mass-tort legal research** — find recalls, adverse events and clearances for a specific device or drug, with firms, dates and risk levels.
- **Medical-device manufacturer lead generation** — turn the FDA establishment registry into a B2B prospecting list: firm name, contact person, phone, full address, product codes and a 0–100 lead score.
- **Market analytics** — one-click counts: recalls by classification or state, top recalling firms, most-reported adverse reactions, devices by product code.

### How to use

1. [Sign up for Apify](https://console.apify.com/sign-up) — the free plan is enough to try this actor.
2. Open the **FDA Scraper**, pick a **What to scrape** type (e.g. *Drug recalls*), add a keyword or filters, and click **Start**.
3. Watch results stream into the dataset table — switch the **view** (Recalls, Manufacturer leads, Device clearances, Adverse events, Drug products, Analytics) to see the right columns.
4. **Export** as JSON, CSV, Excel, XML, or RSS — or pull results via the [Apify API](https://docs.apify.com/api/v2).

### Input

```json
{
    "searchType": "deviceRecalls",
    "keyword": "infusion pump",
    "classification": "Class I",
    "recallStatus": "Ongoing",
    "dateFrom": "2024-01-01",
    "maxResults": 200,
    "monitorMode": true
}
```

Key fields:

- **searchType** — `drugRecalls`, `deviceRecalls`, `foodRecalls`, `drugAdverseEvents` (FAERS), `deviceAdverseEvents` (MAUDE), `foodAdverseEvents` (CAERS), `device510k`, `devicePMA`, `deviceClassification`, `deviceEstablishments` (manufacturer leads), `deviceUDI`, `drugLabels`, `drugApprovals`, `drugNDC`, or `custom`.
- **keyword** — free-text search across the most relevant fields (product / brand / generic / device name, recall reason, reaction).
- **brandName / genericName / firmName** — precise matches.
- **classification / recallStatus** — recall filters (Class I/II/III; Ongoing/Completed/Terminated).
- **seriousOnly** — adverse-event datasets: keep only serious reports (death, life-threatening, hospitalization).
- **state / country / productCode** — geo and device-product-code filters.
- **dateFrom / dateTo** — `YYYY-MM-DD`, mapped to the right date field per dataset.
- **searchQuery** — optional raw openFDA query AND-ed with the filters.
- **searchUrls** — paste full `api.fda.gov` URLs to run them as-is.
- **outputMode** — `records` (default) or `analytics`; with analytics set **countField** (e.g. `classification`, `state`, `recalling_firm`, `patient.reaction.reactionmeddrapt`).
- **monitorMode / monitorKey** — only output new/changed records across runs.
- **apiKey** — optional free openFDA key for higher limits (the actor is keyless by default).

### Output

One record per FDA entry, tagged with a `type`. Example — a device recall:

```json
{
    "type": "recall",
    "dataset": "device",
    "endpoint": "enforcement",
    "recallNumber": "Z-1234-2025",
    "status": "Ongoing",
    "isOngoing": true,
    "classification": "Class I",
    "riskLevel": 3,
    "riskLabel": "Critical — reasonable probability of serious harm or death",
    "productDescription": "Volumetric Infusion Pump, model X100",
    "reasonForRecall": "Software error may cause under-infusion of medication.",
    "recallingFirm": "Acme Medical Devices, Inc.",
    "firmAddress": "1 Industrial Way, Boston, MA 02101, United States",
    "city": "Boston",
    "state": "MA",
    "country": "United States",
    "recallInitiationDate": "2025-02-10",
    "reportDate": "2025-03-01",
    "daysToClassify": 19,
    "openfda": { "device_name": "Infusion Pump", "medical_specialty_description": "General Hospital", "regulation_number": "880.5725", "device_class": "2" },
    "scrapedAt": "2026-06-17T12:00:00.000Z"
}
```

A medical-device **manufacturer lead** (`searchType: "deviceEstablishments"`):

```json
{
    "type": "establishment",
    "firmName": "GLOBUS MEDICAL, INC.",
    "contactName": "DANIEL S PAUL",
    "contactPhone": "x-610-9301800-1680",
    "address": "2560 General Armistead Ave, AUDUBON, PA, 19403, US",
    "city": "AUDUBON",
    "state": "PA",
    "country": "US",
    "establishmentTypes": ["Manufacture Medical Device"],
    "isImporter": false,
    "registrationNumber": "3004142400",
    "feiNumber": "3004142400",
    "productCount": 4,
    "deviceNames": ["Spinal Vertebral Body Replacement Device"],
    "leadScore": 84,
    "scrapedAt": "2026-06-17T12:00:00.000Z"
}
```

Fields are `null` only when the FDA record genuinely doesn't contain them — never because the scraper skipped them.

### Automate & schedule

Run this actor on autopilot and pull results into your own stack:

- **[Apify API](https://docs.apify.com/api/v2)** — start runs, fetch datasets, and manage schedules over REST.
- **[apify-client for JavaScript](https://docs.apify.com/api/client/js/)** and **[apify-client for Python](https://docs.apify.com/api/client/python/)** — official SDKs.
- **[Schedules](https://docs.apify.com/platform/schedules)** — run it hourly/daily/weekly with **monitor mode** to track new recalls, approvals or adverse events; perfect for safety alerts and lead pipelines.
- **[Webhooks](https://docs.apify.com/platform/integrations/webhooks)** — trigger downstream actions (CRM import, Slack alert, email sequence) the moment a run finishes.

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

const client = new ApifyClient({ token: 'MY_APIFY_TOKEN' });

const run = await client.actor('scrapesage/fda-scraper').call({
    searchType: 'drugRecalls',
    classification: 'Class I',
    recallStatus: 'Ongoing',
    monitorMode: true,
    maxResults: 500,
});

const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(`Got ${items.length} FDA records`);
```

### Integrate with any app

Connect the dataset to 5,000+ apps — no code required:

- **[Make](https://docs.apify.com/platform/integrations/make)** — multi-step automation scenarios.
- **[Zapier](https://docs.apify.com/platform/integrations/zapier)** — push new recalls or manufacturer leads straight into your CRM.
- **[Slack](https://docs.apify.com/platform/integrations/slack)** — get notified when a monitored search finds a new Class I recall.
- **[Google Drive / Sheets](https://docs.apify.com/platform/integrations/drive)** — auto-export every run to a spreadsheet.
- **[Airbyte](https://docs.apify.com/platform/integrations/airbyte)** — pipe results into your data warehouse.
- **[GitHub](https://docs.apify.com/platform/integrations/github)** — trigger runs from commits or releases.

### Use with AI assistants (MCP)

The output is clean, LLM-ready JSON. Call this actor from Claude, ChatGPT, or any agent framework through the **[Apify MCP server](https://docs.apify.com/platform/integrations/mcp)** — ask your assistant to "find ongoing Class I device recalls for infusion pumps this year" and let it run this scraper for you.

### Agent-ready: autonomous payments (x402 & Skyfire)

This actor is **agent-ready** — AI agents can discover it, run it, and **pay for it autonomously**, with no Apify account and no human in the loop. It uses [pay-per-event](https://docs.apify.com/platform/actors/publishing/monetize/pay-per-event) pricing and [limited permissions](https://docs.apify.com/platform/actors/development/permissions), so it qualifies for Apify's agentic-payment standards:

- **[x402](https://docs.apify.com/platform/integrations/x402)** — an open, HTTP-native payment protocol. Agents pay per run in USDC on the Base network directly through the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp) — no account, no API key.
- **[Skyfire](https://docs.apify.com/platform/integrations/skyfire)** — agent-to-service payments for fully autonomous AI-agent workflows.

Building an AI agent, MCP tool, or autonomous data pipeline? This scraper is ready to plug in and pay as it goes.

### More scrapers from scrapesage

Build a complete **healthcare, regulatory & lead-gen stack**:

- **[Healthgrades Scraper](https://apify.com/scrapesage/healthgrades-scraper)** — doctors, specialties, reviews & provider leads.
- **[WebMD Scraper](https://apify.com/scrapesage/webmd-scraper)** — physicians, insurance accepted & provider leads.
- **[FindLaw Scraper](https://apify.com/scrapesage/findlaw-scraper)** — attorney & law-firm leads (mass-tort / product-liability prospecting).
- **[Insurance Agent Scraper](https://apify.com/scrapesage/insurance-agent-scraper)** — multi-carrier insurance agent leads.
- **[SAM.gov Scraper](https://apify.com/scrapesage/sam-gov-scraper)** — U.S. federal entities, contracts & opportunities.

### Tips

- **Deep result sets**: openFDA caps pagination at ~25,000 records per query. To exhaust a large dataset, narrow with `dateFrom`/`dateTo` windows or a keyword and run in batches.
- **Recurring monitoring**: combine [Schedules](https://docs.apify.com/platform/schedules) with `monitorMode` so each run outputs only the new/changed records — ideal for daily recall alerts.
- **Analytics first**: run `outputMode: "analytics"` with `countField` to see the shape of the data (top firms, states, reactions) before pulling full records.
- **Higher limits**: the actor is keyless and rotates proxy sessions to spread the per-IP limit; for very large jobs add a free `apiKey`.

### FAQ

**Do I need an FDA or openFDA API key?** No. The actor works keyless. Add an optional free key only for very high-volume jobs.

**What datasets are covered?** Drug (enforcement/recalls, FAERS events, labels, Drugs@FDA approvals, NDC), Device (enforcement/recalls, MAUDE events, 510(k), PMA, classification, registration & listing, UDI), and Food (enforcement/recalls, CAERS events). The `custom` type exposes any other openFDA endpoint.

**How fresh is the data?** It's the FDA's own openFDA API — as current as the FDA publishes (recall and event datasets typically update weekly).

**Can I export to Google Sheets, CSV, or Excel?** Yes — one click in the dataset view, or automatically every run via the [Google Drive integration](https://docs.apify.com/platform/integrations/drive).

**How do I monitor new recalls automatically?** Turn on `monitorMode`, create a [Schedule](https://docs.apify.com/platform/schedules), and optionally add a [webhook](https://docs.apify.com/platform/integrations/webhooks) or [Zapier zap](https://docs.apify.com/platform/integrations/zapier).

**Where do manufacturer contact details come from?** From the FDA's public device registration & listing database (official correspondent + firm address). This is public regulatory data.

**Is this data official?** Yes — it comes directly from the FDA's openFDA API. Note the FDA's disclaimer: openFDA data is not for making medical decisions and should not be assumed to be error-free.

### Need help?

Open an issue on the actor's **Issues** tab, or visit the [Apify help center](https://help.apify.com/). Feature requests are welcome — this actor is actively maintained.

# Actor input Schema

## `searchType` (type: `string`):

Which openFDA dataset to query. Recalls and adverse events power monitoring & safety use cases; clearances/approvals/labels/NDC power regulatory & competitive intelligence; device establishments are ready-to-contact manufacturer leads.

## `outputMode` (type: `string`):

`Records` returns one rich row per FDA record. `Analytics` returns aggregated counts (top recalling firms, recalls by state, most-reported adverse reactions, etc.) — set the Count field below.

## `countField` (type: `string`):

Field to aggregate on when Output mode = Analytics, e.g. `classification`, `state`, `reason_for_recall`, `recalling_firm`, `patient.reaction.reactionmeddrapt` (FAERS), `product_code` (devices). `.exact` is added automatically for text fields; use a date field (e.g. `report_date`) for a time-series histogram.

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

Only for searchType = custom. One of: `drug`, `device`, `food`, `animalandveterinary`, `tobacco`, `other`.

## `endpoint` (type: `string`):

Only for searchType = custom. E.g. `enforcement`, `event`, `label`, `ndc`, `drugsfda`, `510k`, `pma`, `classification`, `recall`, `registrationlisting`, `udi`, `problem`.

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

Free-text search across the most relevant fields for the chosen dataset (product / brand / generic / device name, recall reason, reaction…). Example: `insulin`, `infusion pump`, `peanut`, `ozempic`.

## `brandName` (type: `string`):

Match a specific brand/trade name (drug or device).

## `genericName` (type: `string`):

Match a specific generic or active-substance name.

## `firmName` (type: `string`):

Recalling firm (recalls), applicant/sponsor (clearances/approvals), labeler (NDC) or establishment name (manufacturer leads).

## `classification` (type: `string`):

Recalls only. Class I = most serious (probable serious harm/death), Class II = temporary/reversible harm, Class III = unlikely to cause harm.

## `recallStatus` (type: `string`):

Recalls only.

## `seriousOnly` (type: `boolean`):

Adverse-event datasets only — limit to reports flagged serious (death, life-threatening, hospitalization, disability) for drugs; death/injury for devices.

## `state` (type: `string`):

Two-letter state code for recalls (`CA`, `NY`) or device establishments. Filters by the firm/establishment location.

## `country` (type: `string`):

Country filter. Recalls use the full name (`United States`); device establishments use the ISO code (`US`, `DE`, `CN`).

## `productCode` (type: `string`):

Three-letter FDA device product code (e.g. `LZG`, `DXT`). Applies to device clearances, PMA, classification, establishments, UDI and MAUDE.

## `dateFrom` (type: `string`):

Earliest date (`YYYY-MM-DD`). Mapped to the right date field per dataset — recall report date, adverse-event receive date, clearance/approval decision date, etc. Great for incremental monitoring.

## `dateTo` (type: `string`):

Latest date (`YYYY-MM-DD`).

## `searchQuery` (type: `string`):

Optional raw openFDA query, AND-ed with the filters above. Uses openFDA syntax, e.g. `openfda.pharm_class_epc:"nonsteroidal anti-inflammatory drug"` or `event_type:Death`. See the openFDA query docs.

## `searchUrls` (type: `array`):

Paste full openFDA API URLs (e.g. `https://api.fda.gov/drug/enforcement.json?search=classification:"Class I"`). Each is run as-is — overrides the dataset/filters above. Handy for reproducing a query you built in the openFDA explorer.

## `maxResults` (type: `integer`):

Maximum records (or analytics buckets) to output.

## `deduplicateResults` (type: `boolean`):

Skip duplicate records within a run.

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

Optional free openFDA API key for higher rate limits (240→240k requests/day). Leave blank — the actor works keyless via rotating proxy sessions. Get one at open.fda.gov/apis/authentication.

## `monitorMode` (type: `boolean`):

Remember records across runs and output only new or changed ones each time (a recall re-appears when its status changes). Pairs perfectly with Apify Schedules for recall & safety alerts. Uses its own named store — does not interfere with scheduling.

## `monitorKey` (type: `string`):

Name this monitor watchlist. Use different keys for different saved searches so their histories stay separate.

## `proxyConfiguration` (type: `object`):

Apify Proxy settings. Datacenter proxy is plenty — the openFDA API is clean and keyless; the actor rotates sessions to spread the per-IP rate limit.

## `urlsFromFile` (type: `string`):

Paste a list of URLs (one per line), OR one link to a .txt/.csv file, Google Sheet or Google Drive file containing them. Lets you import many Start URLs at once instead of typing each. Google Sheet/Drive share links are handled automatically.

## Actor input object example

```json
{
  "searchType": "drugRecalls",
  "outputMode": "records",
  "keyword": "insulin",
  "classification": "",
  "recallStatus": "",
  "seriousOnly": false,
  "maxResults": 200,
  "deduplicateResults": true,
  "monitorMode": false,
  "monitorKey": "default",
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

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

All scraped records in the default dataset.

# 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 = {
    "keyword": "insulin",
    "maxResults": 200,
    "urlsFromFile": ""
};

// Run the Actor and wait for it to finish
const run = await client.actor("scrapesage/fda-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 = {
    "keyword": "insulin",
    "maxResults": 200,
    "urlsFromFile": "",
}

# Run the Actor and wait for it to finish
run = client.actor("scrapesage/fda-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 '{
  "keyword": "insulin",
  "maxResults": 200,
  "urlsFromFile": ""
}' |
apify call scrapesage/fda-scraper --silent --output-dataset

```

## MCP server setup

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