# Mercadona Scraper - Products, Prices, EAN & Price Tracker (`opendata_es/mercadona-products-prices`) Actor

Full Mercadona catalog (~4,000 products) by postal code in seconds: price, price per kg/L, Hacendado flag, price drops, new arrivals, EAN, brand, suppliers, ingredients, allergens and price changes between runs. No proxies or browser.

- **URL**: https://apify.com/opendata_es/mercadona-products-prices.md
- **Developed by:** [c.d.s Studio](https://apify.com/opendata_es) (community)
- **Categories:** E-commerce, Lead generation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per event

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

## Mercadona Scraper – Products, Prices, EAN & Price History

Scrape the **full Mercadona online catalog** (about **4,000 products**) in **~15 seconds**, for **any Spanish postal code**. Get prices, **price per kg / litre**, packaging, categories, **Hacendado** (private label) flag, price drops and new arrivals – and optionally the **EAN barcode, brand, origin, suppliers, ingredients and allergens** of every product.

Run it daily and it **tracks price changes** for you: every product gets the price of the previous run, the change in EUR and %, and a webhook can ping Slack / Zapier / Make / n8n when prices move.

> *Extrae el catálogo completo de Mercadona (supermercado online) por código postal: precios, precio por kilo/litro, marca Hacendado, bajadas de precio, novedades, EAN, proveedores, ingredientes y alérgenos, con histórico de precios.*

### Why this Mercadona scraper?

- ⚡ **Fast and light** – talks to the same JSON API as tienda.mercadona.es. No browser, no proxies, no login. A full catalog costs a fraction of a compute unit.
- 📍 **Real regional prices** – each postal code is mapped to the warehouse that serves it. Prices and assortment differ between Madrid, Barcelona, Valencia, Sevilla, the Balearic and the **Canary Islands** (no VAT there!). Pass several postal codes in one run to compare regions.
- 🏷️ **EAN + suppliers** – find out **who manufactures each Hacendado / Deliplus / Bosque Verde product**, get the barcode to match against other retailers, and read ingredients and allergens.
- 📉 **Price tracking built in** – no database needed on your side: the actor remembers the previous prices and flags `priceChange`, `priceChangePct`, `newSinceLastRun`. Turn on *Output only changed or new products* for a tiny daily diff.
- 💸 **Cheap, transparent pay-per-event pricing** – you only pay for the products you get.

### Use cases

- **Grocery price monitoring & inflation tracking** (IPC de la cesta de la compra).
- **Competitor price intelligence** for retailers, brands and FMCG suppliers.
- **Price comparison apps** (Mercadona vs Carrefour vs Dia vs Lidl) matched by EAN.
- **Nutrition / allergen apps** and recipe costing.
- **Private-label research**: which supplier makes each Hacendado product.
- **Academic research and journalism** on food prices in Spain.

### Input

| Field | Description |
|---|---|
| `postalCodes` | Spanish postal codes (default `28001`, Madrid). One warehouse per code. |
| `categories` | Category names or ids, accent-insensitive (`Lácteos`, `Aceite`, `Fruta`, `Bebidas`…). Empty = full catalog. |
| `searchTerms` | Keep products whose name contains any of these words. |
| `brands` | Keep only these brands (`Hacendado`, `Deliplus`, `Coca-Cola`…). |
| `onlyPriceDrops` / `onlyNewArrivals` | Keep only products Mercadona flags as cheaper / new. |
| `includeDetails` | Add EAN, brand, origin, suppliers, ingredients, allergens, photos. |
| `trackPriceChanges` | Compare with the previous run (default on). |
| `outputOnlyPriceChanges` | Return only products whose price changed or are new. |
| `alertWebhookUrl` | Receive a JSON POST with the price changes. |

#### Example input – olive oil in Madrid and the Canary Islands, with EAN

```json
{
  "postalCodes": ["28001", "35012"],
  "searchTerms": ["aceite de oliva"],
  "includeDetails": true
}
```

#### Example input – daily price-change monitor for the whole catalog

```json
{
  "postalCodes": ["08001"],
  "trackPriceChanges": true,
  "outputOnlyPriceChanges": true,
  "alertWebhookUrl": "https://hooks.zapier.com/hooks/catch/123/abc"
}
```

### Output

One item per product (and warehouse):

```json
{
  "productId": "4241",
  "name": "Aceite de oliva 0,4º Hacendado",
  "packaging": "Garrafa",
  "price": 17.25,
  "referencePrice": 3.45,
  "referenceFormat": "L",
  "unitSize": 5.0,
  "sizeFormat": "l",
  "priceDecreased": false,
  "isNewArrival": false,
  "isHacendado": true,
  "category": "Aceite, especias y salsas",
  "subcategory": "Aceite, vinagre y sal",
  "section": "Aceite de oliva",
  "warehouse": "mad3",
  "postalCode": "28001",
  "lastRunPrice": 17.95,
  "priceChange": -0.7,
  "priceChangePct": -3.9,
  "newSinceLastRun": false,
  "ean": "8402001027482",
  "brand": "Hacendado",
  "origin": "España",
  "suppliers": ["Aceites del Sur- Coosur S.A.", "SOVENA ESPAÑA S.A.U."],
  "ingredients": "Ingredientes: Aceite de oliva refinado y Aceite de Oliva Virgen Extra",
  "url": "https://tienda.mercadona.es/product/4241/aceite-oliva-04o-hacendado-garrafa",
  "image": "https://prod-mercadona.imgix.net/images/....jpg",
  "currency": "EUR",
  "scrapedAt": "2026-10-21T07:00:12+00:00"
}
```

The run summary (key-value store record `OUTPUT`) contains, per warehouse: number of products, Hacendado share, price drops, new arrivals, min / max / average price, products by category and price changes since the previous run.

A cumulative dataset named **`mercadona-price-history`** in your account stores `date, warehouse, productId, price, referencePrice` for every run, so you get a ready-made price history time series.

### Pricing (pay per event)

| Event | Price |
|---|---|
| Actor start | $0.005 per run |
| Product result | $0.0004 per product → **full catalog ≈ $1.6** |
| Product detail (EAN, suppliers, ingredients) | $0.0006 per product |
| Price change detected | $0.001 per changed product |

Tip: a daily monitor with *Output only changed or new products* typically costs a few cents per day.

### Scheduling

Create a **Schedule** in Apify (e.g. every day at 07:00) with your postal codes. The price memory is kept per warehouse in the key-value store `mercadona-price-history` of your account.

### FAQ

**Is it legal?** The actor reads publicly available product and price information from Mercadona's public online store, without logging in, at a polite request rate. It collects no personal data. Make sure your use complies with Mercadona's terms and applicable law.

**Which areas are covered?** Every postal code where Mercadona delivers online (Peninsula, Balearic and Canary Islands). Postal codes without online delivery are skipped with a warning.

**Why do prices differ between postal codes?** Mercadona prices by warehouse; taxes also differ (IGIC in the Canary Islands instead of IVA).

**Does it need proxies?** No.

### Related actors

- [Spain Fuel Prices](https://apify.com/opendata_es/spain-fuel-prices) – every petrol station in Spain with daily prices.
- [Spain Public Tenders](https://apify.com/opendata_es/spain-public-tenders) – public procurement in Spain.
- [Spain Grants BDNS](https://apify.com/opendata_es/spain-grants-bdns) – grants and subsidies in Spain.

Keywords: mercadona scraper, mercadona api, mercadona prices, precios mercadona, supermercado scraper, grocery prices spain, hacendado, EAN, price tracker, price monitoring.

# Actor input Schema

## `postalCodes` (type: `array`):

Spanish postal codes. Each one is mapped to the Mercadona warehouse that serves it (prices and assortment change by region, e.g. the Canary Islands). Leave empty for Madrid (28001).

## `warehouses` (type: `array`):

Optional Mercadona warehouse codes (e.g. mad1, bcn1, vlc1, svq1) if you already know them. Used in addition to postal codes.

## `categories` (type: `array`):

Only scrape these categories. Accepts category ids or Spanish names, accent-insensitive (e.g. 'Lácteos', 'Aceite', 'Fruta', 'Bebidas', 'Limpieza'). Empty = full catalog.

## `searchTerms` (type: `array`):

Keep only products whose name contains any of these words (e.g. 'leche', 'aceite de oliva', 'café').

## `brands` (type: `array`):

Keep only products of these brands (e.g. 'Hacendado', 'Deliplus', 'Bosque Verde', 'Coca-Cola').

## `onlyPriceDrops` (type: `boolean`):

Keep only products that Mercadona flags as 'price decreased'.

## `onlyNewArrivals` (type: `boolean`):

Keep only products flagged as new in the store.

## `includeDetails` (type: `boolean`):

Fetch each product page: EAN barcode, brand, origin, legal name, suppliers (who manufactures Hacendado), ingredients, allergens and full-size photos. One extra request per product.

## `maxDetails` (type: `integer`):

Cap on detail pages per warehouse (0 = all returned products).

## `trackPriceChanges` (type: `boolean`):

Remember the prices of this run (per warehouse) and flag price changes, new and removed products on the next run. Schedule the actor daily to build a price history.

## `outputOnlyPriceChanges` (type: `boolean`):

With price tracking on, return only products whose price changed or that are new since the previous run. Ideal for daily monitoring.

## `alertWebhookUrl` (type: `string`):

Optional URL that receives a JSON POST with the price changes of the run (Slack, Zapier, Make, n8n...).

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

0 = no limit.

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

Apify datacenter proxy is enough (the store throttles bursts from cloud IPs; the actor retries and rotates sessions).

## `concurrency` (type: `integer`):

Parallel requests to the store API (1-10).

## Actor input object example

```json
{
  "postalCodes": [
    "28001"
  ],
  "onlyPriceDrops": false,
  "onlyNewArrivals": false,
  "includeDetails": false,
  "maxDetails": 0,
  "trackPriceChanges": true,
  "outputOnlyPriceChanges": false,
  "maxItems": 0,
  "proxyConfiguration": {
    "useApifyProxy": true
  },
  "concurrency": 3
}
```

# Actor output Schema

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

Every product of this run: id, name, price, price per kg/L, packaging, category, Hacendado flag, price drop and new flags, price change vs previous run, link and image (plus EAN, brand, suppliers and ingredients when details are on).

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

Per warehouse: products, Hacendado share, price drops, new arrivals, min/max/avg price, products by category and price changes since the previous run.

# 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 = {
    "postalCodes": [
        "28001"
    ],
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("opendata_es/mercadona-products-prices").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 = {
    "postalCodes": ["28001"],
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("opendata_es/mercadona-products-prices").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 '{
  "postalCodes": [
    "28001"
  ],
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call opendata_es/mercadona-products-prices --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,opendata_es/mercadona-products-prices"
        }
    }
}
```

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/uwCAoJDp7NXZMawzE/builds/3SRYgiDihT6bNjJau/openapi.json
