FDA Food Recalls Scraper (openFDA Enforcement Data JSON)
Pricing
from $1.60 / 1,000 recall delivereds
FDA Food Recalls Scraper (openFDA Enforcement Data JSON)
Track official FDA food enforcement recalls from openFDA: recall number, event, report date, classification, status, product, reason, recalling firm, distribution and location. For recall monitoring, food-safety alerts and compliance research. Public CC0 data, clean JSON, pay per event.
Pricing
from $1.60 / 1,000 recall delivereds
Rating
0.0
(0)
Developer
Steadfetch
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
5 days ago
Last modified
Features
Share
This Actor returns official FDA food enforcement recall records from the openFDA food enforcement API: one validated JSON item per recall with recall number, event, report date, classification, status, product description, reason for recall, recalling firm, distribution pattern and firm location, for recall monitoring, supplier screening and compliance research.
Tested daily. Last verified: 2026-10-30
What it does
- Reads the keyless public endpoint at api.fda.gov and returns one dataset item per recall; no login, no CAPTCHA, no browser.
- Filters by report-date window (
since/until), FDA classification, two-letter US state code and a case-insensitive keyword matched against product description, reason for recall and recalling firm. - Monitor mode is on by default: recalls already delivered for the same classification/state/keyword stream are neither pushed nor charged. Set
monitorMode: falsefor a one-off backfill. - Validates every item against
.actor/dataset_schema.jsonbefore it reaches the dataset; incomplete source records lacking a required field are dropped, never filled with made-up values. - Returns company and product fields only: the raw record's street address and postal code are dropped, so no person-level data is emitted.
- Limits: food enforcement recalls only (not drug or device recalls); the
classificationfilter covers only the three final classes, and a recall published asNot Yet Classifiedis passed through unchanged instead of guessed.
How to use
- Run it from the terminal with the Apify CLI, using the same input as the Store example:
$apify call steadfetch/fda-recall-monitor --input='{"since":"2026-10-01","maxResults":10,"monitorMode":false,"strictSchema":true}'
- Or open the Run tab in the Apify console and set the filters: a date window, one of the three FDA classifications, a state code and/or a keyword.
- Leave
monitorModeenabled and schedule the run to receive only new recalls for the same filter stream; disable it to backfill history. - Read results from the default dataset or the Apify API.
Input
Input fields
| Field | Type | Required | Default/Prefill | Description | Example |
|---|---|---|---|---|---|
since | string (date) | No | Default: 30 days before until/today; prefill 2026-10-01 | Inclusive lower bound for the recall report date (YYYY-MM-DD). | 2026-09-01 |
until | string (date) | No | Default: today (UTC) | Inclusive upper bound for the recall report date (YYYY-MM-DD). | 2026-10-20 |
classification | string (select) | No | None | Only return recalls with this FDA classification. One of Class I, Class II, Class III. | Class I |
state | string (text) | No | None | Only return recalls whose recalling firm is in this two-letter US state code (pattern ^[A-Za-z]{2}$). | FL |
keyword | string (text) | No | None | Case-insensitive keyword matched against product description, reason for recall and recalling firm. | allergen |
maxResults | integer | No | Default 100; minimum 1; maximum 5,000; prefill 10 | Maximum number of recalls delivered to the dataset. | 10 |
monitorMode | boolean | No | Default true; prefill false | When enabled, recalls already delivered by a previous run with the same classification/state/keyword filters are not pushed or charged. Disable for a full backfill. | true |
strictSchema | boolean | No | Default true | Fail the run when an item does not match the output schema. Keep enabled: Steadfetch never delivers unvalidated data. | true |
No input field is required: with no filters the Actor queries the default 30-day window.
Example input
{"since": "2026-10-01","maxResults": 10,"monitorMode": false,"strictSchema": true}
Wider filtered backfill:
{"since": "2026-09-01","until": "2026-10-20","classification": "Class I","state": "FL","keyword": "allergen","maxResults": 100,"monitorMode": false}
Output
Example output
One record per recall, built from the published dataset schema examples:
{"recall_number": "H-1407-2026","event_id": "99887","report_date": "2026-10-07","classification": "Class I","status": "Ongoing","product_description": "Todd's Seeds Salad Sprouting Mixture, packaged in resealable bags","reason_for_recall": "Products may be contaminated with E. coli and/or Salmonella","recalling_firm": "TODD'S SEEDS LLC","distribution_pattern": "Nationwide; through Amazon or direct to consumer","product_quantity": "37,481 retail units (TOTAL)","voluntary_mandated": "Voluntary: Firm initiated","city": "Cookeville","state": "TN","country": "United States","source_url": "https://api.fda.gov/food/enforcement.json?search=recall_number:%22H-1407-2026%22","url": "https://api.fda.gov/food/enforcement.json?search=recall_number:%22H-1407-2026%22","scrapedAt": "2026-10-20T08:00:00.000Z"}
Missing optional values are null or omitted; nothing is invented to fill a gap.
Output fields
| Field | Type | Description |
|---|---|---|
recall_number | string | FDA recall number that identifies the enforcement record. |
event_id | string or null | openFDA event identifier shared by related recall records. |
report_date | string (date) | Date the recall was reported by FDA (YYYY-MM-DD). |
classification | string | FDA classification: Class I, Class II or Class III. |
status | string or null | Current enforcement status, e.g. Ongoing or Terminated. |
product_description | string | Description of the recalled food product. |
reason_for_recall | string or null | Reason stated by FDA for the recall. |
recalling_firm | string | Company that initiated the recall (organisation name only). |
distribution_pattern | string or null | Where the recalled product was distributed. |
product_quantity | string or null | Quantity of product covered by the recall, as published. |
voluntary_mandated | string or null | Whether the recall was voluntary or mandated. |
city | string or null | City of the recalling firm. |
state | string or null | Two-letter US state code of the recalling firm. |
country | string or null | Country of the recalling firm. |
source_url | string (URI) | Official openFDA API URL that pins this recall by recall number. |
url | string (URI) | Common Steadfetch envelope: same as source_url. |
scrapedAt | string (date-time) | Common Steadfetch envelope: ISO 8601 UTC timestamp of the run. |
Pricing
Pay-per-event pricing from .actor/pay_per_event.json, using the two synthetic platform events plus the reserved monitor-check event:
| Event | Charged when | Price |
|---|---|---|
apify-actor-start | a run starts | 0.00005 USD per run; includes the first 5 seconds of compute |
apify-default-dataset-item | a validated recall is saved to the dataset | 0.002 USD per recall = 2.00 USD per 1,000 results |
monitor-check | a watched record is checked in monitorMode | 0.001 USD per checked record = 1.00 USD per 1,000 checks |
Measured cost per 1,000 results: under 0.01 USD (local measurement 2026-10-20: one 1,000-result request, about 1.5 seconds and 7 ms of parsing at 256 MB, no browser or proxy), leaving a gross margin above 99%. The first paid platform run will replace this local measurement with the billed figure.
The platform bills the synthetic events automatically, and the Actor calls Actor.charge() once per monitor run for the reserved monitor-check event (monitor mode only). A check that finds no change still bills monitor-check but no result event. Items that fail schema validation are not pushed and are not billed as dataset items, and runs that return nothing cost only the automatic run-start event. Already-delivered recalls skipped by monitor mode are not pushed and never charged again.
Works on the Apify free plan - about 2,499 recalls for the $5 monthly credit ((5.00 USD - 0.0002 USD run-start at the default 4 GB memory) / 0.002 USD per recall).
Other Steadfetch Actors
- CPSC Recall Monitor - US consumer product recalls to pair with food recalls for a full recall-risk picture.
- EU Safety Gate Monitor - the EU-side alert feed for dangerous products, useful when you also track EU market recalls.
- UK Food Hygiene Monitor - hygiene ratings of UK food establishments, for screening suppliers on the other side of the Atlantic.
- Federal Register Monitor - the FDA rulemaking documents behind enforcement policy changes that affect your monitoring rules.
FAQ
Do I need an openFDA API key, browser or proxy? No. The food enforcement endpoint is keyless and public, returns structured JSON, and releases the data under CC0; the Actor sends plain HTTP requests to the official host.
When am I charged?
Once per run start (apify-actor-start) and once per validated recall saved to the dataset (apify-default-dataset-item). Failed requests, retries, empty runs, dropped invalid records and already-delivered recalls are not billed as results.
What happens when there are no matching recalls?
openFDA returns NOT_FOUND; the Actor treats it as an empty result, exits successfully and pushes nothing.
Does it return personal data? No. Only company and product-level fields are emitted; the raw record's street address and postal code are dropped.
Why does a run return fewer items than maxResults?
The filters may match fewer records, an incomplete source record may have been dropped, or monitor mode skipped recalls it already delivered. The Actor never invents values to fill a gap.
Support
Report bugs through the Issues tab of this Actor's Apify Store page or through the steadfetch actors repository issues. Include the run ID (visible in the Apify console on the run) and the exact input JSON you used, so the problem can be reproduced against the same filters.
Maintenance
Tested daily: daily catalog QA runs the default input; enabled on 2026-10-21. Schema and fixture tests (npm test) last verified locally on 2026-10-22. The source is the versioned official openFDA API; committed fixtures and schema tests catch response-shape changes in CI, and any break in the daily run is reported as an issue in the Steadfetch Actors repository.