openFDA Drug Labels (SPL) Scraper icon

Lead generation

openFDA Drug Labels (SPL) Scraper

Export the openFDA Structured Product Labeling (SPL) drug-label corpus as clean, flat rows — filterable by brand name, generic name, manufacturer, product NDC, or route, with section-level control over which label content (active ingredient, warnings, dosage, and more) lands in your dataset as JSON, CSV, or Excel.

Free Apify credit covers a first run. No credit card to try.

What this Actor scrapes

openFDA's /drug/label.json endpoint is the only place the FDA publishes the full structured product label (SPL) text — active ingredient, purpose, indications, warnings, dosage, and eleven more official sections — for every drug on the US market, keyed by brand name, generic name, manufacturer, NDC code, or route. The raw API ships every section as full paragraphs whether you need them or not, hides an intermittent cold-query 500, and caps pagination at 25 000 skipped records. This Actor normalises all of that into one dependable row shape with a section-level field-selection toggle, so a compliance or competitive-intel watchlist becomes a spreadsheet instead of a scripting project.

What we handle for you

  • 🛡️ Browser fingerprint rotationcurl-cffi impersonates real Chrome / Firefox / Safari TLS handshakes on every request.
  • 🔁 Retries with exponential backoff on 408 / 429 / 5xx, including openFDA's documented cold-query timeouts — up to 5 attempts per page.
  • 🧱 Stops cleanly at openFDA's pagination ceiling instead of looping on a 400, and fails loud (not silently empty) if the endpoint goes down for 3 consecutive pages.
  • 🧊 Per-record fault isolation — one malformed record never takes down the run; we skip it, log it, and keep paging.
  • 🧊 Section-level field selection — pick only the label sections you need; unset sections come back null instead of billing you for paragraphs you'll never read.
  • 💰 Pay-Per-Event pricing — you only pay for results that hit your dataset. No data, no charge.

Use cases

  • Pull the official label text (warnings, dosage, active ingredients) for every SKU your marketplace or pharmacy sells, and flag listings whose copy drifts from the FDA's own record.
  • Track how a manufacturer's label language changes across label versions for a drug you compete with.
  • Build a regulatory/competitive-intel watchlist filtered by brand, generic name, manufacturer, NDC, or route.
  • Feed a research dataset of OTC vs. prescription label sections (active ingredient, purpose, warnings) across thousands of records.

Input

Paste this into the Apify Console, or send it as the run input over the API. Proxy settings are on by default; you rarely need to touch them.

FieldTypeRequiredWhat it does
brandName string no Filter: brand name (matches openfda.brand_name). Only field with a prefill value in this Actor — combine with other filters cautiously since all set filters are ANDed together.
genericName string no Filter: generic name (matches openfda.generic_name).
manufacturerName string no Filter: manufacturer name (matches openfda.manufacturer_name).
productNdc string no Filter: product NDC code (matches openfda.product_ndc).
route string no Filter: administration route (matches openfda.route), e.g. ORAL.
searchQuery string no Raw openFDA search expression, ANDed with the structured filters above (same convention as fda-510k-clearances-scraper). Leave empty to skip.
fields array no Which label content sections to populate in each output row. openfda identity fields (brand/generic name, manufacturer, NDC, route, substance, application number) and id/set_id/version/effective_time are always…
maxResults integer no Stop after this many records. Each record is one billed result row.
{
  "brandName": "Ibuprofen",
  "maxResults": 3,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}

Output

One row per result, schema-validated before it is written. Export JSON, CSV, Excel or XML from the run, or read it over the API.

idset_idversioneffective_timebrand_namegeneric_namemanufacturer_nameproduct_ndcproduct_typeroutesubstance_nameapplication_numberactive_ingredientpurposeindications_and_usagewarnings

{
  "id": "d3f8a2b1-9c44-4e11-8a77-2f6b1c9e0a12",
  "set_id": "b4e2f9c0-1234-4a56-9abc-def012345678",
  "version": "3",
  "effective_time": "20240115",
  "brand_name": "IBUPROFEN",
  "generic_name": "IBUPROFEN",
  "manufacturer_name": "Acme Pharmaceuticals Inc.",
  "product_ndc": [
    "12345-678-90"
  ],
  "product_type": "HUMAN OTC DRUG",
  "route": [
    "ORAL"
  ],
  "substance_name": [
    "IBUPROFEN"
  ],
  "application_number": "part341",
  "active_ingredient": "Ibuprofen 200 mg (NSAID)",
  "purpose": "Pain reliever/fever reducer",
  "indications_and_usage": "temporarily relieves minor aches and pains...",
  "warnings": "Allergy alert: Ibuprofen may cause a severe allergic reaction...",
  "do_not_use": null,
  "ask_doctor": null,
  "ask_doctor_or_pharmacist": null,
  "when_using": null,
  "stop_use": null,
  "pregnancy_or_breast_feeding": null,
  "keep_out_of_reach_of_children": null,
  "dosage_and_administration": null,
  "storage_and_handling": null,
  "inactive_ingredient": null,
  "questions": null,
  "package_label_principal_display_panel": null
}

Pricing

EventPriceWhen
Actor start$0.20Once per run, covers warm-up and proxy session setup.
Result emitted$0.0030Per result written to the dataset.

You pay only for results that land. Cap any run with maxTotalChargeUsd. See pricing & billing for worked examples.

Limitations

  • openFDA caps pagination at 25 000 records per query on this endpoint — narrow the search to go deeper.
  • Filter values aren't escaped for embedded double-quote characters — avoid quotes inside brand, generic, manufacturer, NDC, or route filters.
  • This Actor emits the current label record as returned by openFDA for a given query; it does not walk historical version history for a given set_id.

FAQ

Do I need an API key?
No. openFDA serves label data keylessly; the Actor stays inside the anonymous rate limit (240 requests/min, 1000/day per IP).
Why are so many fields null on my rows?
Two reasons, both intentional: a content section is null when you didn't select it in fields, and it's also null when the source label simply never populated that section (most prescription-only labels skip OTC-style sections like do_not_use or ask_doctor entirely).
What's the difference between this and the other openFDA Actors?
This Actor is the only one covering /drug/label.json — the full structured product label text. openfda-adverse-events-scraper covers FAERS adverse-event reports, fda-510k-clearances-scraper covers device clearances, and fda-recalls-scraper covers recalls/enforcement actions. No output-row overlap between any of them.

Ready to run it?

Open the listing on Apify, paste the input above, and watch rows land. If it ever breaks, it is our problem before it is yours.

Related Actors

Teams that run this also run