# Complete Guide: How to Scrape El Corte Inglés Products Using Python

This comprehensive guide demonstrates how to extract structured catalog data from the Spanish department store El Corte Inglés (`elcorteingles.es`) using Python and the Apify platform. You will learn how to configure category scrapers, extract pricing and discount metrics, capture GTIN barcodes, and differentiate between direct store inventory and third-party marketplace vendors.

El Corte Inglés is a Spanish department store with an online catalog that includes fashion and consumer electronics. Attempting to harvest product listings with direct HTTP clients or simple headless browsers encounters modern anti-bot protection. During reach tests conducted on 2026-10-21, standard direct requests as well as datacenter and residential proxy connections received an "Access Denied" page from the site's Akamai Bot Manager, whereas Apify Unblocker returned the real category pages.

In this tutorial, you will use Python and the **El Corte Inglés Scraper** (`reventadata/elcorteingles-scraper`) Actor. All example numbers and dataset fields cited in this guide originate from a verbatim capture dated 2026-10-21 processed through the Actor's own extraction engine.

---

## TL;DR

In this guide, you will set up a Python script using the official Apify API client to extract product listings from El Corte Inglés category pages into structured JSON records.

Key workflow steps include installing `apify-client`, exporting your API token, defining your target category paths in `run_input`, triggering the execution on Apify, and fetching structured rows from your default dataset. The extracted dataset contains current prices in euros, original prices, discount percentages, brands, GTIN barcodes, and merchant names.

The Actor is available on the Apify Store at [apify.com/reventadata/elcorteingles-scraper](https://apify.com/reventadata/elcorteingles-scraper).

---

## Prerequisites and setup

Before running the extraction script, verify that your local development environment meets the following technical prerequisites:

1. **Python 3.11 or newer:** The official `apify-client` 3.x library requires Python 3.11+.
2. **Apify account:** You can sign up with an email address or GitHub account at [apify.com](https://apify.com/).
3. **Apify API token:** Located under **API & Integrations** in the Apify Console.

Install the Apify Python client library using pip:

```bash
pip install -U "apify-client~=3.0"
```

Next, configure your API token as an environment variable in your terminal:

```bash
export APIFY_API_TOKEN="your_apify_token_here"
```

The Apify Console serves as your cloud workspace where you can inspect Actor runs, monitor execution logs, review storage datasets, and configure scheduled tasks.

---

## Understanding El Corte Inglés Scraper

El Corte Inglés Scraper extracts catalog data from `elcorteingles.es` through specialized handling of the site's architecture:

1. **Robots.txt compliance and category routing:** The site's `robots.txt` explicitly disallows search paths (`/search-nwx/`, `/*/search`) and parameterised filter URLs (such as `brand::` or `price::`). To comply with site rules, the Actor also refuses any query string and search URL up front. It requests clean category paths (e.g., `/electronica/moviles-y-smartphones/` or `/moda-mujer/zapatos/`) and handles all brand, price, and discount filtering post-fetch.
2. **Embedded state parsing:** Category pages are server-rendered Vue pages containing an inline JavaScript state object (`window.__MOONSHINE_STATE__`). While listing grid HTML contains skeleton placeholders filled client-side, the state script already holds complete product metadata. The Actor parses this state directly, joining `state.products` with `state._datalayer[0].products`.
3. **Akamai Bot Manager navigation:** A direct request from a Mac got HTTP 403 and an "Access Denied" body, and the datacenter and residential connections tried from the platform got a deny body too. The Actor routes requests through Apify Unblocker, which returned the real page.
4. **Site pagination boundaries:** Each page holds 12 products. The site enforces a hard ceiling of 833 pages per category (9,996 products), answering page 834 with HTTP 404.

---

## Step-by-step walkthrough

### Step 1: Initialize the client and define inputs

In your Python project, import `os` and `ApifyClient`, initialize the client with your environment token, and define the run configuration dictionary:

```python
import os
from apify_client import ApifyClient

# 1. Initialize ApifyClient with the token from the environment
client = ApifyClient(os.environ["APIFY_API_TOKEN"])

# 2. Configure El Corte Inglés category URL: 2 pages, up to 24 items
run_input = {
    "categoryUrls": [
        "https://www.elcorteingles.es/electronica/moviles-y-smartphones/"
    ],
    "maxPagesPerCategory": 2,
    "maxItems": 24,
}
```

The `categoryUrls` parameter accepts one or more category listing URLs. Setting `maxPagesPerCategory: 2` limits the crawl to the first two numbered pages (up to 24 items), which provides a fast baseline test.

### Step 2: Trigger execution on Apify

Invoke the Actor using the `.call()` method on the Actor client, passing `run_input`:

```python
# 3. Start the Actor run and wait for it to finish
print("Starting El Corte Inglés extraction...")
run = client.actor("reventadata/elcorteingles-scraper").call(run_input=run_input)
if run is None or run.status != "SUCCEEDED":
    status = run.status if run else "unknown"
    raise SystemExit(f"Run did not succeed (status: {status}).")

# 4. Fetch the saved products
items = client.dataset(run.default_dataset_id).list_items().items
print(f"Retrieved {len(items)} products.\n")
```

The `.call()` method initiates cloud execution and blocks until the run settles into a terminal state (`SUCCEEDED`, `FAILED`, or `TIMED-OUT`).

### Step 3: Inspect dataset records

Once the run finishes successfully, access the dataset items stored in `run.default_dataset_id`:

```python
for item in items:
    print(item["name"])
    print(f"  Brand: {item.get('brand')} | Seller: {item.get('seller')} | Marketplace: {item.get('isMarketplace')}")
    print(f"  Price: {item.get('price')} {item.get('currency')} | Original: {item.get('originalPrice')}")
    print(f"  Discount: {item.get('discountPercent')}% | On sale: {item.get('onSale')}")
    print(f"  Barcode: {item.get('gtin')} | Status: {item.get('status')}")
    print(f"  {item['url']}")
    print("-" * 40)
```

The record below is a verbatim sample captured from page 16 of `/moda-mujer/zapatos/`, parsed with the Actor's own extraction engine from a fixture dated 2026-10-21:

```json
{
  "id": "MP_0623819_252BZ131810522",
  "name": "Zapatillas deportivas de mujer retro 13 18 con cordones Marrón",
  "brand": "Bimba y Lola",
  "url": "https://www.elcorteingles.es/moda-mujer/MP_0623819_252BZ131810522-marron-pr-zapatillas-deportivas-de-mujer-retro-13-18-con-cordones/",
  "image": "https://dam.elcorteingles.es/producto/www-8445394427095-00.jpg",
  "gtin": "8445394427149",
  "price": 68.6,
  "currency": "EUR",
  "originalPrice": 98.0,
  "discountPercent": 30,
  "discountAmount": 29.4,
  "onSale": true,
  "category": "Moda mujer > Zapatos > Zapatillas > Zapatillas deportivas",
  "categories": [
    "Moda mujer",
    "Zapatos",
    "Zapatillas",
    "Zapatillas deportivas"
  ],
  "seller": "BIMBA & LOLA",
  "isMarketplace": true,
  "colourCount": 1,
  "status": "ADD",
  "isNew": false,
  "categoryPath": "/moda-mujer/zapatos/",
  "page": 16,
  "position": 1
}
```

---

## Working with the API

The Python client offers two distinct execution methods for this Apify Actor. Calling `client.actor("reventadata/elcorteingles-scraper").call(run_input=run_input)` starts the execution and blocks until the run finishes, returning a populated run model or `None`. For background tasks, scheduled scripts, or job queues, `.start(run_input=run_input)` triggers cloud execution immediately and returns the run object right away, allowing you to track progress later using its unique ID.

Authentication relies on the API token loaded from `APIFY_API_TOKEN`; keep this secret out of version control. Once a run finishes, `client.dataset(run.default_dataset_id).list_items().items` fetches dataset records in a single batch, while `.iterate_items()` allows streaming large datasets item by item to optimize local memory usage.

For event-driven architectures, you can configure webhooks on the `ACTOR.RUN.SUCCEEDED` event. As detailed in Apify documentation, the webhook payload's `resource` object contains the response of the Get Actor run endpoint, providing direct access to `defaultDatasetId` so your application can ingest fresh rows without polling.

Error handling: check `run.status` after execution. Supported terminal statuses include `SUCCEEDED`, `FAILED`, and `TIMED-OUT`. El Corte Inglés Scraper intentionally raises a `RuntimeError` if zero rows are saved, preventing silent failures. When diagnosing runs, inspect logs programmatically with `client.log(run.id).get()`; each page logs its product count and the site's category total, and the final line tallies the filter rejections.

---

## Advanced usage patterns

El Corte Inglés Scraper can be adapted to several enterprise data extraction patterns:

### Multi-category batch extraction

Pass multiple category paths in `categoryUrls`, such as `["/electronica/moviles-y-smartphones/", "/moda-mujer/zapatos/"]`. The Actor walks each category in the specified sequence and aggregates records into one unified dataset. Product deduplication tracks IDs across categories, so items listed in multiple category hierarchies are stored only once, and the run halts once `maxItems` is reached.

### Marketplace vendor auditing

By setting `sellerType: "marketplace"`, you can isolate catalog entries fulfilled by third-party retailers to audit merchant pricing, shipping terms, and catalog assortment. Conversely, setting `sellerType: "elcorteingles"` restricts the dataset exclusively to direct department store retail inventory.

### Discount threshold monitoring

Combine `onlyDiscounted: true` with `minDiscountPercent: 25` to capture substantial price drops. Because filtering occurs within the Actor before records are saved to storage, your dataset contains only relevant promotional records.

### Automated scheduled sweeps

Save your preferred input configuration as a task (a reusable named preset) in the Apify Console. Configure an Apify schedule using standard cron expressions; for instance, `0 8 * * *` triggers the scraper every morning at 8 AM. When combined with webhooks, new catalog updates flow directly into your analytics data warehouse.

---

## Understanding your data

The dataset produced by El Corte Inglés Scraper provides 23 structured fields designed for retail analytics:

- **Product code structure (**`id`**):** Direct retail inventory features an `A` prefix followed by numerical identifiers (e.g., `A200977771`), whereas third-party marketplace stock uses the format `MP_<seller>_<sku>` (e.g., `MP_0623819_252BZ131810522`).
- **Comprehensive price metrics:** The `price` field reflects the active offer price in EUR. When items are on promotion, `originalPrice`, `discountPercent`, and `discountAmount` are populated, and `onSale` evaluates to `true`. On page 16 of our footwear fixture, 9 of 12 items carried discounts between 16% and 31%. For items selling at standard retail price, discount fields remain `null`.
- **Merchant attribution:** The `seller` string indicates the merchant of record (e.g., `"El Corte Ingles, S.A."`, `"BIMBA & LOLA"`, or `"GRUPO MUSTANG"`), accompanied by the `isMarketplace` boolean flag.
- **Barcodes and taxonomy:** The `gtin` field holds standard EAN barcodes, while `category` and `categories` supply hierarchical taxonomy paths.

---

## Troubleshooting guide

When configuring and running El Corte Inglés Scraper, refer to these common operational scenarios:

- **Run FAILED with zero records saved:** The Actor intentionally raises `RuntimeError: 0 rows for categories...` if no products pass your filter criteria. This design ensures that empty results trigger immediate alerts rather than completing silently. Verify that your `brands`, `minDiscountPercent`, or price ranges are not overly restrictive for the chosen category.
- **Input validation errors:** If the Actor raises a `ValueError` for a category URL, it contains query strings (`?`), search paths (`/search/`, `/search-nwx/`), or attribute filter prefixes (`brand::`). Strip parameters to supply only clean category paths.
- **Fewer rows than** `maxItems`**:** For smaller categories (such as smartphones with 135 items across 12 pages), the Actor stops after the last page computed from the site's product count (page 12 for 135 products), even if `maxPagesPerCategory` is set higher.
- **Inspecting execution logs:** Retrieve detailed run logs using `client.log(run.id).get()`. The log records product counts per page, the site's category total, and a final tally of filter rejections.

---

## Best practices

Follow these best practices to ensure reliable and efficient catalog extraction:

1. **Target canonical category paths:** Copy URLs directly from main category navigation on `elcorteingles.es` and omit query parameters.
2. **Set appropriate caps:** Always define `maxItems` and `maxPagesPerCategory` to control execution scope and keep runs bounded.
3. **Use post-fetch filters for discount audits:** Use `onlyDiscounted: true` or `minDiscountPercent` to drop full-price inventory before records are pushed to the dataset.
4. **Rely on GTIN for catalog matching:** Match items across retail competitors using standard `gtin` barcode values rather than relying on variable product names.
5. **Handle execution status explicitly:** Always check `run.status == "SUCCEEDED"` before reading records from the dataset client.

---

## Pricing

For current pricing and details, see the [Store page](https://apify.com/reventadata/elcorteingles-scraper).

---

## Conclusion and next steps

You have learned how to automate product extraction from El Corte Inglés using Python and Apify. You configured category targets, applied post-fetch discount filters, executed cloud runs, and exported structured records containing prices, discounts, GTIN barcodes, and marketplace seller designations.

Next steps include setting up Apify Schedules for automated daily tracking or connecting webhooks to stream data into your analytics database.

Try El Corte Inglés Scraper yourself and let me know what you build!

*About the author: reventadata builds and maintains marketplace and retail scrapers on the Apify Store.*

---

## Resources

- [El Corte Inglés Scraper on Apify Store](https://apify.com/reventadata/elcorteingles-scraper)
- [Apify Python SDK Documentation](https://docs.apify.com/api/client/python/docs)
- [Apify Schedules Guide](https://docs.apify.com/actors/running/schedules)
- [Apify Webhooks Documentation](https://docs.apify.com/integrations/webhooks/actions)
