# European Price Comparison - Compare Prices Across EU Engines (`studio-amba/european-price-comparison`) Actor

Search 10 European price-comparison engines at once and compare prices for any product. Groups by EAN barcode, converts to EUR. No login or cookies required.

- **URL**: https://apify.com/studio-amba/european-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, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.00 / 1,000 result scrapeds

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/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

## European Price Comparison

Compare product prices across ten European price-comparison engines in a single run. This actor searches each engine in parallel, groups the results by EAN/GTIN barcode (with a fuzzy product-name fallback), and converts every price to EUR using live ECB rates so you can see the cheapest source across borders.

No login. No cookies. No account. You give it a product, it gives you a side-by-side comparison.

### What it does

- Searches 10 European price engines at once: Akakçe (TR), Cimri (TR), Ceneo (PL), Compari (RO), Geizhals (AT), Heureka (CZ), Kelkoo (FR), Pazaruvaj (BG), PriceRunner (SE), Zboží (CZ).
- Matches the same product across engines by EAN barcode, then falls back to fuzzy name matching when no barcode is present.
- Converts all prices to EUR with live European Central Bank rates, so a Turkish lira price and a Polish złoty price are directly comparable.
- Returns the lowest price, highest price, and the percentage spread for each matched product.
- Sorts results so products found in the most engines appear first.

### How to scrape European price comparison data

1. Enter a product in the **Search Query** field. Use the brand and model for the best cross-engine matching, for example `iphone 15`, `sony wh-1000xm5`, or `dyson v15`.
2. Optionally restrict the run to certain countries with the **Countries** field (for example `["AT", "CZ"]`). Leave it empty to query every engine.
3. Set **Max Items Per Source** to control how many products are pulled from each engine. More items means more potential matches but a longer, costlier run.
4. Run the actor. Each engine is queried in parallel, the results are grouped by EAN, and prices are converted to EUR.
5. Open the dataset. Each row is one product with the prices found at every engine that carries it.

### Input

| Field | Type | Description |
|-------|------|-------------|
| `searchQuery` | string | Product to search for across all engines. Defaults to `iphone 15`. |
| `countries` | array | Optional country filter (`TR`, `PL`, `RO`, `AT`, `CZ`, `FR`, `BG`, `SE`). Empty means all. |
| `maxItemsPerSource` | integer | Max products to fetch from each engine (1–100, default 10). |
| `timeoutPerSourceSecs` | integer | Max seconds to wait for each engine (30–600, default 120). |
| `proxyConfiguration` | object | Proxy settings passed to the underlying scrapers. Residential recommended. |

#### Example input

```json
{
    "searchQuery": "sony wh-1000xm5",
    "countries": ["AT", "CZ", "PL"],
    "maxItemsPerSource": 10,
    "proxyConfiguration": { "useApifyProxy": true, "apifyProxyGroups": ["RESIDENTIAL"] }
}
```

### Output

Each item in the dataset is one matched product:

```json
{
    "productName": "Sony WH-1000XM5 Wireless Headphones",
    "ean": "4548736141537",
    "lowestPriceEur": 289.0,
    "highestPriceEur": 349.99,
    "priceDifference": "21.1%",
    "sourceCount": 4,
    "prices": [
        { "source": "Geizhals", "country": "AT", "price": 289.0, "currency": "EUR", "priceEur": 289.0, "url": "https://...", "inStock": true },
        { "source": "Heureka", "country": "CZ", "price": 7290, "currency": "CZK", "priceEur": 291.6, "url": "https://...", "inStock": true }
    ],
    "scrapedAt": "2026-06-15T18:00:00.000Z"
}
```

| Field | Description |
|-------|-------------|
| `productName` | Canonical product name from the most detailed source. |
| `ean` | EAN/GTIN barcode used for matching, or `null` if name-matched. |
| `lowestPriceEur` | Lowest price across all sources, in EUR. |
| `highestPriceEur` | Highest price across all sources, in EUR. |
| `priceDifference` | Percentage spread between highest and lowest EUR price. |
| `sourceCount` | How many engines carry this product. |
| `prices` | Per-source price entries with native currency and EUR conversion. |
| `scrapedAt` | ISO 8601 timestamp of the comparison. |

A final `__SUMMARY__` item lists which sources answered, which failed, and the total number of comparisons.

### How matching works

Products are grouped first by EAN/GTIN barcode, which is an exact identifier and the most reliable signal. Products without a barcode are matched to existing groups by name similarity (Jaccard word overlap, threshold 0.6) and otherwise start a new group. This keeps false merges low while still consolidating items that lack barcodes.

### Currency conversion

Prices arrive in each engine's local currency. The actor fetches live EUR reference rates from the European Central Bank at the start of every run and converts each price to EUR for comparison. If the rate service is unreachable, it falls back to a built-in rate table so the run still completes. Native price and currency are always preserved alongside the EUR value.

### Use cases

- Cross-border price monitoring for electronics and consumer goods.
- Finding the cheapest EU source for a specific product before buying.
- Feeding a price-intelligence dashboard with normalized, EUR-denominated data.
- Spotting arbitrage between countries where the same product sells at very different prices.

### Notes

- This is a meta-actor. It orchestrates our individual country price-engine scrapers and runs them in parallel, so a single run can touch many sites at once.
- Results depend on each underlying engine carrying the product and returning it for your query. Generic queries match more broadly; specific brand+model queries match more accurately.
- Use residential proxies for the most reliable results, since some engines are sensitive to datacenter traffic.

# Actor input Schema

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

Product to search for across all price engines (e.g., 'iphone 15', 'sony wh-1000xm5', 'dyson v15'). Use the brand and model for best matching.

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

Filter which countries to include. Leave empty to search all available engines (TR, PL, RO, AT, CZ, FR, BG, SE).

## `maxItemsPerSource` (type: `integer`):

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

## `timeoutPerSourceSecs` (type: `integer`):

Maximum time to wait for each underlying scraper to finish. Sources that take longer are skipped.

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

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

## Actor input object example

```json
{
  "searchQuery": "iphone 15",
  "maxItemsPerSource": 10,
  "timeoutPerSourceSecs": 120,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}
```

# 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": "iphone 15",
    "maxItemsPerSource": 10,
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ]
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("studio-amba/european-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": "iphone 15",
    "maxItemsPerSource": 10,
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
    },
}

# Run the Actor and wait for it to finish
run = client.actor("studio-amba/european-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": "iphone 15",
  "maxItemsPerSource": 10,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}' |
apify call studio-amba/european-price-comparison --silent --output-dataset

```

## MCP server setup

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

```

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/3Q0ncATxzwYsgxF5J/builds/lpI03pYRpuumLFQjS/openapi.json
