# PharmacyChecker Scraper — Drug Price Offers (`muhammadafzal/pharmacychecker-scraper`) Actor

Scrape PharmacyChecker drug price offers with pharmacy, strength, quantity, unit price, total price, shipping fees, and accreditation links.

- **URL**: https://apify.com/muhammadafzal/pharmacychecker-scraper.md
- **Developed by:** [Muhammad Afzal](https://apify.com/muhammadafzal) (community)
- **Categories:** E-commerce, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $10.00 / 1,000 pharmacychecker price offers

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

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

## PharmacyChecker Scraper — Drug Price Offers

Extract public international prescription-drug price offers from PharmacyChecker into a clean dataset for medication cost research, price monitoring, pharmacy comparison, and AI-agent workflows. Each result represents one visible offer—not a page dump—and includes the drug and strength, accredited pharmacy profile, package quantity, unit and total prices, shipping terms, and source URL.

This Actor is designed for researchers, patient-support organizations, health-cost analysts, and developers who need structured public pricing data. It does not buy medication, submit a prescription, click affiliate checkout links, scrape authenticated areas, or provide medical advice.

### What data can I extract from PharmacyChecker?

| Field group | Included data |
| --- | --- |
| Medication | Drug name, related generic name, brand/generic flag, strength, formulation |
| Pharmacy | Displayed pharmacy name and domain, PharmacyChecker profile URL, Tier 1 marker |
| Price | Unit price, price unit, package quantity, total package price, USD currency |
| Shipping | Parsed standard shipping cost, destination scope, displayed origin countries, shipping notes |
| Provenance | Page rank, stable offer ID, lowest-unit-price flag, exact source URL, scrape timestamp |

The dataset contains only international online-pharmacy price offers shown on public PharmacyChecker drug pages. It intentionally excludes local U.S. coupon searches that require a ZIP code, private APIs, patient data, editorial articles, and unrelated page content.

### When should I use this PharmacyChecker Scraper?

Use it to compare international mail-order package prices, watch public price changes for a shortlist of medications, create structured inputs for an affordability analysis, or give an AI agent a predictable list of current offers. Do not use it as a substitute for PharmacyChecker's own verification portal, a clinician, a pharmacist, or legal advice about prescription importation.

PharmacyChecker states that price information can be submitted by participating pharmacies and updated over time. Treat every record as a point-in-time observation. Open `sourceUrl` and `pharmacyProfileUrl` before making a consequential decision.

### Input

The default run searches `Eliquis`, sorts by unit price, and returns at most 25 offers. The Console prefill lowers that to 10 offers for a quick test.

```json
{
  "drugNames": ["Eliquis", "Synthroid"],
  "strength": "",
  "sortBy": "unitPrice",
  "maxResults": 25,
  "maxConcurrency": 1,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": ["RESIDENTIAL"],
    "apifyProxyCountry": "US"
  }
}
```

For an exact strength, either set one strength for all `drugNames` or provide exact public pages:

```json
{
  "startUrls": [
    { "url": "https://www.pharmacychecker.com/eliquis/5+mg/" },
    { "url": "https://www.pharmacychecker.com/synthroid/100+mcg/" }
  ],
  "sortBy": "totalPrice",
  "maxResults": 50
}
```

When `startUrls` is non-empty it replaces `drugNames` and `strength`. Only public `https://www.pharmacychecker.com/{drug}/` and `/{strength}/` pages are accepted. Unsupported or external URLs are ignored with a warning; a run with no usable inputs exits cleanly without result charges.

### Output

One dataset item is one public international pharmacy offer:

```json
{
  "offerId": "0b17e465bb1ae1de9c73b03e",
  "rank": 1,
  "drugName": "Eliquis",
  "genericName": "apixaban",
  "drugType": "brand",
  "strength": "5 mg",
  "formulation": "tablet",
  "pharmacyName": "CanadianPrescriptionDrugstore.com",
  "pharmacyDomain": "canadianprescriptiondrugstore.com",
  "pharmacyProfileUrl": "https://www.pharmacychecker.com/pharmacies/canadianprescriptiondrugstore.com/225/",
  "pharmacyCheckerAccredited": true,
  "tierOne": false,
  "priceCategory": "international-online-pharmacy",
  "unitPrice": 0.7,
  "unit": "tablet",
  "quantity": 180,
  "quantityUnit": "tablets",
  "totalPrice": 126,
  "currency": "USD",
  "shippingCost": 14.95,
  "shippingInfo": "Ships worldwide except Canada from India Standard shipping: $14.95 (Free for first order)",
  "shippingScope": "worldwide except Canada",
  "dispensingCountries": ["India"],
  "shippingNotes": ["Free shipping for first order"],
  "isLowestUnitPrice": true,
  "queryLabel": "Eliquis",
  "sourceUrl": "https://www.pharmacychecker.com/eliquis/5+mg/?sort=cost_per_unit",
  "scrapedAt": "2026-08-11T09:30:00.000Z"
}
```

Diagnostics never pollute the offer dataset. Read `SUMMARY` or `OUTPUT` from the run's default key-value store for page counts, warnings, billing parity, and the terminal classification: `SUCCEEDED`, `PARTIAL`, `EMPTY`, or `BLOCKED`.

### Pricing

The source defines one pay-per-event charge: **$0.01 per delivered `price-offer` record**. A result is normalized, schema-validated, deduplicated, and written through the SDK's dataset-and-event operation. Failed pages, blocked requests, invalid inputs, and empty searches do not create result events.

| Delivered offers | Result-event charge |
| ---: | ---: |
| 1 | $0.01 |
| 25 | $0.25 |
| 100 | $1.00 |
| 500 maximum | $5.00 |

`maxResults` is both an output and result-charge cap. The Actor announces the maximum possible result-event charge at run start and reports delivered/charged parity at the end. Apify's platform pricing configuration remains authoritative after deployment.

### Reliability and access limits

PharmacyChecker currently returns an AWS load-balancer 403 to plain cloud HTTP clients while a normal browser can render its public pages. For that reason this Actor uses Playwright, session-bound cookies and fingerprints, low concurrency, bounded retries, and an Apify residential U.S. proxy by default. Images, fonts, media, and stylesheets are blocked to reduce bandwidth without removing the HTML needed for extraction.

If every requested page is blocked before data is returned, the run fails honestly with a terminal explanation and zero result charges. If a valid page has no international offers, the run succeeds with an `EMPTY` warning. Partial valid data is preserved when another page fails. Retries, request rate, concurrency, output count, and billing are bounded.

The public site can change its markup, supported strengths, prices, shipping policies, or access controls without notice. A local fixture test proves parser behavior against the observed contract; it is not evidence of future cloud reliability. Run a private cloud canary and the documented multi-case matrix before publication.

### API and MCP usage

Run with the Apify JavaScript client:

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

const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('YOUR_USERNAME/pharmacychecker-scraper').call({
  drugNames: ['Eliquis'],
  maxResults: 10,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items);
```

For an MCP agent, select this Actor when the user asks for public PharmacyChecker international drug-price offers or accredited pharmacy comparisons. Do not select it for medical advice, local coupon redemption, pharmacy verification outside an offer page, prescription ordering, or private patient data. The return shape is a flat list of price-offer records and costs $0.01 per delivered item.

### Legal, medical, and responsible-use notice

Scrape only public data and follow PharmacyChecker's terms, applicable laws, and a respectful request rate. Prices and accreditation indicators are informational and can become stale. This Actor is not affiliated with PharmacyChecker.com LLC or any listed pharmacy. PharmacyChecker is a registered service mark of its owner.

Never use this dataset to diagnose, prescribe, replace a pharmacist, or determine whether importing a medication is lawful in a specific jurisdiction. Consult a licensed clinician or pharmacist for treatment decisions and qualified counsel or the relevant regulator for legal questions. A valid prescription may be required by the pharmacy and by law.

### FAQ

#### How many results can I scrape with PharmacyChecker Scraper?

Up to 500 offers per run. Set `maxResults` lower for predictable cost and shorter runs. The number actually returned depends on the public offers available for the requested pages.

#### Can I integrate PharmacyChecker Scraper with other apps?

Yes. Use Apify datasets, webhooks, schedules, Make, Zapier, or the API to move the flat JSON records into a database, spreadsheet, alert, or analysis workflow.

#### Can I use PharmacyChecker Scraper with the Apify API?

Yes. Call the Actor with drug names or exact public URLs, then read items from the run's default dataset and diagnostics from `SUMMARY`.

#### Can I use PharmacyChecker Scraper through an MCP Server?

Yes. Apify's MCP tooling can expose dataset-producing Actors to agents. The input and output descriptions are intentionally routable, bounded, and price-transparent.

#### Do I need proxies to scrape PharmacyChecker?

The observed cloud access path requires a browser and usually a residential proxy. The default input uses Apify Residential in the United States. Direct traffic may work from some networks but is not the advertised reliable path.

#### Is it legal to scrape PharmacyChecker data?

That depends on your jurisdiction, purpose, access method, and the site's current terms. This Actor accesses public pages only and does not bypass authentication, but you remain responsible for compliant use.

#### Your feedback

If a public PharmacyChecker page changes or a field is missing, share the run ID, redacted input, source URL, and final status message. Do not include patient, prescription, payment, or account data.

# Actor input Schema

## `drugNames` (type: `array`):

Use this for simple price research. Enter one public drug name per line, for example Eliquis or Synthroid. Ignored when startUrls is non-empty. Default: Eliquis; maximum 10 names.

## `startUrls` (type: `array`):

Use this for an exact drug or strength page, for example https://www.pharmacychecker.com/eliquis/5+mg/. Only public www.pharmacychecker.com drug-price URLs are accepted. When present, these URLs replace drugNames and strength.

## `strength` (type: `string`):

Use this only with drugNames when every requested drug should use the same strength. Enter a value such as 5 mg or 100 mcg. Leave blank to use each drug page's default strength. Ignored for startUrls.

## `sortBy` (type: `string`):

Use unitPrice to rank comparable per-tablet or per-unit prices, or totalPrice to rank package totals. Default: unitPrice. This changes PharmacyChecker's public result ordering, not the output fields.

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

Use this as the hard output and billing cap across all requested pages. Range 1–500; default 25. At $0.01 per delivered offer, the maximum result-event charge is maxResults × $0.01.

## `maxConcurrency` (type: `integer`):

Use this to limit simultaneous PharmacyChecker pages. Range 1–3; default 1. Lower concurrency is gentler and usually more reliable on this protected site.

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

PharmacyChecker blocks plain cloud HTTP traffic. Use an Apify residential proxy with a consistent U.S. session for the advertised path. The default uses Apify RESIDENTIAL in the US; custom proxy credentials are handled by Apify's standard proxy editor.

## Actor input object example

```json
{
  "drugNames": [
    "Eliquis"
  ],
  "startUrls": [],
  "strength": "",
  "sortBy": "unitPrice",
  "maxResults": 10,
  "maxConcurrency": 1,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "US"
  }
}
```

# Actor output Schema

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

Schema-valid public PharmacyChecker international pharmacy price offers.

## `summary` (type: `string`):

Final status, page counts, result and charge counts, warnings, and timestamps.

# 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 = {
    "drugNames": [
        "Eliquis"
    ],
    "startUrls": [],
    "strength": "",
    "sortBy": "unitPrice",
    "maxResults": 10,
    "maxConcurrency": 1,
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ],
        "apifyProxyCountry": "US"
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("muhammadafzal/pharmacychecker-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 = {
    "drugNames": ["Eliquis"],
    "startUrls": [],
    "strength": "",
    "sortBy": "unitPrice",
    "maxResults": 10,
    "maxConcurrency": 1,
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
        "apifyProxyCountry": "US",
    },
}

# Run the Actor and wait for it to finish
run = client.actor("muhammadafzal/pharmacychecker-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 '{
  "drugNames": [
    "Eliquis"
  ],
  "startUrls": [],
  "strength": "",
  "sortBy": "unitPrice",
  "maxResults": 10,
  "maxConcurrency": 1,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "US"
  }
}' |
apify call muhammadafzal/pharmacychecker-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,muhammadafzal/pharmacychecker-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/SUIGvft8f2xhvWDl7/builds/bJD5O8BndFkImR0aj/openapi.json
