FDA Recalls Scraper (openFDA) — Food, Drug & Device avatar

FDA Recalls Scraper (openFDA) — Food, Drug & Device

Pricing

from $1.60 / 1,000 recalls

Go to Apify Store
FDA Recalls Scraper (openFDA) — Food, Drug & Device

FDA Recalls Scraper (openFDA) — Food, Drug & Device

US FDA recalls from the official openFDA enforcement reports: food, drugs and medical devices with firm, classification, reason, quantity, distribution, dates and status. Filter by keyword, firm, class, state and date, and flag recalls new or changed since your last run.

Pricing

from $1.60 / 1,000 recalls

Rating

0.0

(0)

Developer

Northbell

Northbell

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

5 days ago

Last modified

Share

FDA Recalls Scraper (openFDA) — Food, Drug & Device Recalls

Search US recalls in the FDA enforcement reports (via the official openFDA API) by keyword, recalling firm, classification, status, the firm's state or country and report date, for food, drugs and medical devices, and get one clean row per recall: recall number, event id, product type, class, status, recalling firm and its city / state / country, product description, reason for the recall, quantity, distribution, lot / code info, the recall, classification and termination dates, voluntary or mandated, how the firm was notified, with a link to the record in openFDA. $2.00 per 1,000 recalls, no login, no API key needed.

Run it again — or put it on a daily schedule — and every row also tells you whether the recall is new since the last run (isNew) and whether its status changed, for example Ongoing to Terminated (statusChanged). Set What to return to New or changed and you pay only for those.

Looking for vehicle recalls? See the NHTSA Vehicle Recalls Actor.

Data provided by the U.S. Food and Drug Administration (https://open.fda.gov). This Actor is not an FDA product and is not endorsed by the FDA. Do not use it for decisions about medical care. See Notes.

What you get

FieldWhat it is
recallNumber, eventIdthe FDA recall number (F-0276-2017, D-0879-2026, Z-0004-2027; F or H = food, D = drug, Z = device) and the id of the recall event it belongs to (one event can have many recalls)
productTypefood, drug or device
classificationClass I, Class II or Class III, the FDA's hazard level
statusOngoing, Completed or Terminated as openFDA lists it (Pending is a documented value; no record had it on 16 Oct 2026)
recallingFirm, city, state, countrythe company that recalled the product and where it is located. state is null when openFDA has none or writes N/A (in the newest 3,000 records, 80 of the 82 food, all 312 drug and all 493 device records from firms outside the US had none). Street address and postal code are not returned
productDescription, reasonForRecallthe product and why it was recalled, as the firm and FDA wrote it
productQuantity, distributionPatternhow much was recalled (free text: 1,990 bottles) and where it went (FL, MI, MS, and OH., Nationwide)
codeInfo, codeInfoTruncatedlot / serial numbers and dates on the product, cut at 1,000 characters (codeInfoTruncated says so; of the newest 3,000 records, 685 device, 44 drug and 18 food ones had longer code info)
recallInitiationDate, centerClassificationDate, reportDate, terminationDatewhen the recall started, when the FDA classified it, the date of the enforcement report it appeared in, and when it was terminated (null while it is open), as YYYY-MM-DD
voluntaryMandated, initialFirmNotificationwho started the recall (Voluntary: Firm initiated, FDA Mandated) and how the firm told its customers (Letter, E-Mail …)
urlthe recall's record in the openFDA API (JSON)
isNew, statusChanged, previousStatus, previousRunAttrue / false whether the recall was not in your previous run of the same search, whether its status differs from that run, the status it had then, and when that run was (null the first time)
observedAtwhen the row was collected

Run it again and again

  • On a schedule — save your input as a task and add a Schedule: the same search every week. openFDA is updated weekly. Send each run to Google Sheets, Slack or email with an integration on the task.
  • Watch for changes — Set What to return to New or changed; a recall is new the first time your search returns it, and changed when its status is not the one the previous run saw.
  • In bulk — Put several keywords, firms or classes in one run; a recall that matches any of the values in a field is returned once.

Use it for

  • Supplier and product monitoring — a weekly run with your suppliers' names or your ingredients as keywords, New or changed, sent to Slack or email
  • Compliance and quality teams — Class I recalls in your product area, with reason, quantity and distribution
  • Market research — which firms recall most, in which class and for what reasons
  • Insurance and legal research — a firm's recall history with dates and status

Input

{
"productTypes": ["food", "drug"],
"keywords": ["listeria", "undeclared milk"],
"recallingFirms": [],
"classifications": ["Class I"],
"statuses": [],
"states": [],
"countries": [],
"reportedWithinDays": 90,
"output": "new-or-changed",
"maxResults": 200
}
  • productTypes — food, drug, device. Read in the order you list them, newest report date first within each. Empty means all three.
  • keywords — words or phrases looked for in productDescription and reasonForRecall; a recall matching any keyword is returned.
  • recallingFirms — company names; a name matches whole words in the firm's name, not case sensitive (Stryker finds Stryker Corporation).
  • classifications, statuses — pick any. A search for Ongoing stops returning a recall once it is Terminated, so leave statuses empty if you want to see status changes.
  • states, countries — where the recalling firm is located (two-letter US state codes; country names as the FDA writes them). It is not where the product was sold; that is in distributionPattern.
  • reportDateSince (2026-01-01), reportedWithinDays — limit by the date of the enforcement report. If you give both, the later date is used. A date also makes New or changed runs much faster, see below.
  • maxResults — total rows (default 200, up to 100,000).
  • apiKey — optional, your own free openFDA key. See Rate limits.

Within a field the values are "any of", and the fields are combined with "and": the input above is (listeria or undeclared milk) and Class I.

"Is it new" is remembered per product type and per set of conditions (keywords, firms, classes, statuses, states, countries) in a named key-value store in your Apify account. The date, maximum recalls, what to return and the key can change between runs without losing the history. A product type you search for the first time has isNew: null on that run, and a search that found nothing at that time gets a baseline too, so its first recall later is isNew: true. With a Maximum recalls cap, only the recalls that were returned are remembered, and the older ones the cap left unread are not counted as new next time; only a recall reported after the newest one that run saw is new (so a capped run followed by New or changed never charges for old recalls). Up to 100,000 recall numbers are remembered per product type and search, oldest report dates dropped first.

Large result sets

openFDA lets a search read at most 25,000 records by paging (a skip above 25,000 is refused with HTTP 400, and one request returns at most 1,000). Food (29,485 records on 16 Oct 2026) and devices (40,249) are over that, drugs (18,010) are not. When a search needs more than that, the Actor splits the report-date range in two, newest half first, and keeps halving a half that still has more than 25,000 matches; each record is read once. A cap of up to 25,000 rows, or a narrower search, needs no split at all.

What to return = New or New or changed has to compare every matching recall with the last run, so it reads all of them, and for a broad search that is many requests: reading all 40,248 numbered device records took 45 requests and 106 seconds in a test on 16 Oct 2026 without a key (3 splits). Set Reported since (or within N days) to keep these runs short. A recall keeps its report date when its status changes (F-0276-2017 still has its 2016 report date), so a date filter only shows status changes for recalls inside the window.

Pricing

$2.00 per 1,000 recalls, plus $0.01 per run. Error rows (a search openFDA could not answer) are free. With New or New or changed, recalls you have already seen are skipped and not charged. The $0.01 run-start fee is the one charge every run pays, even one that returns nothing.

Rate limits

openFDA documents these limits (authentication page): without a key, 240 requests per minute and 1,000 requests per day per IP address; with a free key, 240 per minute and 120,000 per day per key. The Actor works without a key and waits 0.4 seconds between requests (about 150 per minute). A run of 200 rows is one request; every 1,000 rows more is one more. The limit without a key is per IP address, so if other runs use the same address the daily allowance is shared; if you see rate-limit errors, add your own free key as apiKey. The key is sent in an Authorization header, never in the URL, and is not logged or written to the dataset. If openFDA answers 429, 5xx or not at all the Actor waits and retries twice; if a rate limit persists it stops with a free error row and the run is marked failed when nothing at all could be read.

Notes

  • Source: the public openFDA enforcement report endpoints api.fda.gov/food/enforcement.json, /drug/enforcement.json and /device/enforcement.json, which serve data from the FDA's Recall Enterprise System. The openFDA terms of service and license put the data under a CC0 public-domain dedication (commercial use allowed without asking; credit is requested, not required). Suggested credit: Data provided by the U.S. Food and Drug Administration (https://open.fda.gov). The terms say the FDA may limit access to manage load and prevent abuse; the Actor stays under the documented limits.
  • openFDA's disclaimer, which comes with every answer: "Do not rely on openFDA to make decisions regarding medical care." The enforcement pages add that the data should not be used to issue alerts to the public or to track the lifecycle of a recall, and that the FDA does not update a recall's status after it has been classified. Use this Actor for research and monitoring, and check the recall on the FDA's own site before you act on a row.
  • About that last point: in the data there are recalls whose termination date is years after their report date (F-0276-2017 was reported 2016-11-02 and terminated 2024-09-23), so statuses are updated, at least in some cases. I did not measure how promptly or completely. statusChanged means openFDA's value differs from your last run, nothing more.
  • Data freshness: openFDA says it is updated weekly. On 16 Oct 2026 its answers said the data was last updated on 7 Oct 2026, and the newest report date was 2026-10-07 in all three endpoints. The Actor puts this date in the run summary (dataLastUpdated). The earliest report date I found in all three endpoints is 2012-06-20.
  • On 16 Oct 2026 the statuses were: food 27,958 Terminated, 1,079 Ongoing, 448 Completed; drugs 14,810, 2,764 and 436; devices 25,333, 14,291 and 625.
  • Records are one per product, not one per event: one eventId can have many recall numbers. The Actor returns one row per recall number. Recalls the FDA has not classified yet (Not Yet Classified: 2 food, 2 drug and 1 device record on 16 Oct 2026) have an empty recall number or N/A; they are skipped and counted in the run summary (skippedNoNumber), because they cannot be compared between runs.
  • Texts are the firm's and the FDA's wording. No contact fields, no street address and no postal code are returned, and e-mail addresses and North American phone numbers in the texts are removed (in the newest 3,000 records of each endpoint, 25 food and 26 drug records had one; none of the devices). Lot codes and part numbers that only look like a phone number or e-mail are kept. Free text can still contain a name the firm wrote there (I found a doctor's name in a device description), and a firm's own name can be a person's name; the Actor does not try to remove those.
  • state and country are the recalling firm's location. The Actor reads only the three enforcement endpoints, not the other openFDA datasets (some of which carry licensed third-party terms).

For AI agents

{"productTypes": ["food"], "keywords": ["listeria"], "classifications": ["Class I"], "reportedWithinDays": 365, "maxResults": 5} returns up to 5 rows, newest report date first, each with recallNumber, recallingFirm, classification, status, productDescription, reasonForRecall and reportDate. Rows have type: recall or error. Fields that do not apply to a recall are null, never missing. Schedule the same input weekly with "output": "new-or-changed" to get only the recalls that appeared or changed status since the previous run. For vehicle recalls use the NHTSA Vehicle Recalls Actor.

**Something broke or looks wrong?** Open an issue on this Actor's Issues tab and I'll look at it. **Found it useful?** A short review on the Store page helps other people find it.