FDA Recall Scraper
Pricing
from $0.70 / 1,000 recalls
FDA Recall Scraper
The FDA gives the recall reason only as free text, so nobody can query it. This classifies it into root causes — undeclared allergen, sterility failure, nitrosamine impurity, software defect, component recall — and scores firms that keep failing the same way. 89.4% classified over 900 live recalls.
FDA Recall Scraper — Root Cause Classified
Scrape every FDA drug, device and food recall from openFDA, with the one thing the FDA does not give you as a field: why the product was actually pulled.
The FDA records the reason as a paragraph of free text. Every other scraper hands that paragraph straight through, so you can filter by Class I but you cannot ask "show me every sterility failure this quarter" or "which firms keep shipping undeclared allergens" — which is the whole question a compliance, quality or supply-chain team is trying to answer.
What you get that a normal FDA scraper cannot give you
Root cause, classified. Seventeen categories derived from the reason text:
undeclared_allergen · microbial_contamination · sterility_failure ·
foreign_material · particulate_matter · nitrosamine_impurity ·
chemical_contamination · impurity_degradation · potency_variance ·
dissolution_stability · spoilage_degradation · cross_contamination ·
product_mixup · formulation_error · specification_failure ·
mislabeling · packaging_defect · software_defect · device_malfunction ·
cgmp_deviation · unapproved_product · adulteration · component_recall
Measured 2026-08-14 over 900 live recalls: 89.4% classified — drugs 100%,
food 98.0%, devices 70.3%. Devices are the weak case and honestly so: many
device narratives say only "Firm X issued a recall for specific items and lots"
and name no defect at all. Those stay unclassified rather than being guessed,
because a wrong category in a compliance dataset is worse than a gap.
component_recall is worth calling out. It marks a kit pulled because a
supplier's component was recalled, not because of the firm's own failure. If
you are mapping supply-chain exposure, that distinction is the point.
Repeat-offender scoring. Per firm: recall count, Class I share, distinct FDA
events, dominant root cause, and isRepeatSameCause — the firm failed the same
way at least twice. A firm that keeps failing identically has a systemic problem;
one that fails differently every time has bad luck.
Blast radius. distribution_pattern is also free text — "CA, WA, OR." or
"Nationwide and Canada". It is parsed into statesAffected, isNationwide and
isInternational. Severity is the first question; how far it went is the second,
and the FDA does not answer it as a field.
Quantity. product_quantity reads "2 cases (1 pc/bx, 48bx/cs)". The
leading count and unit are parsed out. The parenthetical breakdown describes
packing, not volume, so it is deliberately not multiplied out — that would
invent a number.
Time to close. daysToClassification and daysToTermination, computed from
the raw dates. Device enforcement records carry no termination date at all, so
that field is null for devices by design rather than by omission.
Who uses this
- Pharma, medtech and food quality teams — benchmarking their own recall profile against competitors.
- Supply chain and procurement — screening suppliers before onboarding, and catching downstream component recalls.
- Regulatory and compliance consultants — quantifying enforcement trends by cause rather than by class.
- Litigation and insurance analysts — finding firms with a repeated, documented failure mode.
Input
| Field | Type | Default | Notes |
|---|---|---|---|
productTypes | array | ["drug","device","food"] | Three independent endpoints |
classifications | array | [] | Class I = serious injury or death |
rootCauses | array | [] | Filter on the derived category — the FDA has no such field |
searchTerm | string | "" | Matched against reason and product description |
firm | string | "" | Restrict to one company |
state | string | "" | Two-letter state of the recalling firm |
status | string | "" | Ongoing recalls are still in the field |
fromDate / toDate | string | 2025-01-01 / "" | ISO dates, on the FDA report date |
maxRecordsPerType | integer | 200 | openFDA pages at 1000, offsets to 25,000 |
minRecallsForSummary | integer | 1 | Set to 2+ for firms with a pattern, not an incident |
apiKey | string | "" | Optional. Raises the shared 1,000/day/IP anonymous quota to 120,000 |
Root-cause filtering is applied after the firm rollup is computed, so summaries always describe the firm rather than the filter.
Output
recall — classification, isClassI, rootCause, reasonForRecall,
recallingFirm, productDescription, status, statesAffected,
isNationwide, quantity, daysToTermination, isFdaMandated, plus brand,
generic, NDC and device fields from the openFDA block.
firm_summary — recalls, classIRecalls, classISharePercent,
distinctEvents, topRootCause, rootCauseBreakdown, isRepeatSameCause,
ongoingRecalls, medianDaysToTermination, nationwideRecalls.
Reliability
- A query matching nothing returns HTTP 404, not an empty list. That is an empty result set, not a failure — treating it as an error would turn "nothing was recalled this week" into a failed run. Handled.
- One product type failing never fails the run.
- Firm names are escaped before they reach openFDA's Lucene syntax, so a quote in a company name cannot break the query.
Limits
- Only recalls the FDA has classified. Very recent recalls appear in FDA press releases before they appear here.
distinctEventsmatters: one FDA event often spans many recall numbers, so twenty rows can be one incident.- Anonymous callers share 1,000 requests per day per IP. Add a free openFDA key if you run this at volume.
Pricing
Pay per event. $0.001 per recall, $0.05 per firm summary.