# Decathlon.es - Prices, Discounts, Specs & Reviews (`abotapi/decathlon-es-scraper`) Actor

Scrape Decathlon Spain (decathlon.es) sporting goods: current price plus strike-through discount, brand, seller, technical specifications, colour/size availability, GTINs, and reviews. Search by keyword/category with brand and price filters, or paste product and listing links.

- **URL**: https://apify.com/abotapi/decathlon-es-scraper.md
- **Developed by:** [Abot API](https://apify.com/abotapi) (community)
- **Categories:** E-commerce, Automation, Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.00 / 1,000 product results

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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

## Decathlon Spain Product Scraper

Pull product data from Decathlon Spain (decathlon.es), a major sporting goods retailer. Search by keyword or a real Decathlon category, filter by brand and price, or paste product and listing links directly. Every record includes the current price, the strike-through original price with discount percentage when a product is marked down, seller information (Decathlon first-party vs marketplace), and reviews.

### Why This Scraper?

- **Was-price and discount, structured, not scraped from a badge.** When a product is marked down, both prices are captured plus the discount percentage and sale end date -- gated on the site's own real price pair, never fabricated on full-price items.
- **First-party vs marketplace seller.** Decathlon Spain also runs a marketplace with third-party sellers; every record tells you which one sold it.
- **Real technical specifications.** Practice level, terrain, fit, material, waterproofing, and more -- straight from the product page's own structured attribute list, not scraped free text.
- **Reviews straight from Decathlon's own API.** Overall rating, review count, recommended count, and individual reviews (rating, title, body, author, date, verified-buyer flag) -- not a third-party review vendor.
- **Real filters and sort.** Brand and on-sale narrow the actual server-side result set; sort by price, highest discount, or highest rated all reorder the full result set, not just one page.
- **Two ways in.** Keyword or category search with real site filters, or paste any product/search/category link and continue pagination automatically.
- **Incremental & dedup mode for scheduled monitoring.** Run the same search daily and get back only what changed -- NEW, UPDATED, or REAPPEARED products -- instead of the full list every time, with unchanged products suppressed (not returned, not billed) by default.
- **Optional export to your apps.** Send results into Notion, Linear, Airtable, or any Apify MCP connector alongside the dataset.

### Data You Get

| Field | Example value |
|---|---|
| productId / supermodelId / sku | `0000000`, `000000`, `00000000-0000-0000-0000-000000000000` |
| name | `Sample Running Shoes - Grey and Pink` |
| brand | `SAMPLE BRAND` |
| url | `https://www.decathlon.es/es/p/sample-running-shoes/000000/c0000m0000000` |
| price / currency | `39.99`, `EUR` |
| originalPrice / discountPercent | `54.99`, `27` |
| isOnSpecial / saleEndsAt | `true`, `2026-07-31T22:00:00.000Z` |
| onlineAvailable | `true` |
| availableSizes | `["38", "39 1/3", "40", "41 1/3"]` |
| seller | `{"name": "Decathlon", "type": "FIRST_PARTY"}` |
| sports | `["Road running"]` |
| image / images | `["https://contents.mediadecathlon.com/sample/picture.jpg"]` |
| rating / reviewCount | `4.6`, `607` |
| category / categoryPath | `Adidas`, `["Deportes", "Running", "Marcas", "Adidas"]` |
| description | full product description text |
| specifications | `[{"name": "Nivel de práctica", "value": "Iniciación"}, {"name": "Material", "value": "Materia sintética"}]` |
| composition / careInstructions / guarantee | material composition, care text, guarantee terms when the site provides them |
| colors | `[{"name": "rosa", "hexaCode": "#E30076"}]` |
| gtins | `["0000000000000"]` |
| reviews.averageRating / reviews.totalReviewCount / reviews.recommendedCount | `4.64`, `607`, `501` |
| reviews.items\[] | `[{"rating": 5, "title": "Excelente", "body": "Sample review text.", "author": "Sample User", "date": "2026-07-16T11:34:20+00:00", "recommended": true, "verifiedBuyer": true}]` |
| scrapedAt | `2026-07-18T00:00:00.000000+00:00` |
| changeType (incremental mode only) | `NEW`, `UPDATED`, `UNCHANGED`, `REAPPEARED`, or `EXPIRED` |
| changedFields (incremental mode only) | `["price", "isOnSpecial"]` |
| firstSeenAt / lastSeenAt (incremental mode only) | `2026-07-18T00:00:00Z`, `2026-07-19T00:00:00Z` |

> Sample shape: values above are illustrative placeholders, not from a live product.

### How to Use

**1. Keyword search, first page, with reviews (default):**

```json
{
  "mode": "search",
  "searchTerm": "zapatillas running",
  "maxItems": 20
}
```

**2. Category browse, filtered to a brand, sorted by highest discount, on-sale only:**

```json
{
  "mode": "search",
  "category": "deportes/running/zapatillas-running",
  "brand": "ADIDAS",
  "specialsOnly": true,
  "sortBy": "DISCOUNT_DESC",
  "maxItems": 50,
  "maxPages": 5
}
```

**3. Full product detail (specifications + GTINs) and reviews for a pasted product link:**

```json
{
  "mode": "url",
  "urls": ["https://www.decathlon.es/es/p/sample-running-shoes/000000/c0000m0000000"],
  "fetchDetails": true,
  "fetchReviews": true
}
```

**4. Paste a search result page and keep paginating forward:**

```json
{
  "mode": "url",
  "urls": ["https://www.decathlon.es/es/search?Ntt=mochila+trekking"],
  "maxItems": 100,
  "maxPages": 10
}
```

### Input Parameters

| Parameter | Type | Description |
|---|---|---|
| `mode` | string | `search` or `url`. |
| `searchTerm` | string | Keyword (search mode only). |
| `category` | string | A real decathlon.es category path, e.g. `deportes/running/zapatillas-running` (search mode only, used when Search keyword is empty). |
| `brand` | string | Exact brand name to keep, e.g. `ADIDAS` (search mode only). |
| `specialsOnly` | boolean | Keep only products currently marked down (search mode only). |
| `minPrice` / `maxPrice` | number | EUR price band to keep (search mode only). |
| `sortBy` | string | `RELEVANCE`, `PRICE_ASC`, `PRICE_DESC`, `DISCOUNT_DESC`, or `RATING_DESC` (search mode only). |
| `urls` | array | Product, search, or category listing URLs to scrape (url mode only). |
| `fetchDetails` | boolean | Fetch full product detail (breadcrumb category path, description, technical specifications, composition/care/guarantee, colours, GTINs). |
| `fetchReviews` | boolean | Fetch the product's own reviews. |
| `maxReviewsPerProduct` | integer | Cap on reviews per product; the API itself only ever surfaces up to 30 per page. |
| `maxPages` | integer | Cap on result pages per search/category/URL entry; `0` (default) = unlimited -- the run stops at Max products total instead. |
| `maxItems` | integer | Cap on total products returned; `0` = unlimited. |
| `resumeFromRunId` | string | Paste a previous run id (or its dataset id) to continue that run: products already collected there are skipped, so this run only returns new products (a delta). Leave empty for a normal run. |
| `incrementalMode` | boolean | Turn on for daily/recurring monitoring of the same search. The first run returns everything as `NEW`; later runs return only `NEW`/`UPDATED`/`REAPPEARED` products, suppressing (not returning, not billing) unchanged ones by default. Distinct from `resumeFromRunId` -- see "Incremental & dedup mode" below. |
| `stateKey` | string | Incremental mode only. Optional name for a monitoring campaign so its state stays stable, or is deliberately shared across differently-configured runs. Leave empty to derive a key automatically from the search/category/URL and detail/reviews settings. |
| `emitUnchanged` | boolean | Incremental mode only. Off by default. Also return (and bill) products that have not changed, marked `UNCHANGED`. |
| `emitExpired` | boolean | Incremental mode only. Off by default. Also return (and bill) products present in a previous run but no longer found, marked `EXPIRED` -- only produced after a run fully scans the tracked search (not when Max products capped it or Resume was used). |
| `proxy` | object | Apify proxy configuration. Works on every plan by default. |
| `mcpConnectors` | array | Optional MCP connectors to export results into (Notion, Linear, Airtable, Apify). |
| `notionParentPageUrl` | string | Notion connector only: page under which item pages are created. |
| `maxNotifyListings` | integer | Cap on items exported to each connector per run. Does not affect the dataset. |

### Output Example

```json
{
  "productId": "0000000",
  "supermodelId": "000000",
  "sku": "00000000-0000-0000-0000-000000000000",
  "name": "Sample Running Shoes - Grey and Pink",
  "brand": "SAMPLE BRAND",
  "url": "https://www.decathlon.es/es/p/sample-running-shoes/000000/c0000m0000000",
  "image": "https://contents.mediadecathlon.com/sample/picture.jpg",
  "images": ["https://contents.mediadecathlon.com/sample/picture.jpg"],
  "price": 39.99,
  "currency": "EUR",
  "originalPrice": 54.99,
  "discountPercent": 27,
  "isOnSpecial": true,
  "saleEndsAt": "2026-07-31T22:00:00.000Z",
  "availableSizes": ["38", "39 1/3", "40", "41 1/3"],
  "onlineAvailable": true,
  "seller": { "name": "Decathlon", "type": "FIRST_PARTY" },
  "sports": ["Road running"],
  "nature": "zapatillas de deporte",
  "rating": 4.64,
  "reviewCount": 607,
  "categoryPath": ["Deportes", "Running", "Marcas", "Adidas"],
  "category": "Adidas",
  "description": "Sample product description as shown on the site.",
  "specifications": [
    { "name": "Nivel de práctica", "value": "Iniciación" },
    { "name": "Material", "value": "Materia sintética" }
  ],
  "colors": [{ "name": "rosa", "hexaCode": "#E30076" }],
  "gtins": ["0000000000000"],
  "reviews": {
    "averageRating": 4.64,
    "totalReviewCount": 607,
    "recommendedCount": 501,
    "items": [
      { "rating": 5, "title": "Excelente", "body": "Sample review text.", "author": "Sample User", "date": "2026-07-16T11:34:20+00:00", "recommended": true, "verifiedBuyer": true }
    ]
  },
  "scrapedAt": "2026-07-18T00:00:00.000000+00:00"
}
```

> Sample shape: values above are illustrative placeholders, not from a live product.

### A note on was-price and reviews

Decathlon Spain runs genuine seasonal sales and day-to-day promotions. `originalPrice`/`discountPercent`/`isOnSpecial` are only set when the site's own reference price is genuinely higher than the current price -- a manufacturer's suggested reference price shown with no active promotion is never reported as a was-price. Reviews come directly from Decathlon's own reviews API, not a third-party vendor; each product page surfaces its rating, total review count, and individual reviews.

### Incremental & dedup mode (recurring/scheduled monitoring)

Turn on `incrementalMode` to run the same search/category/URL setup again and again (e.g. daily) and get back only what changed, instead of the full result set every time. The first run returns everything as `NEW`; later runs classify each product as `NEW`, `UPDATED` (with `changedFields` naming exactly what changed), `UNCHANGED`, `REAPPEARED` (was missing, now back), or `EXPIRED` (tracked previously, no longer found -- only detected after a run fully scans the tracked search). `UNCHANGED` products are suppressed by default -- neither returned nor billed -- unless `emitUnchanged` is turned on; `EXPIRED` products are only returned when `emitExpired` is turned on. State is kept per search/category/URL and detail/reviews configuration automatically; set `stateKey` to name or deliberately share a monitoring campaign.

This is a different feature from `resumeFromRunId`, which continues one specific interrupted run instead of tracking recurring changes.

### Send results into your apps (MCP connectors)

Optionally pipe results into the apps you already use through Model Context Protocol (MCP) connectors. Authorize a connector once under Apify, Settings, Integrations, then select it in the `mcpConnectors` field. Each connector receives a condensed, human-readable summary per product (name plus key fields), while the complete record always stays in the Apify dataset. For Notion, set `notionParentPageUrl` to the page the item pages should be created under, and use `maxNotifyListings` to cap how many items are exported per connector per run. Supported connectors: Notion, Linear, Airtable, and Apify. Leave the field empty to skip; it never changes the dataset output.

### A note on plans

The default connection works on every Apify plan, including the free tier. A residential proxy connection is optional and only worth turning on for very large or sustained runs.

# Actor input Schema

## `mode` (type: `string`):

'search' finds products by keyword or by a real decathlon.es category, with a brand filter, price range, specials toggle, and sort. 'url' scrapes any product, search, or category listing page URL you paste, walking pagination forward automatically.

## `searchTerm` (type: `string`):

Free-text keyword, e.g. 'zapatillas running' or 'mochila trekking'. Leave empty and use Category below to browse a category without a keyword (the two are alternative ways in, not combined).

## `category` (type: `string`):

A real decathlon.es category path or URL, e.g. 'deportes/running/zapatillas-running' or the full https://www.decathlon.es/es/deportes/running/zapatillas-running link. Used only when Search keyword is empty.

## `brand` (type: `string`):

Only return products from this exact brand, e.g. 'ADIDAS', 'KIPRUN', 'QUECHUA'. Match the brand name as shown on the site. Leave empty for all brands. Applies to search mode only.

## `specialsOnly` (type: `boolean`):

Keep only products currently marked down -- decathlon.es's own live discount signal (a real strike-through original price plus discount percentage on the product itself), not a guessed category or a separate landing-page feed.

## `minPrice` (type: `number`):

Only return products priced at or above this amount, in euros.

## `maxPrice` (type: `number`):

Only return products priced at or below this amount, in euros.

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

decathlon.es's own sort order, verified live to reorder the full server-side result set (so it stays correct across pagination, not just within one fetched page).

## `urls` (type: `array`):

Paste one or more decathlon.es product pages, search result pages, or category listing pages. Pagination continues forward automatically from any ?from= already in the URL. Filter fields above are ignored in this mode.

## `fetchDetails` (type: `boolean`):

Adds the full breadcrumb category path, complete description, technical characteristics (level, terrain, fit, material, etc.), composition/care/guarantee text, colour swatches, and per-size GTIN/EAN codes from the product page. Current price, was-price/discount, brand, and card image are already included without this toggle.

## `fetchReviews` (type: `boolean`):

Fetch the product's own reviews (not a third-party vendor) from decathlon.es's reviews API: overall rating, total review count, recommended count, and individual reviews (rating, title, body, author, date, verified-buyer flag). Products with no reviews simply return an empty list.

## `maxReviewsPerProduct` (type: `integer`):

Cap on reviews fetched per product when 'Fetch reviews' is on, up to the API's own 30-review page limit.

## `maxPages` (type: `integer`):

Stop after this many result pages per search/category/URL entry. 0 (default) = unlimited -- the run stops at Max products total instead.

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

Hard cap on total products returned across every search/category/URL entry. 0 = unlimited (still bounded by Max pages per search).

## `resumeFromRunId` (type: `string`):

Paste a previous run id (or its dataset id) to continue that run without returning or charging for products already collected there. Use this after an interrupted run. For recurring daily/scheduled monitoring of the same search, use Incremental mode below instead.

## `incrementalMode` (type: `boolean`):

Turn this on for daily or recurring monitoring. The first run returns all matching products as NEW. Later runs normally return only NEW, UPDATED, and REAPPEARED products. Turn on "Emit unchanged" or "Emit expired" only when you also want those products returned (and billed). State is kept separately for each search/category/URL and detail/reviews setup; use State key when you want to name or deliberately share a monitoring campaign. To continue one specific interrupted run instead, use Resume from a previous run above.

## `stateKey` (type: `string`):

Optional. Name this monitoring campaign to keep its state stable, or to deliberately share state across differently-configured runs. Leave empty to let the actor derive a key automatically from the search/category/URL and detail/reviews settings -- different searches then never mix state with each other.

## `emitUnchanged` (type: `boolean`):

Off by default. Turn on to also return products that have not changed since the last run, marked UNCHANGED. This returns -- and bills -- extra rows you already have, so leave it off unless you specifically want the full snapshot every run.

## `emitExpired` (type: `boolean`):

Off by default. Turn on to also return products that were present in a previous run but are no longer found, marked EXPIRED. Only produced once a run has fully scanned the tracked search -- not when Max products capped it or when Resume was used. This returns -- and bills -- extra synthetic rows, so leave it off unless you need expiry tracking.

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

The default connection works on every Apify plan, including the free tier. A residential connection is optional and only needed for very large or sustained runs.

## `mcpConnectors` (type: `array`):

Optionally send the scraped results into the apps you already use, via Model Context Protocol (MCP) connectors. Authorize a connector once under Apify -> Settings -> Integrations, then select it here. The connector receives a condensed, human-readable summary per item (title + key fields), not the full JSON; the complete record stays in the dataset. Leave empty to skip. Supported: Notion (https://mcp.notion.com/mcp), Linear (https://mcp.linear.app/sse), Airtable (https://mcp.airtable.com/mcp), Apify (https://mcp.apify.com).

## `notionParentPageUrl` (type: `string`):

URL (or id) of the Notion page under which item pages are created. Required to enable the Notion export; ignored by other connectors.

## `maxNotifyListings` (type: `integer`):

Cap on items written to each connector per run. Does not affect the dataset.

## Actor input object example

```json
{
  "mode": "search",
  "searchTerm": "zapatillas running",
  "specialsOnly": false,
  "sortBy": "RELEVANCE",
  "urls": [
    "https://www.decathlon.es/es/deportes/running/zapatillas-running"
  ],
  "fetchDetails": false,
  "fetchReviews": true,
  "maxReviewsPerProduct": 10,
  "maxPages": 0,
  "maxItems": 20,
  "incrementalMode": false,
  "emitUnchanged": false,
  "emitExpired": false,
  "proxy": {
    "useApifyProxy": true
  },
  "maxNotifyListings": 50
}
```

# Actor output Schema

## `overview` (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 = {
    "mode": "search",
    "searchTerm": "zapatillas running",
    "urls": [
        "https://www.decathlon.es/es/deportes/running/zapatillas-running"
    ],
    "incrementalMode": false,
    "emitUnchanged": false,
    "emitExpired": false,
    "proxy": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("abotapi/decathlon-es-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 = {
    "mode": "search",
    "searchTerm": "zapatillas running",
    "urls": ["https://www.decathlon.es/es/deportes/running/zapatillas-running"],
    "incrementalMode": False,
    "emitUnchanged": False,
    "emitExpired": False,
    "proxy": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("abotapi/decathlon-es-scraper").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 '{
  "mode": "search",
  "searchTerm": "zapatillas running",
  "urls": [
    "https://www.decathlon.es/es/deportes/running/zapatillas-running"
  ],
  "incrementalMode": false,
  "emitUnchanged": false,
  "emitExpired": false,
  "proxy": {
    "useApifyProxy": true
  }
}' |
apify call abotapi/decathlon-es-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=abotapi/decathlon-es-scraper",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/acts/ujDoL7eajor4J2U8x/builds/LFJWUSmhLHmJf8w04/openapi.json
