# Nigeria NAFDAC Greenbook Registered Products (`a-g-d/ng-nafdac`) Actor

Every product in Nigeria's NAFDAC Greenbook (greenbook.nafdac.gov.ng) as English-keyed JSON: registration number (NRN), product, category, status, applicant, manufacturer, active ingredients, form, route, strength, pack size, ATC code, SmPC link, approval and expiry dates.

- **URL**: https://apify.com/a-g-d/ng-nafdac.md
- **Developed by:** [Aloever Dulay](https://apify.com/a-g-d) (community)
- **Categories:** E-commerce, Other
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.00 / 1,000 product registrations

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

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

## Nigeria NAFDAC Greenbook Registered Products Actor (greenbook.nafdac.gov.ng)

Every product in the **NAFDAC Greenbook**, the registered-product database of Nigeria's
National Agency for Food and Drug Administration and Control
([greenbook.nafdac.gov.ng](https://greenbook.nafdac.gov.ng)), as clean, English JSON:
NAFDAC registration number (NRN), product name, category, status, marketing category
(prescription-only or over-the-counter), applicant, manufacturer (name, and country on
request), active ingredients, dosage form, route, strength, pack size, composition, ATC
code, a link to the SmPC (PDF), approval and expiry dates, and a link to the product page.

Categories: drugs (about 7,500 records), medical devices (about 1,100), vaccines and
biologics (about 150), herbals and nutraceuticals (about 130) and veterinary products
(about 90); about 9,000 in all, Active and Inactive. Counts from September 2026.

### Who needs this

- **Pharmacies, distributors and marketplaces** checking that the products they stock or
  list carry a valid NAFDAC registration, or auditing a catalogue in bulk.
- **Manufacturers and importers** watching competitors' new approvals, and registrations
  (their own or others') that are about to expire.
- **Market-access and regulatory consultants** sizing a therapeutic area in Nigeria: which
  molecules are registered, by whom, made where, prescription-only or over the counter.
- **Researchers and public-health analysts** studying Nigeria's medicines market, for
  example how many antimalarial generics are registered and who makes them.
- **AI agents and automations** that need a stable schema rather than a search page.

### Input

| Field                        | Type    | Default  | Description                                                                                                                                                          |
| ---------------------------- | ------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `category`                   | string  | `""`     | `drugs`, `vaccines-and-biologics`, `medical-devices`, `veterinary`, `herbals-and-nutraceuticals`, `disinfectants` (none listed in September 2026), or empty for all. |
| `status`                     | string  | `""`     | `Active` or `Inactive`, or empty for both.                                                                                                                           |
| `productName`                | string  | `""`     | Product name contains this text, e.g. `paracetamol`.                                                                                                                 |
| `ingredient`                 | string  | `""`     | Active ingredient or its synonym contains this text, e.g. `artemether`, or `acetaminophen` (which finds paracetamol).                                                |
| `registrationNumber`         | string  | `""`     | Registration number contains this text: a full NRN (`A11-101363`) or a prefix (`A4-`).                                                                               |
| `applicant`                  | string  | `""`     | Applicant's company name contains this text, e.g. `emzor`.                                                                                                           |
| `approvedSince`              | string  | `""`     | Approved on or after this date (`YYYY-MM-DD`).                                                                                                                       |
| `expiringBefore`             | string  | `""`     | Expiry date between today (Lagos time) and this date (`YYYY-MM-DD`): registrations due for renewal.                                                                  |
| `includeManufacturer`        | boolean | `true`   | Add the manufacturer's name (about 29 extra requests per run, roughly a minute).                                                                                     |
| `includeManufacturerCountry` | boolean | `false`  | Also add the manufacturer's country (one extra request, about 2 s, per distinct manufacturer in the results).                                                        |
| `maxItems`                   | integer | `100`    | Stop after this many registrations (1-20,000), newest approval first.                                                                                                |
| `proxyConfiguration`         | object  | no proxy | Optional Apify Proxy; the Greenbook does not need one.                                                                                                               |

Text filters are case-insensitive "contains" matches. Filters combine with AND.

**Order.** Results always come newest approval first, so an empty query gives the latest
approvals, and a daily run with `approvedSince` set to yesterday gives the day's new
registrations.

### Output

One dataset item per registered product, newest approval first. Product names, forms,
strengths and compositions are kept as published, with HTML entities decoded, surrounding
spaces trimmed and placeholders such as `NA`, `N/A` and `nil` turned into `null`. Dates
are ISO dates (`YYYY-MM-DD`): the Greenbook publishes calendar dates without a time, in
West Africa Time (WAT, UTC+1). `fetchedAt` is a UTC timestamp. The Output tab on this page documents every field.

A real item (a drug, captured 2026-09-26 with manufacturer countries on):

```json
{
  "registrationNumber": "B4-7079",
  "productId": 12464,
  "productName": "AFLOTIN 80/480 TABLETS",
  "dataQualityNote": null,
  "category": "Drugs",
  "status": "Active",
  "marketingCategory": "Over-the-counter (OTC)",
  "applicant": { "id": 578, "name": "Ajanta Pharma Nigeria Limited" },
  "manufacturer": { "id": 364, "name": "Ajanta Pharma Limited", "country": "INDIA" },
  "activeIngredients": ["Artemether", "Lumefantrine"],
  "ingredientSynonym": null,
  "dosageForm": "Tablet",
  "route": "Oral",
  "strength": "80mg; 480mg",
  "packSize": "30 x 6",
  "composition": "Each tablet contains: Artemether 80 mg, Lumefantrine 480 mg",
  "atcCode": "P01BF01",
  "smpcUrl": "https://admin.greenbook.nafdac.gov.ng/uploadImage/smpc_files/2026/09/11/2026091135eff8ba-d6ad-5ff3-924a-a103c754a1b7.pdf",
  "approvedAt": "2026-08-26",
  "expiresAt": "2031-08-25",
  "detailUrl": "https://greenbook.nafdac.gov.ng/products/details/12464",
  "sourceUrl": "https://greenbook.nafdac.gov.ng/",
  "fetchedAt": "2026-09-26T20:17:35.347Z"
}
```

What to know about the fields:

- **Medical devices** usually have no strength, form or route (`null`), and
  `activeIngredients` names the kind of device, e.g. `["Sanitary Pads"]`.
- **Registration numbers are not unique**: in September 2026, 266 numbers were shared by 544
  products. `productId` identifies a record.
- **`dataQualityNote`**: NAFDAC's editors mark some product names with `#`, `*` or `$` and
  sometimes a review note such as "duplicate NRN", "check pack size" or "strength format"
  (about 440 records). The actor removes the marks from `productName` and returns the note
  here, so you can decide how far to trust that record.
- **`marketingCategory`** is `null` for devices and other products the site marks "NA".
- **`manufacturer`**: the list itself gives only a manufacturer id. With
  `includeManufacturer` on (the default), the actor reads the Greenbook's manufacturer
  directory once per run and adds the name; with `includeManufacturerCountry` on, it also
  reads one product page per distinct manufacturer for the country. One manufacturer id in
  September 2026 was missing from the directory; its records keep the id with a `null` name.

### Data and privacy

The actor publishes the product and company data NAFDAC publishes so that the public can
check products. It **drops one field the site sends**: `product_description`, a free-text
field that in 1,699 of 8,980 records (September 2026) holds pasted spreadsheet rows with the
applicant's phone numbers and e-mail addresses, many of them named people's addresses at
Gmail or Yahoo (73% of the addresses were at free mail providers). It is never read into
the output. As a second safeguard, any other
free-text value (`composition`, `packSize`, `strength`) that contains an e-mail address or
a phone number is replaced by `null` (none did in September 2026). Applicants and
manufacturers are companies; a few are sole proprietorships trading under a person's name.
Nigeria's Data Protection Act 2023 applies to any personal data in what you store: use the
data for the purpose it is published for, checking products and their registrations.

### Pricing

Pay per event:

| Event            | Charged for                              |
| ---------------- | ---------------------------------------- |
| `product-record` | Each registration stored in the dataset. |

Apify's standard run-start event covers starting the actor. Manufacturer lookups are not
charged separately. Records are stored first and charged after, so you never pay for data
you did not receive. When your spending limit runs out, the run stops cleanly and never
stores an unpaid record.

### Data source and politeness

- **Source:** the same JSON the Greenbook's own search table loads: a jQuery DataTables
  `GET https://greenbook.nafdac.gov.ng/` with `X-Requested-With: XMLHttpRequest`. No login,
  cookie or captcha. The actor asks for 1,000 records per request (about 2 MB, 4 s), so the
  whole Greenbook takes 9 data requests. Manufacturer names come from
  `https://greenbook.nafdac.gov.ng/manufacturers` (29 pages of 50 in September 2026, about
  35 KB each, read once per run) and countries from the public product pages
  (`/products/details/<id>`, about 15 KB each, once per manufacturer).
- **robots.txt** (checked 2026-09-26) allows every user agent and every path, with no crawl
  delay. The actor still
  - waits **at least 1 second** after each request ends before the next one starts (retries
    included; a constant, not an input),
  - uses **one connection**, one request at a time,
  - identifies itself honestly as
    `ng-nafdac-actor/0.1 (+https://apify.com/a-g-d/ng-nafdac)`,
  - retries connection errors, timeouts, HTTP 429 and 5xx with exponential backoff and
    jitter inside a run-wide budget (90 s of backoff), and stops at once, with a clear
    message, if the site refuses access (HTTP 401 or 403).
- **Errors are not results.** The server answers a failed query with HTTP 200, an `error`
  message and an empty list; the actor treats that as an error, never as "no matches".
- **Terms:** the Greenbook links no terms of use; its footer reads "© NAFDAC 2025. All
  rights reserved." No statement about automated access or reuse was found.
- **Typical runs** (measured 2026-09-26): the prefill (20 newest, with names) takes about
  50 s and 30 requests; 200 records with names about 50 s; 2,500 drugs without names 16 s
  and 3 requests; 50 filtered records with names and countries 90 s and 55 requests.

### Limitations

- **Active and Inactive only.** The public Greenbook shows only registrations whose status
  is Active or Inactive and that have not been deleted; product ids run to about 12,470,
  and roughly 3,500 of them do not appear in the public list. Third-party sites that quote
  more registrations (11,704 "tracked" on one) count records collected over time, including
  ones the Greenbook no longer shows. This actor returns what the Greenbook shows today.
- **Countries are slow to add.** They are only on product pages, one request per
  manufacturer: a run over the whole Greenbook with countries on makes about 1,000 extra
  requests (about 35 minutes). Raise the run timeout accordingly.
- **Date filters are applied after download.** The site cannot filter by date range, so
  `approvedSince` and `expiringBefore` are checked on each record (the actor stops paging
  once approvals are older than `approvedSince`, and narrows `expiringBefore` to the
  expiry years on the site first). A filtered run may download more than it stores.
- **Data quality is the source's.** Strengths, pack sizes and ATC codes are free text as
  entered (some ATC codes are partial or read "Pending", which becomes `null`), and some
  records carry review notes (see `dataQualityNote`).
- **A run is a snapshot.** Approvals that arrive while a long run pages through the list
  shift it; the actor skips records it has already stored, and new approvals belong to the
  next run.

# Changelog

This Actor's version history is a separate document: https://apify.com/a-g-d/ng-nafdac/changelog.md

# Actor input Schema

## `category` (type: `string`):

Only products of this NAFDAC category. Leave on "All categories" for everything. Results always come newest approval first.

## `status` (type: `string`):

Only Active or only Inactive registrations. Leave on "Any status" for both.

## `productName` (type: `string`):

Only products whose name contains this text (case-insensitive), e.g. "paracetamol" or "amoxil". Leave empty for all.

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

Only products whose active ingredient (or its synonym) contains this text, e.g. "artemether" or "acetaminophen". Leave empty for all.

## `registrationNumber` (type: `string`):

Only registrations whose number contains this text, e.g. a full NRN such as "A11-101363" or a prefix such as "A4-". Leave empty for all.

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

Only registrations held by a company whose name contains this text, e.g. "emzor". Leave empty for all.

## `approvedSince` (type: `string`):

Only registrations approved on or after this date (YYYY-MM-DD), for monitoring new approvals.

## `expiringBefore` (type: `string`):

Only registrations whose expiry date falls between today (Lagos time) and this date (YYYY-MM-DD), for monitoring renewals.

## `includeManufacturer` (type: `boolean`):

Add the manufacturer's name to each record. The actor reads the Greenbook's manufacturer directory once per run (about 29 extra requests, roughly a minute). Turn off for the manufacturer id only.

## `includeManufacturerCountry` (type: `boolean`):

Also add the manufacturer's country, read from one product page per manufacturer (cached within the run). That is one extra request, about 2 seconds, for every distinct manufacturer in the results, so large runs take much longer.

## `maxItems` (type: `integer`):

Stop after storing this many registrations (newest approval first). The whole Greenbook held about 9,000 in September 2026.

## `proxyConfiguration` (type: `object`):

Optional. The Greenbook needs no proxy; use one only if runs fail with connection errors.

## Actor input object example

```json
{
  "category": "",
  "status": "",
  "productName": "",
  "ingredient": "",
  "registrationNumber": "",
  "applicant": "",
  "approvedSince": "",
  "expiringBefore": "",
  "includeManufacturer": true,
  "includeManufacturerCountry": false,
  "maxItems": 20,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

## `products` (type: `string`):

One item per registered product matching the input, newest approval first: NAFDAC registration number, product name, category, status, marketing category, applicant, manufacturer, active ingredients, form, route, strength, pack size, composition, ATC code, SmPC link, approval and expiry dates (ISO dates, WAT) and a link to the product page.

# 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 = {
    "maxItems": 20,
    "proxyConfiguration": {
        "useApifyProxy": false
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("a-g-d/ng-nafdac").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 = {
    "maxItems": 20,
    "proxyConfiguration": { "useApifyProxy": False },
}

# Run the Actor and wait for it to finish
run = client.actor("a-g-d/ng-nafdac").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 '{
  "maxItems": 20,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}' |
apify call a-g-d/ng-nafdac --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,a-g-d/ng-nafdac"
        }
    }
}
```

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/JxlUljfbMsjL8dK4z/builds/ihK9EZPYzEjBuBOql/openapi.json
