# openFDA Scraper · Drug Events, Recalls & Labels (`reapx/openfda-scraper`) Actor

Scrape FDA drug adverse events, drug and food recalls, product labels, the NDC directory, device events, device recalls and 510(k) clearances from the public openFDA API. No key required, no browser. Pharmaceutical safety and medical device recall data.

- **URL**: https://apify.com/reapx/openfda-scraper.md
- **Developed by:** [Tarek Etman](https://apify.com/reapx) (community)
- **Categories:** Developer tools, Business, Other
- **Stats:** 1 total users, 0 monthly users, 93.8% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.30 / 1,000 record returneds

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

## openFDA Scraper — Drug Events, Recalls, Labels & Devices

Scrape **openFDA** — the FDA's public API — for drug adverse events, drug and food recalls,
product labels, the NDC directory, medical device events, device recalls and 510(k) clearances.
No API key required, no login, no headless browser. Run it empty and you get the newest drug
recalls; pick a different dataset and it returns that instead.

Eight FDA datasets, **over 46 million records**, every row keyed by its own FDA identifier.

### What this openFDA scraper returns

| Dataset | Records | Keyed by |
| --- | --- | --- |
| Drug recalls and enforcement | 17,800+ | Recall number |
| Drug adverse events (FAERS) | 20.3M | Safety report ID |
| Drug product labels (SPL) | 261,000+ | SPL set ID |
| NDC directory of marketed drugs | 136,000+ | Product NDC |
| Device recalls | 58,800+ | Product recall number |
| Device adverse events (MAUDE) | 25.3M | Report number |
| 510(k) device clearances | 175,000+ | K number |
| Food recalls and enforcement | 29,200+ | Recall number |

Every row carries `recordId`, `recordType`, `endpoint`, `primaryDate` and `scrapedAt`, plus the
fields that actually apply to that dataset — recall class and reason, reaction terms and
seriousness flags, label sections, ingredients and routes, applicant and review time.

Five named dataset views ship with it: **Records**, **Recalls**, **Adverse events**,
**Products & labels** and **510(k) clearances**.

### How to scrape openFDA

1. Pick a **dataset**. Leave everything else empty and you get the newest records.
2. Narrow by **product or brand name**, **company**, **recall class**, **status**, **state** or a **date window**.
3. For anything the plain-language filters do not cover, use the **raw openFDA query** field.
4. Set **Max records**. You are charged once per record returned, so that is your cost cap.

### Filters

- **Product or brand name** — matches the product, brand or device name fields of the chosen dataset
- **Company or firm** — recalling firm, labeler, applicant or manufacturer
- **Date window** — a rolling "last N days" or explicit from/to dates, applied to that dataset's main date
- **Recall classification** — Class I, II or III — and **recall status**
- **US state** and **country**
- **Serious outcomes only**, **reports involving death only**, and a **MedDRA reaction term**
- **Raw openFDA query** — any expression from the openFDA query syntax, ANDed with the rest

### What you can build with it

- **Recall monitoring** — run daily on drug, device or food recalls and diff by `recordId`.
- **Pharmacovigilance signals** — count reaction terms for a drug across FAERS over a date window.
- **Competitive device intelligence** — every 510(k) an applicant has cleared, with review times.
- **Label change tracking** — pull SPL labels by set ID and watch indications and warnings move.
- **Formulary and NDC datasets** — the marketed drug directory with ingredients, routes and DEA schedule.
- **Food safety alerting** — Class I food recalls by state, as they are published.
- **Regulatory RAG corpora** — label text and recall reasons with a citable FDA identifier on every row.

### Pricing

Pay per event: **$0.002 per record returned**, with automatic discounts on every Apify plan tier
(Bronze through Diamond). Nothing else is billed to you — no separate platform-usage line.

You are charged **only** for complete records written to the dataset. A rate-limited or
unreachable API, a query openFDA rejects, and a search that matches nothing all cost **zero**.
Set **Max total charge** on the run to cap spend; the actor checks that cap before it starts and
stops cleanly the moment it is reached.

### Input example

```json
{
  "dataset": "drug-recalls",
  "classification": "Class I",
  "lastNDays": 365,
  "maxRecords": 500
}
```

### Output example

```json
{
  "recordId": "D-0690-2026",
  "recordType": "drug-recall",
  "endpoint": "drug/enforcement",
  "primaryDate": "2026-07-09",
  "productDescription": "BD ChloraPrep Clear, 2% chlorhexidine gluconate and 70% isopropyl alcohol, 60 x 1 mL applicators",
  "reasonForRecall": "Lack of Assurance of Sterility: affected product may exhibit an open or incomplete seal",
  "classification": "Class II",
  "recallStatus": "Ongoing",
  "recallingFirm": "CareFusion 213, LLC",
  "productQuantity": "43,066,599 units",
  "distributionPattern": "U.S.A. Nationwide",
  "city": "El Paso",
  "state": "TX",
  "country": "United States",
  "reportDate": "2026-07-22",
  "eventId": "99377",
  "scrapedAt": "2026-08-03T00:10:00Z"
}
```

### FAQ

#### How do I scrape openFDA data?

Pick a dataset and run. Everything comes from `api.fda.gov`, the FDA's own public API, which
needs no authentication for normal use.

#### Do I need an openFDA API key?

Not for most runs. Without a key openFDA allows 1,000 requests per day per IP; this actor pulls
1,000 records per request, so that is a great deal of data. For very large jobs, paste a free key
from open.fda.gov/apis/authentication into the optional **openFDA API key** field and the limit
rises to 120,000 requests per day.

#### How do I find Class I recalls?

Choose **Drug recalls** or **Food recalls**, set **Recall classification** to Class I, and
optionally add a date window. Class I means FDA judged there is a reasonable probability of
serious harm or death.

#### How do I search adverse events for one drug?

Choose **Drug adverse events (FAERS)** and put the drug name in **Product or brand name**. Add a
**Reaction term** such as `ANAPHYLACTIC REACTION` to narrow to one reaction, or turn on **Reports
involving death only**.

#### How far back does the data go?

It varies by dataset — FAERS runs from 2004, enforcement reports from 2012, 510(k) clearances
from 1976. Set **From date** as early as you like; the actor passes it straight through.

#### How many records can one run return?

Up to 25,000 for a single query, which is openFDA's own paging ceiling. Split a larger job into
date windows and run each one.

#### What identifies each row?

`recordId` — the recall number, safety report ID, SPL set ID, NDC, K number or device recall
number, depending on the dataset. It is FDA's own identifier and is stable across runs.

#### Can I use my own openFDA query syntax?

Yes. The **Raw openFDA query** field takes any expression the API accepts, for example
`openfda.pharm_class_epc:"Antibacterial"`, and it is combined with the other filters using AND.

#### Can an AI agent call this actor?

Yes. Every input and output field carries a title, description and example, and every row is
addressed by its FDA `recordId`, so an agent can fill the input and chain the output without
extra prompting.

***

Unofficial - not affiliated with the FDA. Collects public data only. reapx.
Contact reapxdev@proton.me.

# Actor input Schema

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

Which openFDA endpoint to read. Each one returns a different kind of record, all keyed by their own FDA identifier.

## `searchTerm` (type: `string`):

Matches the product, brand or device name fields of the chosen dataset.

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

Recalling firm, labeler, applicant or manufacturer, depending on the dataset.

## `maxRecords` (type: `integer`):

Hard cap on how many records the run returns. This is also your cost cap: you are charged once per record returned. openFDA serves at most 25,000 records for one query.

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

Ordering on the dataset's main date field.

## `lastNDays` (type: `integer`):

Rolling window on the dataset's main date — recall initiation, report received, decision date or marketing start. Ignored if you set an explicit "From date". Note the adverse event datasets lag: FAERS is usually 3-5 months behind and MAUDE 1-2 months, so windows under 180 days can come back empty.

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

Earliest date, YYYY-MM-DD.

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

Latest date, YYYY-MM-DD.

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

Class I is the most serious (reasonable probability of serious harm), Class III the least. Applies to drug and food recalls.

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

Where the recall stands today. Drug and food recalls use Ongoing/Completed/Terminated; device recalls use Open, Classified/Terminated/Completed.

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

Two-letter state code of the recalling firm or applicant.

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

Country of the recalling firm or applicant.

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

Keep only adverse event reports FDA flagged as serious. Applies to drug adverse events.

## `deathsOnly` (type: `boolean`):

Keep only adverse event reports where death was an outcome.

## `reaction` (type: `string`):

MedDRA reaction term as FDA records it, in capitals, e.g. HEADACHE, NAUSEA, ANAPHYLACTIC REACTION.

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

Advanced. A raw openFDA search expression, combined with every other filter using AND. Example: openfda.pharm\_class\_epc:"Antibacterial". Full syntax at open.fda.gov/apis/query-syntax.

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

Optional and free from open.fda.gov/apis/authentication. Without one, openFDA allows 1,000 requests per day per IP; with one, 120,000. Only needed for very large runs.

## Actor input object example

```json
{
  "dataset": "drug-recalls",
  "searchTerm": "insulin",
  "firmName": "Medtronic",
  "maxRecords": 100,
  "sortBy": "newest",
  "lastNDays": 90,
  "dateFrom": "2026-01-01",
  "dateTo": "2026-12-31",
  "classification": "Class I",
  "recallStatus": "Ongoing",
  "state": "CA",
  "country": "United States",
  "seriousOnly": true,
  "deathsOnly": true,
  "reaction": "ANAPHYLACTIC REACTION",
  "searchQuery": "openfda.route:\"INTRAVENOUS\"",
  "apiKey": "your-openfda-key"
}
```

# Actor output Schema

## `items` (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 = {
    "dataset": "drug-recalls",
    "maxRecords": 100,
    "sortBy": "newest"
};

// Run the Actor and wait for it to finish
const run = await client.actor("reapx/openfda-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 = {
    "dataset": "drug-recalls",
    "maxRecords": 100,
    "sortBy": "newest",
}

# Run the Actor and wait for it to finish
run = client.actor("reapx/openfda-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "dataset": "drug-recalls",
  "maxRecords": 100,
  "sortBy": "newest"
}' |
apify call reapx/openfda-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=reapx/openfda-scraper",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/7I7mVgWEEjiCGTSNz/builds/oQpK1RV69YjN4VOQd/openapi.json
