# FDA Orange Book Patents & Exclusivity Scraper (`scrapers_lat/fda-orange-book-patents-scraper`) Actor

Scrape the FDA Orange Book: approved drug products joined to their patents and marketing exclusivity, with patent numbers, expiry dates, use codes and generic-entry / patent-cliff dates. Filter by ingredient, brand, applicant or expiry. Export JSON, CSV or Excel.

- **URL**: https://apify.com/scrapers\_lat/fda-orange-book-patents-scraper.md
- **Developed by:** [Scrapers Lat](https://apify.com/scrapers_lat) (community)
- **Categories:** Developer tools, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $14.18 / 1,000 drug product results

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/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

[![FDA Orange Book Patents & Exclusivity Scraper](https://scrapers.lat/banners/fda-orange-book-patents-scraper.png)](https://console.apify.com/actors/djEUsvb1AYpcNvakp/input)

## FDA Orange Book Patents & Exclusivity Scraper

Here is one real result, with every field the actor returns:

```json
{
  "ingredient": "ATORVASTATIN CALCIUM",
  "tradeName": "ATORVALIQ",
  "applicant": "CMP DEV LLC",
  "applicantFullName": "CMP DEVELOPMENT LLC",
  "strength": "20MG/5ML",
  "dosageForm": "SUSPENSION",
  "route": "ORAL",
  "applType": "NDA - New Drug (brand)",
  "applTypeCode": "N",
  "applNo": "213260",
  "productNo": "001",
  "teCode": null,
  "approvalDate": "2023-02-01",
  "approvalDateText": "Feb 1, 2023",
  "referenceListedDrug": true,
  "referenceStandard": true,
  "marketingStatus": "Prescription",
  "hasPatents": true,
  "patentCount": 7,
  "exclusivityCount": 0,
  "earliestPatentExpiry": "2037-06-07",
  "latestPatentExpiry": "2037-06-07",
  "patents": [
    {
      "patentNo": "11654106",
      "expireDate": "2037-06-07",
      "expireDateText": "Jun 7, 2037",
      "drugSubstance": false,
      "drugProduct": true,
      "patentUseCode": "U-3612",
      "delisted": false,
      "submissionDate": "2023-06-01"
    }
  ],
  "exclusivity": null,
  "orangeBookUrl": "https://www.accessdata.fda.gov/scripts/cder/ob/results_product.cfm?Appl_Type=n&Appl_No=213260",
  "aiPatentCliff": null,
  "dataFileDate": "2026-08-14",
  "source": "FDA Orange Book",
  "observedAt": "2026-08-20T15:57:53.743Z",
  "error": null
}
```

The most complete FDA Orange Book scraper available. It returns every product the Orange Book lists, joined to its patents and marketing exclusivity, with patent numbers, expiry dates, drug-substance and drug-product flags and use codes, plus derived fields (`earliestPatentExpiry`, `latestPatentExpiry`, `patentCount`, `hasPatents`), and it gives you eight filters to target exactly the drugs and patent-cliff windows you need.

**📥 [Input](https://apify.com/scrapers_lat/fda-orange-book-patents-scraper/input-schema) · 📤 [Output](https://apify.com/scrapers_lat/fda-orange-book-patents-scraper/output-schema) · 💰 [Pricing](https://apify.com/scrapers_lat/fda-orange-book-patents-scraper/pricing) · ▶️ [Examples](https://apify.com/scrapers_lat/fda-orange-book-patents-scraper/examples)**

![Apify](https://img.shields.io/badge/Platform-Apify-1CE1CE?logo=apify\&logoColor=white)
![Coverage](https://img.shields.io/badge/Coverage-United%20States-blue)
![Output](https://img.shields.io/badge/Output-JSON%20%7C%20CSV%20%7C%20Excel-orange)
![Billing](https://img.shields.io/badge/Billing-Pay%20per%20result-brightgreen)

### Table of contents

- [What it does](#what-it-does)
- [Quickstart](#quickstart)
- [Input reference](#input-reference)
- [Output reference](#output-reference)
- [Example output record](#example-output-record)
- [Run via API and CLI](#run-via-api-and-cli)
- [Fetch results](#fetch-results)
- [Billing and limits](#billing-and-limits)
- [FAQ and troubleshooting](#faq-and-troubleshooting)

### What it does

The actor reads the current FDA Orange Book (Approved Drug Products with Therapeutic Equivalence Evaluations) data file, joins each approved drug product to its listed patents and marketing exclusivity by application and product number, applies the filters you pass, and writes one normalized record per product to the run's dataset.

The uniquely valuable part is the patent and exclusivity layer. For every product you get the full list of Orange Book patents (patent number, expiry date, drug-substance flag, drug-product flag, use code, delist flag, submission date) and every exclusivity entry (code and date), plus derived `earliestPatentExpiry` and `latestPatentExpiry` so you can rank drugs by patent cliff without extra parsing. That is the data that drives generic-entry timing, patent-cliff models, paragraph-IV strategy and pharma investment analysis.

Dates are normalized to `YYYY-MM-DD` (the original printed text is kept alongside), missing source values are returned as `null`, and each record names the exact Orange Book data-file date it was drawn from.

### Quickstart

Open the actor, paste this into the input, and press Run. It returns up to 10 atorvastatin products that list patents.

```json
{
  "ingredient": "atorvastatin",
  "hasPatents": true,
  "maxResults": 10
}
```

Every input field is optional. Combine filters to narrow the set, for example a `patentExpiresAfter` / `patentExpiresBefore` window to find drugs whose patents fall due in a target period.

### Input reference

| Field | Type | Required | Default | Description |
|---|---|---|---|---|
| `ingredient` | string | no | (empty) | Active ingredient contains this text, case-insensitive, for example `atorvastatin`, `semaglutide`, `apixaban`. |
| `tradeName` | string | no | (empty) | Trade / brand name contains this text, for example `Lipitor`, `Eliquis`, `Ozempic`. |
| `applicant` | string | no | (empty) | Applicant / holder name contains this text, for example `Pfizer`, `Teva`, `Novartis`. Matches the short and full name. |
| `applNo` | string | no | (empty) | Exact FDA application number, with or without its `N`/`A` prefix, for example `020702` or `NDA020702`. |
| `teCode` | string | no | (empty) | Exact therapeutic equivalence code, for example `AB`, `AP`, `BX`. `AB` products are substitutable generics. |
| `hasPatents` | boolean | no | `false` | When on, return only products that list at least one Orange Book patent. |
| `patentExpiresAfter` | string | no | (empty) | Return only products with at least one patent expiring on or after this date (`YYYY-MM-DD`). |
| `patentExpiresBefore` | string | no | (empty) | Return only products with at least one patent expiring on or before this date (`YYYY-MM-DD`). |
| `maxResults` | integer | no | `10` | Maximum drug product records to return. One drug can yield several product rows (one per strength). Free Apify plans are capped at 10. |
| `withAiPatentCliff` | boolean | no | `false` | Paid add-on. For each product that lists patents, generate an AI patent-cliff read (generic-entry outlook, key blocking patents, risk notes). Disabled for free plans. |

Filters combine with logical AND. With an empty input the actor returns the first products in the current data file, up to `maxResults`.

### Output reference

One dataset item per drug product. Types: `string`, `integer`, `boolean`, `array`, `object`, or `null` when the source value is absent.

| Field | Type | Description |
|---|---|---|
| `ingredient` | string | Active ingredient(s) of the product. |
| `tradeName` | string | Trade / brand name. |
| `applicant` | string | Applicant / holder short name. |
| `applicantFullName` | string | Applicant full legal name. |
| `strength` | string | Product strength. |
| `dosageForm` | string | Dosage form, for example `TABLET`, `SUSPENSION`, `INJECTION`. |
| `route` | string | Route of administration, for example `ORAL`, `INTRAVENOUS`. |
| `applType` | string | Application type in words: `NDA - New Drug (brand)` or `ANDA - Generic`. |
| `applTypeCode` | string | Raw application type code: `N` (NDA) or `A` (ANDA). |
| `applNo` | string | FDA application number. |
| `productNo` | string | Product number within the application. |
| `teCode` | string | Therapeutic equivalence code, or `null` when not rated. |
| `approvalDate` | string | Approval date (`YYYY-MM-DD`), or `null` when approved before 1982. |
| `approvalDateText` | string | Approval date as printed in the source, for example `Feb 1, 2023`. |
| `referenceListedDrug` | boolean | Whether the product is a Reference Listed Drug (RLD). |
| `referenceStandard` | boolean | Whether the product is a Reference Standard (RS). |
| `marketingStatus` | string | `Prescription`, `Over-the-counter`, or `Discontinued`. |
| `hasPatents` | boolean | Whether the product lists any Orange Book patent. |
| `patentCount` | integer | Number of listed patents. |
| `exclusivityCount` | integer | Number of exclusivity entries. |
| `earliestPatentExpiry` | string | Earliest listed patent expiry (`YYYY-MM-DD`), or `null`. |
| `latestPatentExpiry` | string | Latest listed patent expiry (`YYYY-MM-DD`), or `null`. |
| `patents` | array | Listed patents, each with `patentNo`, `expireDate`, `expireDateText`, `drugSubstance`, `drugProduct`, `patentUseCode`, `delisted`, `submissionDate`. `null` when none. |
| `exclusivity` | array | Marketing exclusivity entries, each with `exclusivityCode`, `exclusivityDate`, `exclusivityDateText`. `null` when none. |
| `orangeBookUrl` | string | Link to the product's Orange Book page. |
| `aiPatentCliff` | object | AI patent-cliff analysis when the add-on is enabled, otherwise `null`. |
| `dataFileDate` | string | Date of the Orange Book data file the record was drawn from. |
| `source` | string | Always `FDA Orange Book`. |
| `observedAt` | string | ISO 8601 timestamp of when the record was collected. |
| `error` | string | `null` on success. On a failed run a single item with a populated `error` field is written instead. |

### Example output record

Real record from a live run (input `{"ingredient":"atorvastatin","hasPatents":true,"maxResults":10}`), showing the full patent list:

```json
{
  "ingredient": "ATORVASTATIN CALCIUM",
  "tradeName": "ATORVALIQ",
  "applicant": "CMP DEV LLC",
  "applicantFullName": "CMP DEVELOPMENT LLC",
  "strength": "20MG/5ML",
  "dosageForm": "SUSPENSION",
  "route": "ORAL",
  "applType": "NDA - New Drug (brand)",
  "applNo": "213260",
  "productNo": "001",
  "approvalDate": "2023-02-01",
  "referenceListedDrug": true,
  "marketingStatus": "Prescription",
  "hasPatents": true,
  "patentCount": 7,
  "earliestPatentExpiry": "2037-06-07",
  "latestPatentExpiry": "2037-06-07",
  "patents": [
    { "patentNo": "11654106", "expireDate": "2037-06-07", "drugSubstance": false, "drugProduct": true, "patentUseCode": "U-3612", "delisted": false, "submissionDate": "2023-06-01" },
    { "patentNo": "11925704", "expireDate": "2037-06-07", "drugSubstance": false, "drugProduct": true, "patentUseCode": "U-3853", "delisted": false, "submissionDate": "2024-03-25" }
  ],
  "exclusivity": null,
  "orangeBookUrl": "https://www.accessdata.fda.gov/scripts/cder/ob/results_product.cfm?Appl_Type=n&Appl_No=213260",
  "dataFileDate": "2026-08-14",
  "source": "FDA Orange Book",
  "observedAt": "2026-08-20T15:57:53.743Z",
  "error": null
}
```

With `withAiPatentCliff` enabled, each product that lists patents also gets an `aiPatentCliff` object, for example:

```json
{
  "aiPatentCliff": {
    "genericEntryOutlook": "Generic competition can realistically enter after the earliest patent on November 8, 2026, but may be delayed until February 2, 2037 due to additional patents.",
    "keyPatents": ["10722471", "9388134", "8877938"],
    "riskNotes": "No exclusivities are listed that would further delay generic entry, but multiple patents may pose challenges for generic manufacturers."
  }
}
```

### Run via API and CLI

Start a run and wait for it to finish, then read the dataset. Replace `<TOKEN>` with your Apify API token.

Run synchronously and get dataset items in one call:

```bash
curl -X POST "https://api.apify.com/v2/acts/scrapers_lat~fda-orange-book-patents-scraper/run-sync-get-dataset-items?token=<TOKEN>" \
  -H "Content-Type: application/json" \
  -d '{"ingredient":"apixaban","hasPatents":true,"maxResults":25}'
```

Start a run asynchronously:

```bash
curl -X POST "https://api.apify.com/v2/acts/scrapers_lat~fda-orange-book-patents-scraper/runs?token=<TOKEN>" \
  -H "Content-Type: application/json" \
  -d '{"patentExpiresAfter":"2027-01-01","patentExpiresBefore":"2030-12-31","maxResults":100}'
```

Apify CLI:

```bash
apify call scrapers_lat/fda-orange-book-patents-scraper \
  --input '{"tradeName":"eliquis","hasPatents":true}'
```

### Fetch results

Every run writes to a dataset. Fetch items as JSON, CSV, or Excel by changing `format`:

```bash
## JSON
curl "https://api.apify.com/v2/datasets/<DATASET_ID>/items?token=<TOKEN>&clean=true&format=json"

## CSV
curl "https://api.apify.com/v2/datasets/<DATASET_ID>/items?token=<TOKEN>&clean=true&format=csv"

## Paginate large datasets
curl "https://api.apify.com/v2/datasets/<DATASET_ID>/items?token=<TOKEN>&offset=1000&limit=1000"
```

`<DATASET_ID>` is returned as `defaultDatasetId` in the run object. Use `offset` and `limit` to page through large result sets. `clean=true` drops empty and internal fields.

### Billing and limits

- **Pay per result.** You are charged per drug product record returned (`result` event), plus a small one-time `Actor start` fee per run. See the [pricing tab](https://apify.com/scrapers_lat/fda-orange-book-patents-scraper/pricing) for current prices.
- **AI patent-cliff add-on.** When you enable `withAiPatentCliff`, the `AI patent-cliff analysis` event is charged once per product, only when the analysis is produced. Off by default and disabled for free plans.
- **No charge on failure.** If a run errors, the actor writes a single item with a populated `error` field and does not charge for it. Empty runs cost nothing.
- **Spend cap respected.** Set `maxTotalChargeUsd` on the run; once reached, the actor stops emitting and charging further billable results.
- **Free Apify plans** are capped at 10 records per run. Upgrade for higher `maxResults`.

### FAQ and troubleshooting

**A run returned 0 records. Why?**
The filter combination matched nothing in the current data file. Loosen filters (for example remove `hasPatents` or widen the expiry window), or check the spelling of the ingredient or trade name. Zero-result runs are not charged.

**How do I find drugs facing a patent cliff in a given window?**
Set `patentExpiresAfter` and `patentExpiresBefore` to the window you care about and `hasPatents` to true. Rank the results by `earliestPatentExpiry`.

**Why do some products have no patents or no exclusivity?**
Older drugs and many generics have no listed patents or exclusivity, so those fields are `null`. The Orange Book only lists patents and exclusivity that a sponsor has submitted for the product.

**What is the difference between `earliestPatentExpiry` and `latestPatentExpiry`?**
They are the minimum and maximum expiry dates across the product's listed patents. The earliest is the first date a patent barrier can fall; the latest is when the last listed patent expires.

**Why is `teCode` null?**
The product is not therapeutically rated (for example a single-source innovator with no rated equivalent). Missing source values are returned as `null`, never invented.

**Is this an official FDA tool?**
No. This actor is independent and has no affiliation with the FDA. It reads only data that the FDA publishes publicly in the Orange Book data file. Use it in accordance with the FDA terms of use.

### Related scrapers

- [FDA Drug Approvals Scraper](https://apify.com/scrapers_lat/fda-drug-approvals-scraper): Drugs@FDA NDA, ANDA and BLA approvals with sponsors and submission history.
- [FDA NDC Drug Directory Scraper](https://apify.com/scrapers_lat/fda-ndc-drug-directory-scraper): National Drug Code directory of marketed drug products.
- [openFDA Drug Labels Scraper](https://apify.com/scrapers_lat/openfda-drug-labels-scraper): Structured drug labeling (SPL) content.
- [USPTO Patent Assignments Scraper](https://apify.com/scrapers_lat/uspto-patent-assignments-scraper): US patent assignment and ownership records.
- [SEC EDGAR Company Filings Scraper](https://apify.com/scrapers_lat/sec-edgar-filings-scraper): SEC filings by ticker or CIK.

### More scrapers at scrapers.lat

Built and maintained by [scrapers.lat](https://scrapers.lat), where we publish scrapers for US and Latin American public platforms: company registries, government data, finance, e-commerce and more. Browse the catalog or request a custom scraper at [scrapers.lat](https://scrapers.lat).

***

> Independent tool, not affiliated with the FDA. Accesses only publicly available FDA Orange Book data. Use in accordance with the FDA terms of use.

# Actor input Schema

## `ingredient` (type: `string`):

Return products whose active ingredient contains this text, for example atorvastatin, semaglutide or apixaban. Case-insensitive substring match. Leave empty to ignore.

## `tradeName` (type: `string`):

Return products whose trade (brand) name contains this text, for example Lipitor, Eliquis or Ozempic. Case-insensitive substring match. Leave empty to ignore.

## `applicant` (type: `string`):

Return products whose applicant name contains this text, for example Pfizer, Teva or Novartis. Matches the short and full applicant name. Leave empty to ignore.

## `applNo` (type: `string`):

Exact FDA application number, with or without its N/A prefix, for example 020702 or NDA020702. Returns just that application's products.

## `teCode` (type: `string`):

Restrict to an exact TE code, for example AB, AP or BX. AB-rated products are substitutable generics. Leave empty for all.

## `hasPatents` (type: `boolean`):

When on, return only products that have at least one listed Orange Book patent. Useful for patent-cliff and generic-entry analysis.

## `patentExpiresAfter` (type: `string`):

Return only products that have at least one listed patent expiring on or after this date. Format YYYY-MM-DD, for example 2027-01-01. Use with the field below to target a patent-cliff window.

## `patentExpiresBefore` (type: `string`):

Return only products that have at least one listed patent expiring on or before this date. Format YYYY-MM-DD, for example 2030-12-31.

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

Maximum number of drug product records to return. One drug can yield several product rows (one per strength). Free Apify plans are capped at 10.

## `withAiPatentCliff` (type: `boolean`):

Add-on: for each product that lists patents, generate an AI patent-cliff read (generic-entry outlook, key blocking patents, risk notes) from the Orange Book patent and exclusivity dates. Billed once per product only on usable output. Disabled for free plans.

## Actor input object example

```json
{
  "hasPatents": false,
  "maxResults": 10,
  "withAiPatentCliff": false
}
```

# Actor output Schema

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

No description

# 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 = {
    "maxResults": 10
};

// Run the Actor and wait for it to finish
const run = await client.actor("scrapers_lat/fda-orange-book-patents-scraper").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 = { "maxResults": 10 }

# Run the Actor and wait for it to finish
run = client.actor("scrapers_lat/fda-orange-book-patents-scraper").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 '{
  "maxResults": 10
}' |
apify call scrapers_lat/fda-orange-book-patents-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,scrapers_lat/fda-orange-book-patents-scraper"
        }
    }
}

```

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/djEUsvb1AYpcNvakp/builds/BVBr48s6qs469R24B/openapi.json
