If you need FDA recall data — which drugs, devices and foods got pulled, why, by whom, and how serious it was — you do not need to scrape fda.gov, and you do not need a paid API. The FDA runs openFDA, a free, keyless JSON API over its own enforcement, adverse-event and labeling databases.
No sign-up. No API key. No token. There's a higher rate limit if you register a free key, but every endpoint below works with nothing at all.
The base
https://api.fda.gov
Recalls live under the enforcement endpoints, one per product area:
curl "https://api.fda.gov/drug/enforcement.json?limit=1"
curl "https://api.fda.gov/device/enforcement.json?limit=1"
curl "https://api.fda.gov/food/enforcement.json?limit=1"
Each response has a meta block (with results.total) and a results array. A single drug-recall record carries recalling_firm, product_description, reason_for_recall, classification (Class I / II / III — I is the most serious), status (Ongoing / Completed / Terminated), recall_initiation_date, distribution_pattern, code_info, plus an openfda block that links the product back to NDC codes and brand/generic names.
Search with the search parameter
openFDA uses a simple field:value query syntax. Quote multi-word values and URL-encode:
# All Class I (most serious) drug recalls
curl 'https://api.fda.gov/drug/enforcement.json?search=classification:"Class+I"&limit=5'
# Recalls that are still Ongoing
curl 'https://api.fda.gov/drug/enforcement.json?search=status:"Ongoing"'
# Ranges and booleans work too — food recalls initiated in 2026
curl 'https://api.fda.gov/food/enforcement.json?search=recall_initiation_date:[20260101+TO+20261231]'
At the time of writing there are 1,733 Class I drug recalls on record and 2,580 with an Ongoing status — all as structured JSON, no scraping.
Count instead of list
Add count=<field>.exact and openFDA returns an aggregation instead of raw rows — great for dashboards:
curl "https://api.fda.gov/drug/enforcement.json?count=classification.exact"
Right now that returns Class II = 14,381, Class I = 1,733, Class III = 1,701. One call, the whole distribution.
Page through everything
curl "https://api.fda.gov/device/enforcement.json?limit=100&skip=200"
limit (max 1000) and skip page the results. The device enforcement set alone is 39,539 records; food is 29,238.
Beyond recalls
Same base, same keyless deal, for two more datasets people usually ask about in the same breath:
# Adverse event reports (FAERS)
curl "https://api.fda.gov/drug/event.json?limit=1"
# Structured drug product labeling
curl "https://api.fda.gov/drug/label.json?limit=1"
The only two rules
- Be reasonable with volume — anonymous calls are rate-limited (a registered free key just raises the ceiling).
- Page with
limit+skip, and remember openFDA data is a snapshot the FDA refreshes periodically, not a live wire.
That's the whole thing.
If you'd rather skip the paging, the search encoding and the field-mapping, the FDA Recalls Scraper on Apify wraps exactly these endpoints — drug/device/food, class and status filters in, structured rows out.
📌 Full endpoint cheatsheet (copy-paste reference): github.com/noble-ronin/fda-recalls-api


Top comments (0)