# Pharmacy Price Comparison — European Pharmacy Prices (`studio-amba/pharmacy-price-comparison`) Actor

Compare pharmacy prices across Europe. Searches 12 online pharmacies in BE, NL, DE, AT, SE, DK simultaneously and groups results by EAN barcode. Find the cheapest option for any medicine or health product.

- **URL**: https://apify.com/studio-amba/pharmacy-price-comparison.md
- **Developed by:** [Studio Amba](https://apify.com/studio-amba) (community)
- **Categories:** E-commerce
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, NaN bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per usage

This Actor is paid per platform usage. The Actor is free to use, and you only pay for the Apify platform usage, which gets cheaper the higher subscription plan you have.

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

## What's an Apify Actor?

Actors are a software tools running on the Apify platform, for all kinds of web data extraction and automation use cases.
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.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp.md).

If your project is in a different language, use 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

## Pharmacy Price Comparison

Compare pharmacy product prices across 12 European online pharmacies in 6 countries (BE, NL, DE, AT, SE, DK) with a single API call.

### How to compare pharmacy prices across Europe

This actor searches multiple online pharmacies simultaneously and groups identical products by EAN barcode. You get a side-by-side price comparison showing which pharmacy offers the lowest price for any medicine, supplement, or health product.

Instead of manually visiting each pharmacy website, this actor does all the work: it runs 12 specialized pharmacy scrapers in parallel, collects their results, matches products by EAN code (or by fuzzy name matching as fallback), and outputs a unified comparison dataset.

### Why use this actor?

- **Save hours of manual comparison** — one search query, 12 pharmacies checked automatically
- **Find real savings** — price differences of 20-50% are common for identical products across pharmacies
- **Cross-border arbitrage** — compare prices in Belgium, Netherlands, Germany, Austria, Sweden, and Denmark
- **No login or cookies required** — all data comes from publicly available product listings
- **Automated monitoring** — schedule runs to track price changes over time

### Supported pharmacies

| Pharmacy | Country | Currency |
|----------|---------|----------|
| Farmaline | Belgium | EUR |
| Multipharma | Belgium | EUR |
| Kruidvat | Belgium / Netherlands | EUR |
| Apotheek | Belgium / Netherlands | EUR |
| Viata | Belgium | EUR |
| APONEO | Germany | EUR |
| Shop Apotheke | Germany / Austria | EUR |
| dm | Germany | EUR |
| Apoteket | Sweden | SEK |
| Apotea | Sweden | SEK |
| Apotekshjärtat | Sweden | SEK |
| Matas | Denmark | DKK |

### Input

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `searchQuery` | String | No | Product to search for (default: "paracetamol") |
| `countries` | Array | No | Country codes to include: BE, NL, DE, AT, SE, DK (default: all) |
| `maxItemsPerPharmacy` | Integer | No | Max products per pharmacy (default: 10) |
| `timeoutPerPharmacySecs` | Integer | No | Timeout per scraper in seconds (default: 120) |
| `proxyConfiguration` | Object | No | Proxy settings passed to underlying scrapers |

### Output

Each result is a product comparison showing the price at every pharmacy where it was found:

| Field | Type | Example |
|-------|------|---------|
| `productName` | String | `"Paracetamol 500mg 20 tablets"` |
| `ean` | String | `"5412345678901"` |
| `lowestPrice` | Number | `2.99` |
| `highestPrice` | Number | `4.49` |
| `priceDifference` | String | `"50.2%"` |
| `pharmacyCount` | Number | `4` |
| `prices` | Array | Price at each pharmacy (see below) |
| `scrapedAt` | String | ISO 8601 timestamp |

Each entry in the `prices` array contains:

| Field | Type | Description |
|-------|------|-------------|
| `pharmacy` | String | Pharmacy name |
| `country` | String | Country code (BE, NL, DE, etc.) |
| `price` | Number | Current selling price |
| `currency` | String | Currency code (EUR, SEK, DKK) |
| `url` | String | Direct link to the product page |
| `inStock` | Boolean | Whether the product is available |
| `originalPrice` | Number | Price before discount (if applicable) |

The last item in the dataset is a `__SUMMARY__` record with run metadata: `pharmaciesQueried`, `pharmaciesFailed`, `totalComparisons`, and `multiPharmacyMatches`.

### Example output

```json
{
    "productName": "Paracetamol EG 500mg 20 Tabletten",
    "ean": "5420036901234",
    "prices": [
        {
            "pharmacy": "Multipharma",
            "country": "BE",
            "price": 2.49,
            "currency": "EUR",
            "url": "https://www.multipharma.be/...",
            "inStock": true
        },
        {
            "pharmacy": "Farmaline",
            "country": "BE",
            "price": 2.99,
            "currency": "EUR",
            "url": "https://www.farmaline.be/...",
            "inStock": true
        },
        {
            "pharmacy": "Kruidvat BE",
            "country": "BE",
            "price": 3.49,
            "currency": "EUR",
            "url": "https://www.kruidvat.be/...",
            "inStock": true
        }
    ],
    "lowestPrice": 2.49,
    "highestPrice": 3.49,
    "priceDifference": "40.2%",
    "pharmacyCount": 3,
    "scrapedAt": "2026-06-07T10:30:00.000Z"
}
````

### How product matching works

Products are matched across pharmacies using two methods:

1. **EAN barcode match (primary)** — When pharmacies provide EAN/GTIN barcodes, products with the same EAN are grouped together. This is the most reliable method and guarantees exact product matches.

2. **Fuzzy name matching (fallback)** — When no EAN is available, the actor uses word-overlap similarity to group products with similar names. A Jaccard similarity threshold of 55% is used to avoid false matches.

Results are sorted with multi-pharmacy matches first (most valuable comparisons), then by pharmacy count descending.

### How it works technically

This is a **meta-actor** — it does not scrape pharmacy websites directly. Instead, it orchestrates 12 specialized pharmacy scrapers that are each optimized for their target site. The workflow:

1. Receives your search query and country filters
2. Starts the relevant pharmacy scrapers in parallel via the Apify API
3. Waits for all scrapers to finish (with configurable timeout)
4. Collects and normalizes results from each scraper's dataset
5. Groups identical products by EAN barcode
6. Applies fuzzy name matching for products without EAN codes
7. Calculates price comparisons and outputs unified results

If any pharmacy scraper fails or times out, the actor continues with results from the remaining pharmacies.

### Cost estimate

This actor runs multiple sub-actors, so costs depend on how many pharmacies are queried:

- **All 12 pharmacies, 10 items each** — approximately 0.5-1.0 compute units per run
- **Single country (e.g., BE only)** — approximately 0.1-0.3 compute units per run

The main cost driver is the number of pharmacies queried and the `maxItemsPerPharmacy` setting. Keep `maxItemsPerPharmacy` at 10-20 for cost-effective comparison runs.

### Tips for best results

- Use **generic product names** like "paracetamol", "ibuprofen 400mg", or "vitamine D" for the broadest matches
- **Filter by country** if you only care about local prices — this saves compute and speeds up results
- Set `maxItemsPerPharmacy` to **5-10** for quick price checks, or **20-50** for comprehensive comparisons
- **Schedule weekly runs** to monitor price changes over time
- The `priceDifference` field makes it easy to spot products with the biggest savings potential

### Limitations

- Products can only be matched across pharmacies when they share an EAN barcode or have very similar names
- Currency conversion is not performed — EUR, SEK, and DKK prices are shown as-is
- Some pharmacies may not return results for certain search terms due to language differences
- Prescription-only medicines may not be available on all pharmacy websites
- The actor's cost scales with the number of pharmacies queried (each is a separate Apify run)
- If an underlying pharmacy scraper is temporarily broken, that pharmacy will be marked as failed and results from other pharmacies are still returned

# Actor input Schema

## `searchQuery` (type: `string`):

Product to search for across all pharmacies (e.g., 'paracetamol 500mg', 'ibuprofen', 'vitamine D'). Use the common product name in English or the local language.

## `countries` (type: `array`):

Filter which countries to include. Leave empty to search all available pharmacies (BE, NL, DE, AT, SE, DK).

## `maxItemsPerPharmacy` (type: `integer`):

Maximum number of products to fetch from each pharmacy. Higher values give more matches but take longer and cost more.

## `timeoutPerPharmacySecs` (type: `integer`):

Maximum time to wait for each pharmacy scraper to finish. Pharmacies that take longer will be skipped.

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

Proxy settings passed to the underlying pharmacy scrapers. Residential proxies recommended for reliable results.

## Actor input object example

```json
{
  "searchQuery": "paracetamol",
  "maxItemsPerPharmacy": 10,
  "timeoutPerPharmacySecs": 120,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "BE"
  }
}
```

# 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 = {
    "searchQuery": "paracetamol",
    "maxItemsPerPharmacy": 10,
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ],
        "apifyProxyCountry": "BE"
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("studio-amba/pharmacy-price-comparison").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 = {
    "searchQuery": "paracetamol",
    "maxItemsPerPharmacy": 10,
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
        "apifyProxyCountry": "BE",
    },
}

# Run the Actor and wait for it to finish
run = client.actor("studio-amba/pharmacy-price-comparison").call(run_input=run_input)

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

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

```

## CLI example

```bash
echo '{
  "searchQuery": "paracetamol",
  "maxItemsPerPharmacy": 10,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "BE"
  }
}' |
apify call studio-amba/pharmacy-price-comparison --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=studio-amba/pharmacy-price-comparison",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "Pharmacy Price Comparison — European Pharmacy Prices",
        "description": "Compare pharmacy prices across Europe. Searches 12 online pharmacies in BE, NL, DE, AT, SE, DK simultaneously and groups results by EAN barcode. Find the cheapest option for any medicine or health product.",
        "version": "0.1",
        "x-build-id": "G8T3c51Td8TelyFHL"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/studio-amba~pharmacy-price-comparison/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-studio-amba-pharmacy-price-comparison",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/acts/studio-amba~pharmacy-price-comparison/runs": {
            "post": {
                "operationId": "runs-sync-studio-amba-pharmacy-price-comparison",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor and returns information about the initiated run in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/runsResponseSchema"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/acts/studio-amba~pharmacy-price-comparison/run-sync": {
            "post": {
                "operationId": "run-sync-studio-amba-pharmacy-price-comparison",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "inputSchema": {
                "type": "object",
                "properties": {
                    "searchQuery": {
                        "title": "Search Query",
                        "type": "string",
                        "description": "Product to search for across all pharmacies (e.g., 'paracetamol 500mg', 'ibuprofen', 'vitamine D'). Use the common product name in English or the local language."
                    },
                    "countries": {
                        "title": "Countries",
                        "type": "array",
                        "description": "Filter which countries to include. Leave empty to search all available pharmacies (BE, NL, DE, AT, SE, DK).",
                        "items": {
                            "type": "string"
                        }
                    },
                    "maxItemsPerPharmacy": {
                        "title": "Max Items Per Pharmacy",
                        "minimum": 1,
                        "maximum": 100,
                        "type": "integer",
                        "description": "Maximum number of products to fetch from each pharmacy. Higher values give more matches but take longer and cost more.",
                        "default": 10
                    },
                    "timeoutPerPharmacySecs": {
                        "title": "Timeout Per Pharmacy (seconds)",
                        "minimum": 30,
                        "maximum": 600,
                        "type": "integer",
                        "description": "Maximum time to wait for each pharmacy scraper to finish. Pharmacies that take longer will be skipped.",
                        "default": 120
                    },
                    "proxyConfiguration": {
                        "title": "Proxy Configuration",
                        "type": "object",
                        "description": "Proxy settings passed to the underlying pharmacy scrapers. Residential proxies recommended for reliable results."
                    }
                }
            },
            "runsResponseSchema": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            },
                            "actId": {
                                "type": "string"
                            },
                            "userId": {
                                "type": "string"
                            },
                            "startedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "finishedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "status": {
                                "type": "string",
                                "example": "READY"
                            },
                            "meta": {
                                "type": "object",
                                "properties": {
                                    "origin": {
                                        "type": "string",
                                        "example": "API"
                                    },
                                    "userAgent": {
                                        "type": "string"
                                    }
                                }
                            },
                            "stats": {
                                "type": "object",
                                "properties": {
                                    "inputBodyLen": {
                                        "type": "integer",
                                        "example": 2000
                                    },
                                    "rebootCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "restartCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "resurrectCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "computeUnits": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "options": {
                                "type": "object",
                                "properties": {
                                    "build": {
                                        "type": "string",
                                        "example": "latest"
                                    },
                                    "timeoutSecs": {
                                        "type": "integer",
                                        "example": 300
                                    },
                                    "memoryMbytes": {
                                        "type": "integer",
                                        "example": 1024
                                    },
                                    "diskMbytes": {
                                        "type": "integer",
                                        "example": 2048
                                    }
                                }
                            },
                            "buildId": {
                                "type": "string"
                            },
                            "defaultKeyValueStoreId": {
                                "type": "string"
                            },
                            "defaultDatasetId": {
                                "type": "string"
                            },
                            "defaultRequestQueueId": {
                                "type": "string"
                            },
                            "buildNumber": {
                                "type": "string",
                                "example": "1.0.0"
                            },
                            "containerUrl": {
                                "type": "string"
                            },
                            "usage": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "usageTotalUsd": {
                                "type": "number",
                                "example": 0.00005
                            },
                            "usageUsd": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "number",
                                        "example": 0.00005
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
