# FDA Drug Shortage Scraper (openFDA Shortages Data) (`steadfetch/fda-drug-shortage-monitor`) Actor

Official FDA drug shortage records from openFDA in JSON: drug, brand, company, status, availability, therapeutic category and ISO dates - the shortage list as data. Filters plus a change monitor for new and revised entries. For pharmacy stock planning and drug supply research. CC0 data, no login.

- **URL**: https://apify.com/steadfetch/fda-drug-shortage-monitor.md
- **Developed by:** [Steadfetch](https://apify.com/steadfetch) (community)
- **Categories:** Business, Other
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.20 / 1,000 shortage record delivereds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## FDA Drug Shortage Scraper (openFDA Shortages Data)

[![Steadfetch](https://img.shields.io/badge/Steadfetch-public%20data-0b7285)](https://apify.com/steadfetch)

Read the official [openFDA drug shortage](https://open.fda.gov/apis/drug/shortage/) dataset as clean, schema-validated JSON. Every run reads the public, keyless openFDA API and returns one item per shortage record with the drug, brand, company, status, availability, therapeutic category and ISO dates. A built-in monitor mode delivers only new records or records whose status or availability changed since the previous run.

### What it does

- Reads `https://api.fda.gov/drug/shortages.json` (no API key, no login, no browser, no proxy).
- Normalizes the source into a single schema: `genericName`, `brandName`, `companyName`, `status`, `availability`, `updateType`, `updateDate`, `initialPostingDate`, `packageNdc`, `presentation`, `applicationNumber`, `therapeuticCategory` and `therapeuticCategories`.
- Converts the source `MM/DD/YYYY` dates to ISO 8601 (`YYYY-MM-DD`).
- Sorts results newest first (by update date) and deduplicates identical records within a run.
- Filters by `status` and `therapeuticCategory`.
- Monitor mode: stores the last status/availability snapshot per Apify user and returns only records that are new or changed. A quiet run returns zero results and charges no result event.
- Validates every item against `.actor/dataset_schema.json` before it reaches the dataset. Unvalidated data is never published.

The openFDA shortage feed is public but awkward to use directly: callers must build the query, parse `MM/DD/YYYY` dates, resolve the `openfda` product block and diff `status`/`availability` between runs by hand. This Actor does that and returns one stable, documented schema.

### How to use

Run it from the Apify Console, the API or the CLI:

```bash
apify call steadfetch/fda-drug-shortage-monitor --input='{"status":["Current"],"maxResults":50}'
```

With every field omitted, the Actor returns 10 records (the schema prefill), which keeps the first run fast and cheap.

#### Input fields

| Field | Type | Default | Description |
| --- | --- | --- | --- |
| `status` | array of strings | `[]` (all) | Keep only records with one of these statuses: `Current`, `Resolved`, `To Be Discontinued`. |
| `therapeuticCategory` | array of strings | `[]` (all) | Keep only records tagged with at least one of these categories (case-insensitive). |
| `monitorMode` | boolean | `false` | When `true`, deliver only new or changed records for this Apify user and bill one `monitor-check` event per checked record. |
| `maxResults` | integer | `2000` | Maximum records delivered. Lower it for small, cheap runs. |

#### Example input

Matches the declared `exampleRunInput` exactly:

```json
{
  "status": [],
  "therapeuticCategory": [],
  "monitorMode": false,
  "maxResults": 10
}
```

### Example output

```json
{
  "url": "https://api.fda.gov/drug/shortages.json",
  "title": "VYVANSE",
  "scrapedAt": "2026-10-26T04:00:00.000Z",
  "genericName": "Lisdexamfetamine Dimesylate Capsule",
  "brandName": "VYVANSE",
  "companyName": "Takeda Pharmaceuticals USA Inc.",
  "status": "Current",
  "availability": "Available",
  "updateType": "Reverified",
  "updateDate": "2026-10-15",
  "initialPostingDate": "2023-07-14",
  "packageNdc": "59417-102-10",
  "presentation": "Vyvanse, Capsule, 20 mg (NDC 59417-102-10)",
  "applicationNumber": "NDA021977",
  "therapeuticCategory": "Psychiatry",
  "therapeuticCategories": ["Psychiatry"],
  "sourceUrl": "https://api.fda.gov/drug/shortages.json"
}
```

In monitor mode every item also carries `changeType` (`new` or `updated`) and `changedFields` (for example `["availability"]`).

#### Output fields

| Field | Type | Description |
| --- | --- | --- |
| `url` | string | Source API URL (common Steadfetch envelope, required). |
| `title` | string or null | Brand name when available, otherwise the generic name. |
| `scrapedAt` | string | ISO 8601 UTC timestamp of the extraction (required). |
| `genericName` | string | Generic drug name and dosage form (required). |
| `brandName` | string or null | Brand name from the openFDA product block. |
| `companyName` | string or null | Company reporting the shortage. |
| `status` | string or null | `Current`, `Resolved` or `To Be Discontinued`. |
| `availability` | string or null | Availability text, kept verbatim from the source. |
| `updateType` | string or null | Latest update type (for example `Reverified`). |
| `updateDate` | string | Latest update date, ISO 8601 (required). |
| `initialPostingDate` | string | First posting date, ISO 8601 (required). |
| `packageNdc` | string or null | National Drug Code of the affected package. |
| `presentation` | string or null | Presentation as published by the FDA (product, dosage form, strength and NDC). Distinguishes records that share an NDC and posting date. |
| `applicationNumber` | string or null | FDA application number (NDA/ANDA). |
| `therapeuticCategory` | string or null | First therapeutic category. |
| `therapeuticCategories` | array of strings | All therapeutic categories for the record. |
| `changeType` | string or null | Monitor mode only: `new` or `updated`. |
| `changedFields` | array of strings | Monitor mode only: fields that changed (`status`, `availability`). |

### Pricing

Pay per event, so you only pay for what you use:

- **`apify-default-dataset-item`:** 1.50 USD per 1,000 delivered records (0.0015 USD per record). Only validated records delivered to the dataset are charged.
- **`monitor-check`:** 0.05 USD per 1,000 checks (0.00005 USD per checked record), charged in `monitorMode` only, once per record actually checked. A check that finds no change still bills the check but no result event.
- **`apify-actor-start`:** 0.00005 USD per run (the Apify default; includes the first 5 seconds of compute).

Measured cost: the whole shortage feed is about 1,600 records and two keyless API requests, so the source cost is effectively **below 0.01 USD per 1,000 records**. The `monitor-check` price keeps a wide margin over the measured compute cost per 1,000 checks.

On the Apify free plan, the 5 USD monthly credit pays for roughly 3,300 delivered records (5.00 / 0.0015), more than the whole current dataset, before any `monitor-check` events.

### Data source and licence

- Source: [openFDA Drug Shortages API](https://open.fda.gov/apis/drug/shortage/), endpoint `https://api.fda.gov/drug/shortages.json`.
- Licence: **public domain (CC0 1.0)**, per the [openFDA terms](https://open.fda.gov/terms/). Attribution: data courtesy of the U.S. Food and Drug Administration (openFDA).
- Only product-level supply fields are mapped. No patient, prescriber or private contact data is read or emitted.
- Requests use a single identified user agent (`SteadfetchBot/1.0`) and at least one second between page requests.

> **FDA disclaimer:** Do not rely on openFDA to make decisions regarding medical care. While the FDA makes every effort to ensure the data is accurate, all results should be assumed unvalidated.

### FAQ

**Does it need an API key?** No. openFDA is keyless; the Actor needs no secrets.

**What does monitor mode return on a quiet day?** Zero results. Only new records or records whose `status`/`availability` changed are delivered, and no result event is charged.

**Why is `packageNdc` not unique?** The FDA can list the same NDC twice (for example a current shortage and a separate "To Be Discontinued" notice), and one NDC can carry several presentations. The Actor uses NDC, posting date, drug, company and presentation as its identity, so distinct presentations stay as separate rows and remain stable across runs.

**Can I get every record?** Yes. Leave both filters empty and keep `maxResults` at its default (or higher).

**What happens if the API rate-limits us?** The client retries with backoff and, if the limit persists, stops gracefully and returns the records already collected. Failed requests are never charged.

**Is it legal to use this data?** The dataset is public-domain openFDA data. Review the [openFDA terms](https://open.fda.gov/terms/) for your use case.

### Maintenance

Tested daily by Steadfetch against the live source and its output schema, in CI on every push, and in the Store quality test. If the source changes shape, the output-schema validation fails loudly instead of publishing bad data.

Steadfetch builds public-data Actors that keep working. Issues are fixed before new features are added.

# Actor input Schema

## `status` (type: `array`):

Optional. Keep only records whose status is one of these values. Empty means all statuses. Source values: Current, Resolved, To Be Discontinued.

## `therapeuticCategory` (type: `array`):

Optional. Keep only records tagged with at least one of these therapeutic categories (for example Anesthesia, Oncology, Cardiovascular). Matching ignores case. Empty means all categories.

## `monitorMode` (type: `boolean`):

When enabled, only records that are new or whose status/availability changed since the previous run for the same Apify user are delivered, and each checked record bills one monitor-check event. Leave disabled for a one-off backfill.

## `maxResults` (type: `integer`):

Maximum number of records delivered to the dataset. The default of 100 is a small, cheap first run; raise it to pull the full current source (about 1,700 open shortages). Each delivered record is one billable result event.

## Actor input object example

```json
{
  "status": [
    "Current"
  ],
  "therapeuticCategory": [
    "Anesthesia"
  ],
  "monitorMode": false,
  "maxResults": 10
}
```

# Actor output Schema

## `results` (type: `string`):

Dataset items validated against the item schema in dataset_schema.json (fields).

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "status": [],
    "therapeuticCategory": [],
    "monitorMode": false,
    "maxResults": 10
};

// Run the Actor and wait for it to finish
const run = await client.actor("steadfetch/fda-drug-shortage-monitor").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "status": [],
    "therapeuticCategory": [],
    "monitorMode": False,
    "maxResults": 10,
}

# Run the Actor and wait for it to finish
run = client.actor("steadfetch/fda-drug-shortage-monitor").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "status": [],
  "therapeuticCategory": [],
  "monitorMode": false,
  "maxResults": 10
}' |
apify call steadfetch/fda-drug-shortage-monitor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,steadfetch/fda-drug-shortage-monitor"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/n9sMGJgGYlmIetTFm/builds/LIXRxJjPzpbFLglXN/openapi.json
