FDA logo

Open data · Coming soon

FDA Recalls Export and Monitor

Get FDA recalls for food, drugs and medical devices in one table. Filter by class, firm, product, reason and state. Mark which recalls are new or changed since last time.

Built and tested. Prices will be shown after release.

Coming soon to the Apify StoreFollow us on Apify

What you get, for example

recallKeyfood:H-1395-2026
recallNumberH-1395-2026
eventId99874

How it will work: 3 steps

  1. Follow us on ApifyThe tool is built and waits in the queue for the Apify Store. Apify is the cloud platform where our tools run.
  2. Paste your input and press StartNo code needed: you fill in a form (the input). It already has a working example. For example: food in Product categories. Each start is one run.
  3. Download the resultsWhen the run ends, the results are in a table (the dataset). Open Output, press Export and pick Excel or CSV. JSON and the API are there too.

This tool is an Apify Actor: a small program that runs on Apify. You can also run it on a schedule, for example every Monday. New to it? Read how it works, step by step and the 8 words you need first.

What it does

FDA Recalls & Enforcement Monitor searches FDA recalls of food, drugs and medical devices in the official FDA Enforcement Reports, through the openFDA API. Filter by recall class, status, dates, firm, product, reason and firm state. You get one clean row per recalled product, with the four FDA dates kept apart, the recall number, the firm, the reason and a link to the record in openFDA.

  • One request per category. Each category you pick is one search, newest records first. maxResults applies to each category.
  • Four dates, never mixed. recallInitiationDate (the firm started the recall), centerClassificationDate (FDA set the class), reportDate (FDA published it in the Enforcement Report) and terminationDate (FDA closed it). You choose which date your range uses.
  • Not yet classified recalls. The newest recalls appear before FDA gives them a class and a recall number. You can include or skip them. They get a stable recallKey anyway.
  • Monitoring. With a monitorKey, the Actor saves the recalls it saw in your account. The next run marks each recall new, updated (for example the status changed to Terminated) or unchanged, and by default writes only new and updated ones.

Good for

  • Get a weekly list of new Class I food recalls for your quality or safety team.
  • Check if a supplier, brand or competitor had FDA recalls, by firm name.
  • Find recalls by reason: Listeria, undeclared peanut, sterility, mislabeling.
  • Watch medical device or drug recalls of one firm state, such as CA or NJ.
  • Feed FDA recall rows into a spreadsheet, a dashboard or an AI agent.

Not a good fit

  • Official consumer alerts or a guarantee that you see every recall in time. FDA publishes Enforcement Reports weekly, and a recall can appear later than the firm's press release.
  • Full recall lifecycle tracking. The Actor sees only what the Enforcement Report says on the day of the run.
  • Cosmetics or tobacco as separate categories, animal food recall press releases, and device recall details from the separate device recall database.
  • A full copy of all FDA recalls since 2004. Use the openFDA downloads for that.

Who uses it

Food safety and QA teams

Get a weekly list of new Class I food recalls.

Buyers and supplier managers

Check if a supplier had recalls.

Health researchers

Study recall reasons, like allergens or germs.

Price

Prices will be shown after release.

Questions

Where does the recall data come from?

From openFDA, the official open data API of the US FDA. The records are FDA Enforcement Reports.

What do Class I, II and III mean?

Class I is the most serious risk. Class II is a temporary or reversible risk. Class III is unlikely to cause health problems.

Do I need an openFDA API key?

No. A free key is optional. It only gives you your own request limit.

Is this medical advice?

No. It is FDA data as published. Ask FDA, the firm or your doctor about a product you use.

How fresh is the data?

Each run reads openFDA live. openFDA updates the enforcement data about once a week, after FDA publishes the Enforcement Report. Firm press releases can come earlier.

Does monitoring cost more?

No. Unchanged recalls are not written and not charged when onlyChanges is on.

Why are there no device codes like GMDN?

GMDN terms have their own licence, so the Actor does not output openFDA device classification data. If a firm wrote a code into its own codeInfo text, it stays as FDA published it.

Details

Step by step on Apify
  1. Open the Input tab. The form already has an example: food, Class I, last 30 days, 20 recalls.
  2. Click Start.
  3. Open the Recalls view in the Output tab. Check recallNumber, recallingFirm, productDescription, reasonForRecall and reportDate.
  4. Change the categories, classes or filters to your own. To get only changes next time, add a monitorKey such as food-class-1.
Use cases
TaskInputYou getKey fields
Weekly food safety watchcategories: ["food"], classifications: ["I"], monitorKey, on a scheduleonly new and updated Class I recallschangeType, reasonForRecall, distributionPattern
Supplier checkfirmNames, all categories, a 90-day rangethat firm's recallsrecallingFirm, productDescription, status
Allergen or pathogen researchreasonQuery: "Listeria" or "undeclared peanut"matching recallsreasonForRecall, codeInfo, productQuantity
Medical device recall searchcategories: ["device"], productQuery, firmStatesdevice recall rowsrecallNumber, classification, centerClassificationDate
Drug recall list with NDCscategories: ["drug"]drug rowsdrugBrandNames, drugGenericNames, drugProductNdcs
Closed recallsdateField: "termination_date"recalls FDA terminated in the rangeterminationDate, status
Tips for better results
  • Pick which date your range uses. FDA keeps four different dates per recall.
  • Use a monitor key to get only new and updated recalls each week.
  • openFDA updates about once a week, so a weekly run is often enough.
Limits and good to know
  • Up to 1,000 recalls per category and 3 categories, so up to 3,000 rows per run. In our test, 2,541 rows took about 4 seconds
  • The date range is at most 90 days. Enforcement Reports start in 2004
  • Without a key, openFDA limits requests per IP address per day, and the IP can be shared with other users. Each category is one request. If openFDA refuses with a rate limit, the run stops with ERROR and a hint. Add your free openFdaApiKey to get your own quota
  • If openFDA does not answer (up to 30 seconds per try, at most 3 tries and 2 timeouts), the run stops early and does not ask for the other categories. You get the rows found so far. The internal time budget is 240 seconds
  • Monitor snapshots keep up to 20,000 recalls per monitorKey. previousDatasetId reads up to 20,000 rows
  • Not yet classified recalls have no recall number. When FDA classifies them, they come back with a recall number as a new row with a new recallKey
  • firmStates is the firm's address, not where the product was sold
  • openFDA updates the enforcement data about once a week. sourceUpdatedAt shows the last update

Troubleshooting

SymptomCheckAction
NO_RESULTSRUN_SUMMARY.filtersWiden the dates, remove a class or a filter, or try another dateField.
ERROR with a rate limit messageRUN_SUMMARY.messageAdd your free openFdaApiKey, or run again later.
ERROR, openFDA unavailableRUN_SUMMARY.messageRun again later. A failed run does not remove recalls from your monitor snapshot; it only adds the rows it reported.
INVALID_INPUTRUN_SUMMARY.messageFix the field named in the message. The range is at most 90 days.
truncated: truecategories[].matchedAtSourceRaise maxResults (up to 1,000) or narrow the filters or dates.
A recent recall is missingsourceUpdatedAt, reportDateFDA adds recalls to the weekly report after classification. Try dateField: "recall_initiation_date" and include unclassified.
Warning about different filtersRUN_SUMMARY.warningsYou changed filters but kept the same monitorKey. Use one key per saved search.

For developers

Sample result

One result from a real test run, in JSON. Real values change from run to run. In Excel or CSV each field is a column.

one result · JSON
{
  "recallKey": "food:H-1395-2026",
  "recallNumber": "H-1395-2026",
  "eventId": "99874",
  "category": "food",
  "classification": "Class I",
  "recallClass": "I",
  "status": "Ongoing",
  "recallingFirm": "WFM Purchasing, LP",
  "productDescription": "Fromagerie Coop de Mean Cabricharme and Belgium Cabricharme ...",
  "productQuantity": "21 Wheels",
  "reasonForRecall": "Undeclared Egg Allergen",
  "distributionPattern": "CA, AZ, NJ, MA, RI, CT, NY",
  "recallInitiationDate": "2026-09-08",
  "centerClassificationDate": "2026-09-22",
  "reportDate": "2026-09-30",
  "terminationDate": null,
  "city": "Austin",
  "state": "TX",
  "changeType": null,
  "sourceUrl": "https://api.fda.gov/food/enforcement.json?search=recall_number%3A%22H-1395-2026%22",
  "provider": "openFDA (U.S. Food and Drug Administration)",
  "sourceUpdatedAt": "2026-09-30",
  "fetchedAt": "2026-10-12T10:54:50.382Z"
}
Data fields (37)
FieldTypeMeaning
changeTypestringChange since the baseline: initial (first monitored run), new, updated or unchanged. null when no monitorKey/previousDatasetId is used.
changedFieldsarrayFor updated recalls: which tracked fields changed (status, classification, terminationDate, the other dates, firm, product, quantity, code info, reason, distribution, voluntaryMandated).
previousValuesobjectFor updated recalls: previous value of each changed field.
recallKeystringStable key: category:recallNumber, e.g. food:F-0123-2026; for not-yet-classified recalls category:unclassified:eventId:hash. Use it to deduplicate and join.
recallNumberstringFDA recall number, e.g. F-0123-2026 (food), D-0860-2026 (drug), Z-3247-2026 (device). null while FDA has not classified the recall yet.
eventIdstringFDA recall event ID. One event (one firm action) can cover several products, each with its own recall number.
categorystringopenFDA enforcement category searched: food, drug or device.
productTypestringProduct type as reported by FDA, e.g. Food/Cosmetics, Drugs, Devices.
classificationstringFDA classification text: Class I, Class II, Class III or Not Yet Classified.
recallClassstringShort class: I, II or III; null when not yet classified.
statusstringRecall status: Ongoing, Completed or Terminated.
recallingFirmstringFirm that initiated the recall.
productDescriptionstringProduct as described in the enforcement report.
productQuantitystringQuantity of product recalled, as free text.
codeInfostringLot numbers, codes, expiry dates identifying the recalled units.
moreCodeInfostringContinuation of codeInfo when FDA splits it.
reasonForRecallstringReason for the recall, as written by FDA.
distributionPatternstringWhere the product was distributed, as free text (states, countries, nationwide).
voluntaryMandatedstringVoluntary: Firm initiated, or FDA Mandated. null when FDA reports N/A or nothing.
initialFirmNotificationstringHow the firm first notified consignees, e.g. Letter, E-Mail, Press Release.
recallInitiationDatestringDate the firm started the recall (YYYY-MM-DD, calendar date without time zone).
centerClassificationDatestringDate the FDA center classified the recall (YYYY-MM-DD).
reportDatestringDate FDA published the recall in its weekly Enforcement Report (YYYY-MM-DD).
terminationDatestringDate FDA terminated the recall (YYYY-MM-DD); null while it is not terminated.
address1stringRecalling firm address line 1.
address2stringRecalling firm address line 2.
citystringRecalling firm city.
statestringRecalling firm state (2-letter code for US firms).
postalCodestringRecalling firm postal code.
countrystringRecalling firm country.
drugBrandNamesarrayDrug recalls only: brand names linked by openFDA. null for food and device rows.
drugGenericNamesarrayDrug recalls only: generic names linked by openFDA.
drugProductNdcsarrayDrug recalls only: product NDC codes linked by openFDA.
sourceUrlstringopenFDA API query returning this recall (by recall number; by event ID while not yet classified).
providerstringData provider: openFDA (U.S. Food and Drug Administration).
sourceUpdatedAtstringopenFDA dataset last_updated date at fetch time (YYYY-MM-DD).
fetchedAtstringWhen this run fetched the record (ISO 8601 UTC).
Input settings (16)

The main fields of the input form. With the API you send them as JSON.

SettingName in the APITypeExample value
Product categoriescategoriesarray["food"]
Recall classclassificationsarray["I"]
Recall statusstatusesarray["Ongoing", "Completed", "Terminated"]
Look back (days)lookbackDaysinteger30
Date the range applies todateFieldstring"report_date"
Date fromdateFromstring
Date todateTostring
Recalling firm namesfirmNamesarray
Product containsproductQuerystring
Reason containsreasonQuerystring
Firm statesfirmStatesarray
Max recalls per categorymaxResultsinteger20
Monitor key (for scheduled runs)monitorKeystring
Compare with datasetpreviousDatasetIdstring
Only write new and updated recallsonlyChangesbooleantrue
openFDA API key (optional)openFdaApiKeystring

Start on Apify

Make a free Apify account: you get $5 of free usage every month. Missing a tool? Suggest it. We read every idea, but we do not promise to build it.

Apify links on this page are affiliate links. We may earn a commission. You pay the same price. Affiliate disclosure