# Pakistan DRAP Drug Prices (PharmaPrice Index) (`a-g-d/pk-drap`) Actor

Registered drug prices from the Drug Regulatory Authority of Pakistan's PharmaPrice Index (e.dra.gov.pk) as English-keyed JSON: product, composition, registration number, company and DML/DSL licence, category, pack size, maximum retail price in PKR and effective date.

- **URL**: https://apify.com/a-g-d/pk-drap.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 priced packs

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

## Pakistan DRAP Drug Prices Actor (PharmaPrice Index)

Registered drug prices from the **Drug Regulatory Authority of Pakistan (DRAP)**, read from
its public PharmaPrice Index at
[e.dra.gov.pk/public/price](https://e.dra.gov.pk/public/price), as clean, English-keyed
JSON: product name, composition, strength and dosage form, DRAP registration number, the
registration holder and its drug manufacturing (DML) or drug sale (DSL) licence, price
category, pack size, the published maximum retail price in Pakistani rupees and the date
it took effect.

The index lists about 21,500 priced packs from 392 registration holders (1,076 pages on
2026-09-26): about 20,600 in the "Essential Drugs" category and about 870 in "Low Price
Drugs".

### Who needs this

- **Pharmacies, distributors and e-pharmacies** checking shelf and listing prices against
  the price DRAP has notified, or loading a price list into their own systems.
- **Pharmaceutical companies and market-access teams** watching competitors' registered
  prices and new packs as DRAP adds them.
- **Hospitals, insurers and procurement teams** benchmarking tender and reimbursement
  prices against the regulated retail price.
- **Researchers, journalists and health-policy analysts** studying medicine prices and
  affordability in Pakistan.
- **AI agents and automations** that need a stable schema instead of a paged HTML table.

### Input

| Field                | Type    | Default    | Description                                                                                                                                         |
| -------------------- | ------- | ---------- | --------------------------------------------------------------------------------------------------------------------------------------------------- |
| `search`             | string  | `""`       | Product name or registration number contains this text, e.g. `panadol`, `augmentin` (the site's own search).                                        |
| `registrationNumber` | string  | `""`       | Every priced pack of one DRAP registration, e.g. `137272`; leading zeros optional.                                                                  |
| `company`            | string  | `""`       | Registration holder: part of its name (`searle`) or its licence number (`000016`, `DML 000016`). Matches every holder whose name contains the text. |
| `category`           | string  | `""` (any) | `essential-drugs` or `low-price-drugs`.                                                                                                             |
| `effectiveSince`     | string  | `""`       | Only prices that took effect on or after this date (`YYYY-MM-DD`). See [Prices effective since a date](#prices-effective-since-a-date).             |
| `order`              | string  | `"newest"` | `newest`: the packs DRAP added to the index most recently come first. `oldest`: the site's own order.                                               |
| `maxItems`           | integer | `100`      | Stop after this many priced packs (1-25,000).                                                                                                       |
| `proxyConfiguration` | object  | no proxy   | Optional Apify Proxy, if the site is unreachable from Apify's network.                                                                              |

Filters combine with AND. The site itself answers one filter per request, so the actor asks
it for the most selective one (a registration number, then a search, then a company, then a
category) and checks the rest on each pack it reads.

**Search.** The site's search looks at the product name and registration number, not at the
composition line: an ingredient is found only where the product name states it
(`paracetamol` finds "Nuberol-P Forte Suspension (Paracetamol)" but not "Panadol"). Search
for brand names, or use `company`.

**Order.** The site has no sort control; it lists packs in the order DRAP added them, so
the newest additions sit on its last pages. With `order` set to `newest` (the default) the
actor reads the list from the end, so a small run returns the most recently added packs.

#### Prices effective since a date

The site cannot filter or sort by the effective date, so the actor checks the date of every
pack it reads and keeps the ones on or after `effectiveSince`. Recently added packs come
first (newest order), but a price revision of an older product can sit anywhere in the
list: a complete check reads all 1,076 pages, which takes about 40 minutes at the actor's
polite pace. Raise the run timeout for that (Run options), or combine the date with a
search, company or category to read less. A run always stops cleanly shortly before its
timeout, keeping everything it stored.

### Output

One dataset item per priced pack. Keys are English; names, compositions and pack sizes are
kept exactly as DRAP publishes them (HTML entities decoded, whitespace tidied).
`maximumRetailPricePkr` is a number and `priceText` the price as printed; `effectiveFrom`
is an ISO date. `strength` and `dosageForm` are read by the actor from the product name
and are `null` when the name states none. The Output tab on this page documents every field.

A real item (captured 2026-09-26, newest-first list):

```json
{
  "productName": "Vitcefrol Injection 5mg/ml (IM/Oral)",
  "composition": "Cholecalciferol : 5 mg/ml",
  "strength": "5mg/ml",
  "dosageForm": "Injection",
  "registrationNumber": "137272",
  "company": {
    "name": "Q. Track Pharma",
    "licenceType": "DML",
    "licenceNo": "000982"
  },
  "category": "Essential Drugs",
  "packSize": "1mlx1's",
  "maximumRetailPricePkr": 110,
  "priceText": "Rs 110.00",
  "effectiveFrom": "2026-09-18",
  "sourceUrl": "https://e.dra.gov.pk/public/price?page=1076",
  "fetchedAt": "2026-09-26T20:12:08.634Z"
}
```

Notes on the fields:

- **One registration, several packs.** Each pack size has its own price and its own item;
  they share the `registrationNumber`.
- **Company and licence.** `licenceType` is `DML` (Drug Manufacturing Licence, local
  manufacturers) or `DSL` (Drug Sale Licence, importers and distributors); `licenceNo` keeps
  leading zeros and DSL formats such as `017/DSL(D)/PS&DC-ICT/2025`.
- **Composition** is the line the index prints under the product name. It is `null` when
  that line is blank (common for older entries) or only repeats the product name.
- **sourceUrl** is the list page the pack was read from. Searches and company lists are
  answers to a form the site accepts only as a POST, so for those it is the index page,
  where the same search can be repeated.

### Pricing

Pay per event:

| Event          | Charged for                             |
| -------------- | --------------------------------------- |
| `price-record` | Each priced pack stored in the dataset. |

Apify's standard run-start event covers starting the actor. Packs 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 pack.

### Data source and politeness

- **Source:** DRAP's public PharmaPrice Index, the server-rendered pages a browser sees:
  `GET https://e.dra.gov.pk/public/price` (20 packs per page, `?page=N`, `?category=`), its
  search form (`POST /public/price/find`) and its company filter (`POST /public/price`,
  one page per registration holder). The forms carry the page's own session token, as a
  browser sends it. No login, no captcha.
- **robots.txt** (checked 2026-09-26) allows every user agent and path and sets no crawl
  delay. The actor still
  - waits **at least 1 second** after each request ends before the next one starts
    (retries and session renewals included; a constant, not an input),
  - uses **one connection**, one request at a time,
  - identifies itself honestly as `pk-drap-actor/0.1 (+https://apify.com/a-g-d/pk-drap)`,
  - reads only the list pages it needs: a 20-pack run makes 3 requests.
- **Measured on 2026-09-26:** about 14 KB per page on the wire (gzip), about 2 seconds per
  page including the pause. 20 packs took 6 s, 200 packs 25 s (12 requests); the default
  300-second run timeout covers about 2,000 packs.
- **Resilience:** connection errors, timeouts, HTTP 5xx and 429, and pages that do not
  contain the price table are retried with exponential backoff and jitter inside a run-wide
  budget (90 s of backoff), well inside the default timeout. If the site sends a form back
  (an expired session), the actor starts a fresh session once and retries; a second
  refusal stops the run with a clear message.
- **Terms:** the site links no terms of use; its footer reads "© 2026 Drug Regulatory
  Authority Pakistan. All rights reserved." The prices are published by DRAP for the public.
  Check DRAP's terms for your own use of the data.

### Data and privacy

The index publishes product and company data: registered medicines, the companies that hold
the registrations and their licence numbers, and prices. It contains no personal data, and
the actor outputs only the fields listed above; the office addresses and phone numbers in
the site's footer are not collected.

### Limitations

- **No ingredient search.** The site searches product names and registration numbers only
  (see [Input](#input)).
- **Effective-date filtering reads the list.** See
  [Prices effective since a date](#prices-effective-since-a-date).
- **Derived fields.** `strength` and `dosageForm` come from the product name by pattern
  matching: the first strength stated, and the first dosage form named. Names that state
  neither give `null`; check `composition` for the full formula.
- **No detail pages.** The index has no per-product page, so there is no detail link.
- **A run is a snapshot.** If DRAP adds packs while a long run pages through the list, the
  actor skips packs it has already stored (`duplicates` in the run log); additions made
  mid-run belong to the next run.
- **The registered-product database is not covered.** DRAP's product registration search
  (eapp.dra.gov.pk) refused requests (HTTP 403) from the network this actor was built on;
  this actor covers the price index only.

# Changelog

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

# Actor input Schema

## `search` (type: `string`):

Product name or registration number contains this text, e.g. "panadol" or "augmentin" (the site's own search). It does not search the composition line: an ingredient is found only where the product name states it, e.g. "paracetamol" finds "Nuberol-P Forte Suspension (Paracetamol)". Leave empty for all.

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

Every priced pack of one DRAP registration, e.g. "137272" (leading zeros optional). Leave empty for all.

## `company` (type: `string`):

Registration holder (manufacturer or importer): part of its name, e.g. "searle", or its licence number, e.g. "000016" or "DML 000016". Leave empty for all.

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

The index's price category. Leave on "Any category" for both.

## `effectiveSince` (type: `string`):

Only prices that took effect on or after this date (YYYY-MM-DD). The site cannot filter or sort by this date, so the actor checks every pack it reads: with no other filter, the newest-listed packs come first, and a check of the whole index (1,076 pages) takes about 40 minutes, so raise the run timeout for that, or combine the date with a search, company or category.

## `order` (type: `string`):

The site lists packs in the order DRAP added them to the index and has no sort control. "Newest listed first" reads that list from its end, so recent additions come first.

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

Stop after storing this many priced packs. The site shows 20 packs per page and the actor reads a page about every 2 seconds, so the default 300 s run timeout covers about 2,000 packs; raise the timeout for more.

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

Optional. Use Apify Proxy if e.dra.gov.pk is unreachable from Apify's network.

## Actor input object example

```json
{
  "search": "",
  "registrationNumber": "",
  "company": "",
  "category": "",
  "effectiveSince": "",
  "order": "newest",
  "maxItems": 20,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

## `prices` (type: `string`):

One item per priced pack matching the input, newest listed first by default: product name, composition, strength and dosage form, registration number, company and its DML/DSL licence, category, pack size, maximum retail price in PKR (number and as published), the date it took effect, the source page and the fetch time.

# 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/pk-drap").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/pk-drap").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/pk-drap --silent --output-dataset

```

## MCP server setup

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

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/Al1BSyp6JNCsdYM3I/builds/wKYCVe0NCSQUVDXpP/openapi.json
