openFDA Scraper · Drug Events, Recalls, Labels & Devices
Pricing
from $1.30 / 1,000 record returneds
openFDA Scraper · Drug Events, Recalls, Labels & Devices
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.
Pricing
from $1.30 / 1,000 record returneds
Rating
0.0
(0)
Developer
Tarek Etman
Maintained by CommunityActor stats
0
Bookmarked
1
Total users
0
Monthly active users
5 hours ago
Last modified
Categories
Share

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.
Maintained by reapX. Every row cites the Apify run that produced it — nothing is inferred, modelled or filled in, and a field absent from the source is absent from the row. The extracted archive for this source is browsable at reapx.dev/data/openfda-scraper/ and mirrored as an open dataset on Hugging Face and Kaggle. Questions: reapxdev@proton.me
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
- Pick a dataset. Leave everything else empty and you get the newest records.
- Narrow by product or brand name, company, recall class, status, state or a date window.
- For anything the plain-language filters do not cover, use the raw openFDA query field.
- Set Max records. You are charged once per record returned, so that is your cost cap.
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.
Input configuration
Every field is optional. The prefilled values below are what runs if you press Start without changing anything.
What to read
Leave every filter below empty and the run returns the newest records in the chosen dataset.
| Field | Type | Accepts | What it does |
|---|---|---|---|
dataset | string | one of 8: drug-recalls, drug-adverse-events, drug-labels, drug-ndc-directory, ... | Which openFDA endpoint to read. Each one returns a different kind of record, all keyed by their own FDA identifier. Prefilled with "drug-recalls". |
searchTerm | string | free text | Matches the product, brand or device name fields of the chosen dataset. |
firmName | string | free text | Recalling firm, labeler, applicant or manufacturer, depending on the dataset. |
How much to fetch
Volume and ordering. You pay per record returned, so this decides the price of the run.
| Field | Type | Accepts | What it does |
|---|---|---|---|
maxRecords | integer | 1 to 25000 | 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. Prefilled with 100. |
sortBy | string | newest, oldest, none | Ordering on the dataset's main date field. Prefilled with "newest". |
Dates
All dates are YYYY-MM-DD and apply to whichever date field the chosen dataset uses.
| Field | Type | Accepts | What it does |
|---|---|---|---|
lastNDays | integer | 1 to 20000 | 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 | string | free text | Earliest date, YYYY-MM-DD. |
dateTo | string | free text | Latest date, YYYY-MM-DD. |
Recall filters
These apply to the recall and enforcement datasets.
| Field | Type | Accepts | What it does |
|---|---|---|---|
classification | string | Class I, Class II, Class III | Class I is the most serious (reasonable probability of serious harm), Class III the least. Applies to drug and food recalls. |
recallStatus | string | one of 5: Ongoing, Completed, Terminated, Pending, ... | Where the recall stands today. Drug and food recalls use Ongoing/Completed/Terminated; device recalls use Open, Classified/Terminated/Completed. |
state | string | free text | Two-letter state code of the recalling firm or applicant. |
country | string | free text | Country of the recalling firm or applicant. |
Adverse event filters
These apply to the drug adverse event dataset.
| Field | Type | Accepts | What it does |
|---|---|---|---|
seriousOnly | true/false | checkbox | Keep only adverse event reports FDA flagged as serious. Applies to drug adverse events. |
deathsOnly | true/false | checkbox | Keep only adverse event reports where death was an outcome. |
reaction | string | free text | MedDRA reaction term as FDA records it, in capitals, e.g. HEADACHE, NAUSEA, ANAPHYLACTIC REACTION. |
Advanced
Escape hatches for anything the plain-language filters above do not cover.
| Field | Type | Accepts | What it does |
|---|---|---|---|
searchQuery | string | free text | 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 | string | free text | 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. |
Pricing
Pay per event. The primary event is Record returned (record-returned), charged at $0.002 per event on the free plan, falling to $0.0008 on the highest tier.
Charged once per complete openFDA record written to the default dataset. A rate-limited or unreachable API, a rejected query and a search that matches nothing are never charged.
Minimum charge cap per run: $0.002.
Tiered discounts apply automatically on every paid Apify plan. Platform usage is absorbed by the Actor, so the per-event price is the whole price.
Usage examples
The prefilled run, which is what Start does with nothing changed
{"dataset": "drug-recalls","maxRecords": 100,"sortBy": "newest"}
Filter by product or brand name
{"dataset": "drug-recalls","maxRecords": 100,"sortBy": "newest","searchTerm": "insulin"}
Filter by company or firm
{"dataset": "drug-recalls","maxRecords": 100,"sortBy": "newest","firmName": "Medtronic"}
Filter by in the last n days
{"dataset": "drug-recalls","maxRecords": 100,"sortBy": "newest","lastNDays": 90}
Filter by from date
{"dataset": "drug-recalls","maxRecords": 100,"sortBy": "newest","dateFrom": "2026-01-01"}
Output example
One row, exactly as the actor wrote it to the dataset:
{"recordId": "65585-361","recordType": "drug-ndc","endpoint": "drug/ndc","primaryDate": "2026-07-31","scrapedAt": "2026-08-03T01:57:36Z","brandName": "WhiskCare 373","genericName": "Alcohol","labelerName": "Whisk Products, Inc.","dosageForm": "SOLUTION","routes": ["TOPICAL"],"marketingCategory": "OTC MONOGRAPH DRUG","productType": "HUMAN OTC DRUG","applicationNumber": "505G(a)(3)","activeIngredients": ["ALCOHOL 700 mL/L"],"listingExpirationDate": "2027-12-31","packageCount": 7}
Fields on every row
| Field | Type | What it is |
|---|---|---|
activeIngredient | string | Active ingredient text from the label. Present on: drug-labels. |
activeIngredients | list | Active ingredients with their strengths. Present on: drug-ndc-directory. |
adverseEventFlag | string | Whether the report was flagged as an adverse event. Present on: device-adverse-events. |
advisoryCommittee | string | FDA advisory committee that reviews this device area. Present on: device-510k-clearances. |
applicant | string | Company that submitted the 510(k). Present on: device-510k-clearances. |
applicationNumber | string | FDA application number, e.g. an NDA or ANDA. Present on: drug-ndc-directory. |
brandName | string | Marketed brand name of the drug product. Present on: drug-ndc-directory. |
brandNames | list | Brand names FDA associates with the product. Present on: drug-labels, drug-recalls. |
cfresId | string | Internal FDA device recall record ID. Present on: device-recalls. |
city | string | City of the firm on record. Present on: device-510k-clearances, device-recalls, drug-recalls, food-recalls. |
classification | string | FDA seriousness class. Class I means a reasonable probability of serious harm. Present on: drug-recalls, food-recalls. |
clearanceType | string | Type of 510(k) submission. Present on: device-510k-clearances. |
companyNumber | string | Reporting company case number. Present on: drug-adverse-events. |
country | string | Country of the firm on record. Present on: device-510k-clearances, drug-recalls, food-recalls. |
dateOfEvent | string | Date the device event occurred, YYYY-MM-DD. Present on: device-adverse-events. |
datePosted | string | Date the device recall was posted, YYYY-MM-DD. Present on: device-recalls. |
dateReceived | string | Date FDA received the submission, YYYY-MM-DD. Present on: device-510k-clearances. |
deaSchedule | string | Controlled substance schedule, when the drug is scheduled. Present on: drug-ndc-directory. |
decisionCode | string | Short FDA code for the decision. Present on: device-510k-clearances. |
decisionDescription | string | FDA decision on the submission. Present on: device-510k-clearances. |
deviceBrandNames | list | Brand names of the devices in the report. Present on: device-adverse-events. |
deviceCount | integer | How many devices this report covers. Present on: device-adverse-events. |
deviceGenericNames | list | Generic names of the devices in the report. Present on: device-adverse-events. |
deviceName | string | Trade name of the cleared device. Present on: device-510k-clearances. |
distributionPattern | string | Where the product was distributed. Present on: device-recalls, drug-recalls, food-recalls. |
documentId | string | Version-specific SPL document ID. The set ID in recordId is stable across versions. Present on: drug-labels. |
dosageAndAdministration | string | Dosing instructions from the label. Present on: drug-labels. |
dosageForm | string | Physical form of the product, e.g. TABLET. Present on: drug-ndc-directory. |
drugCount | integer | How many drugs this report lists. Present on: drug-adverse-events. |
endpoint | string | The api.fda.gov endpoint the row came from. |
eventId | string | FDA enforcement event ID grouping related recall records. Present on: drug-recalls, food-recalls. |
eventType | string | Nature of the device event, e.g. Malfunction or Injury. Present on: device-adverse-events. |
genericName | string | Generic name of the drug product. Present on: drug-ndc-directory. |
genericNames | list | Generic drug names FDA associates with the product. Present on: drug-labels, drug-recalls. |
indicationsAndUsage | string | What the product is approved to treat, from the label. Present on: drug-labels. |
initialFirmNotification | string | How the firm first told its customers. Present on: drug-recalls, food-recalls. |
kNumbers | list | 510(k) clearance numbers linked to the recalled device. Present on: device-recalls. |
labelVersion | string | Version number of this SPL label. Present on: drug-labels. |
labelerName | string | Company that labels and markets the product. Present on: drug-ndc-directory. |
listingExpirationDate | string | Date the NDC listing expires, YYYY-MM-DD. Present on: drug-ndc-directory. |
manufacturerNames | list | Manufacturer names on the record. Present on: device-adverse-events, drug-labels. |
marketingCategory | string | Regulatory pathway under which the product is marketed. Present on: drug-ndc-directory. |
medicinalProducts | list | Drug products named in the report. Present on: drug-adverse-events. |
occurCountry | string | Country where the event occurred. Present on: drug-adverse-events. |
packageCount | integer | How many package configurations this NDC has. Present on: drug-ndc-directory. |
patientOnsetAge | string | Patient age when the reaction began, as reported. Present on: drug-adverse-events. |
patientSex | string | Patient sex as reported. Present on: drug-adverse-events. |
pharmClasses | list | Established pharmacologic class terms. Present on: drug-ndc-directory. |
primaryDate | string | The dataset’s main date, normalised to YYYY-MM-DD: recall initiation, report received, decision date or marketing start. |
productCode | string | FDA three-letter device product code. Present on: device-510k-clearances, device-recalls. |
productCodes | list | FDA device product codes in the report. Present on: device-adverse-events. |
productDescription | string | Full description of the recalled or reported product as the firm filed it. Present on: device-recalls, drug-recalls, food-recalls. |
productNdcs | list | National Drug Codes covered by this label. Present on: drug-labels. |
productQuantity | string | How much product is covered by the recall, as filed. Present on: device-recalls, drug-recalls, food-recalls. |
productType | string | Broad FDA product category. Present on: drug-ndc-directory, drug-recalls, food-recalls. |
purpose | string | Purpose section of the label. Present on: drug-labels. |
reactionCount | integer | How many distinct reactions this report lists. Present on: drug-adverse-events. |
reactions | list | MedDRA reaction terms reported. Present on: drug-adverse-events. |
reasonForRecall | string | Why the product was recalled, in the firm’s own words. Present on: device-recalls, drug-recalls, food-recalls. |
recallAction | string | What the firm is doing about the recalled device. Present on: device-recalls. |
recallStatus | string | Where the recall stands today. Present on: device-recalls, drug-recalls, food-recalls. |
recallingFirm | string | Company that initiated or was ordered to conduct the recall. Present on: device-recalls, drug-recalls, food-recalls. |
receiptDate | string | Date FDA most recently received information, YYYY-MM-DD. Present on: drug-adverse-events. |
recordId | string | The FDA identifier for this record - recall number, NDC, 510(k) number, safety report ID or SPL set ID depending on the dataset. Stable, unique, and how the row is addressed downstream. |
recordType | string | Which kind of FDA record this row is. |
reportDate | string | Date FDA published the enforcement report, YYYY-MM-DD. Present on: drug-recalls, food-recalls. |
reportSource | string | Who submitted the report. Present on: device-adverse-events. |
reviewDays | integer | Days between FDA receiving the 510(k) and deciding it. Present on: device-510k-clearances. |
routes | list | Routes of administration. Present on: drug-labels, drug-ndc-directory. |
scrapedAt | string | UTC ISO 8601 timestamp of this run. |
serious | true/false | FDA flagged the report as serious. Present on: drug-adverse-events. |
seriousnessDeath | true/false | Death was an outcome of this report. Present on: drug-adverse-events. |
seriousnessHospitalization | true/false | Hospitalisation was an outcome of this report. Present on: drug-adverse-events. |
seriousnessLifeThreatening | true/false | The event was life threatening. Present on: drug-adverse-events. |
state | string | Two-letter US state code of the firm on record. Present on: device-510k-clearances, device-recalls, drug-recalls, food-recalls. |
substanceNames | list | UNII substance names on the label. Present on: drug-labels. |
terminationDate | string | Date FDA terminated the recall, YYYY-MM-DD. Present on: food-recalls. |
voluntaryMandated | string | Whether the firm initiated the recall or FDA required it. Present on: drug-recalls, food-recalls. |
warnings | string | Warnings section of the product label. Present on: drug-labels. |
5 named dataset views ship with it: Records, Recalls, Adverse events, Products & labels, 510(k) clearances. They drive the Output tab in Console and the Output block on the Actor's .md page.
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.
The full published archive
- openfda scraper archive — every entity this Actor has observed
- All reapx datasets — 20 sources, tens of thousands of pages
- llms.txt · feed.json · feed.xml — the machine-readable index, for agents
Each archive page carries Dataset JSON-LD, a canonical URL and the identifiers used, so an agent can resolve an entity without running anything. Nothing on those pages is estimated or modelled.
🧪 Example input
A real, runnable configuration — this is an actual input this Actor has run with.
{"dataset": "drug-ndc-directory","lastNDays": 365,"maxRecords": 500}
📄 Sample output
One real row from a real run of this Actor, unedited.
{"recordId": "65585-361","recordType": "drug-ndc","endpoint": "drug/ndc","primaryDate": "2026-07-31","scrapedAt": "2026-08-03T01:57:36Z","brandName": "WhiskCare 373","genericName": "Alcohol","labelerName": "Whisk Products, Inc.","dosageForm": "SOLUTION","routes": ["TOPICAL"],"marketingCategory": "OTC MONOGRAPH DRUG","productType": "HUMAN OTC DRUG","applicationNumber": "505G(a)(3)","activeIngredients": ["ALCOHOL 700 mL/L"],"listingExpirationDate": "2027-12-31","packageCount": 7}
How it works
- You set the filters below, or none at all.
- The Actor calls the source's own public endpoint and pages through the results.
- Every row is pushed to the dataset as it is built, not buffered to the end — so a run that hits its time limit still returns everything it collected up to that point.
- You are charged per row returned, so the maximum-results field is also your cost cap.
💬 Your feedback
Found a bug, or need a field this does not return yet? Open an issue on the Actor's Issues tab, or write to reapxdev@proton.me. Bugs get fixed and reasonable field requests get added.