# Mercadona Product Scraper — Spanish Supermarket Catalog (`memo23/mercadona-product-scraper`) Actor

Scrape the full Mercadona product catalog — name, price, packaging, category, image. JSON or CSV out.

- **URL**: https://apify.com/memo23/mercadona-product-scraper.md
- **Developed by:** [Muhamed Didovic](https://apify.com/memo23) (community)
- **Categories:** E-commerce
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $10.00 / 1,000 scraped items

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 Product Scraper — Spanish Supermarket Catalog

<p align="center"><img src="https://raw.githubusercontent.com/muhamed-didovic/muhamed-didovic.github.io/main/assets/mercadona-logo.png" width="140" alt="Mercadona Scraper"></p>

Scrape the full Mercadona product catalog, priced for any Spanish postal code. Name, price, price per kg or litre, previous price, packaging, full category path and image for every product, plus EAN barcode, brand, ingredients and allergens when you switch on product details.

***

### Why use this scraper

- **Local prices.** Enter a postal code and get the prices of the warehouse that delivers there. Fresh food prices differ between Madrid, Barcelona, Valencia and Sevilla.
- **Full catalog.** All 26 top categories and 152 subcategories, each product returned once even when Mercadona lists it in two places.
- **Comparable prices.** Price per kg or litre, the previous price when a product got cheaper, and the VAT rate, all as numbers.
- **Product details on demand.** EAN barcode, brand, origin, suppliers, ingredients, allergens and full-size photos.
- **No login.** Reads Mercadona's public online shop.

***

### Overview

Mercadona is Spain's largest supermarket chain. Its online shop (`tienda.mercadona.es`) serves each delivery area from a regional warehouse, and the warehouse sets the prices and the product range. This actor turns a postal code into that warehouse, walks every category, and writes one clean row per product.

***

### Use cases

- **Price monitoring.** Track Mercadona prices and price drops over time, per region.
- **Regional price comparison.** Run the same catalog for several postal codes and compare fresh food prices.
- **Product matching.** Use the EAN barcode to match Mercadona products against Carrefour, Dia, Lidl or Alcampo.
- **Nutrition and allergen apps.** Ingredients and allergen statements for every product.
- **Market research.** Mercadona's private labels (Hacendado, Deliplus, Bosque Verde) against branded products, category by category.

***

### How it works

1. If you gave a postal code, the actor asks Mercadona which warehouse delivers there.
2. It fetches the category tree, then every subcategory in parallel, using that warehouse's prices.
3. Products already seen in another subcategory are skipped.
4. With **Include product details** on, it fetches each product's detail page as well.
5. Each product is written to the dataset as one flat row.

***

### Input

| Field | Type | Default | Notes |
|---|---|---|---|
| `postalCode` | string | empty | Five-digit Spanish postal code, e.g. `28001`. Empty uses Mercadona's default warehouse (Valencia). |
| `includeDetails` | boolean | `false` | Adds EAN, brand, origin, suppliers, ingredients, allergens, instructions and photos. One extra request per product. |
| `maxItems` | integer | 1000 | Maximum products to return. |
| `maxConcurrency` | integer | 8 | How many requests run in parallel. |
| `proxy` | object | Apify proxy | Proxy configuration. |

```json
{
  "postalCode": "08001",
  "includeDetails": true,
  "maxItems": 5000
}
```

***

### Output

One row per product. Example from a Barcelona run (`08001`) with product details on:

```json
{
  "type": "product",
  "productId": "4240",
  "slug": "aceite-oliva-04o-hacendado-botella",
  "displayName": "Aceite de oliva 0,4º Hacendado",
  "packaging": "Botella",
  "unitPrice": 3.7,
  "bulkPrice": 3.7,
  "referencePrice": 3.7,
  "referenceFormat": "L",
  "previousUnitPrice": null,
  "priceDecreased": false,
  "currency": "EUR",
  "unitSize": 1,
  "sizeFormat": "l",
  "taxPercentage": 4,
  "isNewArrival": false,
  "purchaseLimit": 999,
  "requiresAgeCheck": false,
  "thumbnail": "https://prod-mercadona.imgix.net/images/65c2349950feb1958362e06217003b10.jpg?fit=crop&h=300&w=300",
  "shareUrl": "https://tienda.mercadona.es/product/4240/aceite-oliva-04o-hacendado-botella",
  "category": "Aceite, especias y salsas",
  "categoryId": 12,
  "subcategory": "Aceite, vinagre y sal",
  "subcategoryId": 112,
  "section": "Aceite de oliva",
  "sectionId": 420,
  "categoryPath": "Aceite, especias y salsas > Aceite, vinagre y sal > Aceite de oliva",
  "postalCode": "08001",
  "warehouse": "bcn1",
  "published": true,
  "scrapedAt": "2026-10-26T11:39:08.116Z",
  "detailsFetched": true,
  "ean": "8402001027475",
  "brand": "Hacendado",
  "origin": "España",
  "suppliers": ["Aceites Abril S.L.", "SOVENA ESPAÑA S.A.U."],
  "legalName": "HACENDADO ACEITE DE OLIVA",
  "ingredients": "Ingredientes: Aceite de oliva refinado y Aceite de Oliva Virgen.",
  "allergens": null,
  "usageInstructions": "Cocinar y sazonar",
  "isBulk": false,
  "isVariableWeight": false,
  "images": [
    "https://prod-mercadona.imgix.net/images/65c2349950feb1958362e06217003b10.jpg?fit=crop&h=3600&w=3600"
  ]
}
```

#### Key output fields

- **`productId`**: Mercadona product ID, stable across runs.
- **`unitPrice`**: the shelf price of one item, in EUR.
- **`referencePrice` / `referenceFormat`**: price per kg or litre (`referenceFormat` is e.g. `kg` or `L`), for comparing pack sizes.
- **`previousUnitPrice` / `priceDecreased`**: the earlier price when Mercadona has lowered it.
- **`taxPercentage`**: VAT rate (4, 10 or 21).
- **`categoryPath`**: top category, subcategory and section, joined with `>`.
- **`postalCode` / `warehouse`**: the postal code you asked for and the Mercadona warehouse that priced the row.
- **`ean`**: EAN-13 barcode (product details only).
- **`ingredients` / `allergens`**: plain text; `allergens` is null when Mercadona declares none (product details only).
- **`images`**: full-size photos, 3600 px (product details only).

***

### FAQ

**Do I need a Mercadona account?**
No. The actor reads the public online shop.

**Why does the postal code matter?**
Mercadona prices online orders by regional warehouse. In a test of the fruit aisle, about half the products had a different price in Madrid, Barcelona or Sevilla than in Valencia, and each warehouse stocks a slightly different range.

**What happens if Mercadona does not deliver to my postal code?**
The run stops at once with a message saying so. Try a nearby postal code.

**How many products are in the catalog?**
Around 4,000 to 4,500, depending on the warehouse. Set `maxItems` to 5000 to get all of them.

**Are prices in EUR?**
Yes, all prices are in euros, VAT included.

***

### ⚠️ Disclaimer

This Actor scrapes publicly available product data from tienda.mercadona.es. It does not access authenticated or private content. You are responsible for using the output in line with Mercadona's terms and any applicable law in your jurisdiction. This Actor is not affiliated with, endorsed by, or sponsored by Mercadona.

***

### SEO Keywords

mercadona scraper, mercadona product scraper, spanish supermarket scraper, mercadona api, mercadona catalog, mercadona prices, mercadona prices by postal code, mercadona ean, mercadona ingredients allergens, tienda mercadona, supermarket price scraper, spain grocery scraper, mercadona product data, mercadona csv export, grocery price monitoring

# Actor input Schema

## `postalCode` (type: `string`):

Spanish postal code to price the catalog for, e.g. 28001 (Madrid) or 08001 (Barcelona). Mercadona serves each area from a regional warehouse, and fresh food prices and the product range differ between them. Leave empty for Mercadona's default warehouse (Valencia). The run stops with an error if Mercadona does not deliver online to the code.

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

Fetch each product's detail page and add EAN barcode, brand, origin, suppliers, legal name, ingredients, allergens, storage and usage instructions, and the full-size photo gallery. One extra request per product, so runs take longer.

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

Maximum number of products to scrape. Products listed in more than one category are returned once.

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

How many requests to Mercadona run in parallel.

## `proxy` (type: `object`):

Apify proxy to use.

## Actor input object example

```json
{
  "postalCode": "28001",
  "includeDetails": false,
  "maxItems": 1000,
  "maxConcurrency": 8,
  "proxy": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

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

No description

# 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 = {
    "postalCode": "28001"
};

// Run the Actor and wait for it to finish
const run = await client.actor("memo23/mercadona-product-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 = { "postalCode": "28001" }

# Run the Actor and wait for it to finish
run = client.actor("memo23/mercadona-product-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 '{
  "postalCode": "28001"
}' |
apify call memo23/mercadona-product-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,memo23/mercadona-product-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/SWhHeKo9EQHc45mrP/builds/ybAX4ud8bXfGUEMV5/openapi.json
