# Zara Product Scraper — Prices, Sizes & Stock (`sian.agency/zara-product-scraper`) Actor

Scrape Zara into a clean 58-column dataset: price, discount, currency, colours, images, description and per-SKU sizes with stock, across 200+ country stores. Sweep the catalogue, one category, the sitemap, or paste product URLs. No account, API key or proxy needed.

- **URL**: https://apify.com/sian.agency/zara-product-scraper.md
- **Developed by:** [SIÁN OÜ](https://apify.com/sian.agency) (community)
- **Categories:** E-commerce, Business
- **Stats:** 4 total users, 3 monthly users, 100.0% runs succeeded, 1 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.25 / 1,000 scraped products

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

## Zara Product Scraper — Prices, Sizes & Stock 🛍️

[![SIÁN Agency Store](https://img.shields.io/badge/Store-SI%C3%81N%20Agency-1AE392)](https://apify.com/sian.agency?fpr=sian) [![Myntra Product Scraper](https://img.shields.io/badge/Store-Myntra%20Product%20Scraper-FF3F6C)](https://apify.com/sian.agency/myntra-product-scraper?fpr=sian) [![Nike Product Scraper](https://img.shields.io/badge/Store-Nike%20Product%20Scraper-111111)](https://apify.com/sian.agency/nike-product-scraper?fpr=sian) [![AliExpress Product Scraper](https://img.shields.io/badge/Store-AliExpress%20Product%20Scraper-E62E04)](https://apify.com/sian.agency/aliexpress-product-scraper?fpr=sian)

#### 🎉 Zara's catalogue in 96 country stores, priced in each market's own currency — 58 columns per product, including per-SKU sizes, stock and Zara's own per-SKU demand signal

##### Built for price analysts, assortment planners, resellers and anyone who wants zara.com as clean rows instead of screenshots.

### 🔎 What is the Zara Product Scraper — and when should you use it?

The **Zara Product Scraper** turns zara.com's public catalogue into clean, structured rows you can filter, export and feed straight into a spreadsheet, database or AI agent. No account, no portal API key, no browser automation to maintain.

**Use it when you need:** Zara products with current price, pre-discount price, discount percentage and the market's own currency. Also colours, images, the full category path, descriptions, composition, per-SKU sizes with stock, and the merchandising slot each product held in its grid.

**Use something else when:** you want a different Inditex brand. Use [Zara Home Product Scraper](https://apify.com/sian.agency/zara-home-product-scraper?fpr=sian) for homeware, [Bershka Product Scraper](https://apify.com/sian.agency/bershka-product-scraper?fpr=sian) for Bershka, or [Inditex Product Scraper](https://apify.com/sian.agency/inditex-product-scraper?fpr=sian) when you want several brands in one dataset with one schema.

### 🤖 Use with AI agents

Already connected to the [Apify MCP server](https://mcp.apify.com)? Just ask for this Actor by name: sian.agency/zara-product-scraper

Otherwise copy this prompt into Claude, ChatGPT, Cursor or any MCP-enabled assistant:

```text
I want Zara product data using the Apify Actor `sian.agency/zara-product-scraper`.

Use it when I need: Zara products with price, old price, discount, currency, colours, images, category taxonomy, description, composition, and per-SKU sizes with stock.

Don't use it when: I want a different Inditex brand — use `zara-home-product-scraper`, `bershka-product-scraper`, or `inditex-product-scraper` for several brands at once.

How to call it: `mode` is either "overview" (walks the category tree and returns every product) or "detail" (takes product URLs I paste). In overview mode set `country` to the zara.com market segment, keep `allCategories` on, and cap the run with `maxItems`. Turn on `withSizes` when I need sizes, stock and descriptions — Zara's grid does not carry them.

Start with this input:
{
  "mode": "overview",
  "country": "de",
  "allCategories": true,
  "withSizes": true,
  "maxItems": 100
}

Ask me which market and how many products, then run the Actor and summarise the results as a table.
```

**Things you can ask your agent for:**

- *Compare the same Zara dress across the German, British and Japanese stores and show me the price gaps in local currency.*
- *Pull the first 500 products from the Zara new-in grid and list everything that is already discounted.*
- *Take these 40 Zara product URLs and give me every size with its stock state and Zara's own demand signal.*

Machine-readable API, MCP config and OpenAPI definition for this Actor are published at [apify.com/sian.agency/zara-product-scraper.md](https://apify.com/sian.agency/zara-product-scraper.md).

***

### 📋 Overview

**The Zara Product Scraper reads zara.com the way zara.com reads itself.** It talks to the same catalogue endpoints the website uses, so you get the real record — not whatever survived an HTML parse.

**What you get:**

- ✅ **58 columns per product**: price, old price, discount, currency, colours, images, taxonomy, description, composition, availability, per-SKU sizes
- 🌍 **96 country stores**: every market zara.com publishes, each priced in its own currency with the right divisor applied
- 📐 **Sizes and per-SKU stock**: Zara's grid carries neither — one switch fetches them and merges them into the row
- 📊 **Merchandising rank**: `grid_position` and `is_pinned` tell you where Zara chose to place a product in the grid, and which tiles it pinned there
- 🆕 **Drop detection**: `first_visible_date` is when a product entered the catalogue — diff two runs and you have the new-arrivals feed
- 🔗 **Twinned SKUs and cross-market size ids**: the same physical SKU under sibling style ids, and Zara's own mapping between a German S and a US S
- 🧾 **A bill you can audit**: the `source` column on every row says which call produced it, so your invoice reconciles against the dataset
- 💰 **$2.50 per 1,000 products** on the category sweep, and the price steps down as your Apify plan tier goes up

### ✨ Features

- 🗂️ **Category sweep**: walk the whole tree, or name one category and take just that
- 🗺️ **Sitemap sweep**: pick up catalogue items no category lists, for genuine full-catalogue coverage
- 🔗 **Paste your own URLs**: hand it product links or bare `?v2=` ids and get one full record each
- 🎚️ **Facet filters**: filter by colour, size or any facet the category publishes, one filter per line
- 💶 **Price bounds**: keep only what falls between your floor and ceiling, in the market's major units
- ↕️ **Sort**: catalogue order, price ascending or descending, or novelty where the category offers it
- 🌐 **Any market**: `de` for zara.com/de, `us` for zara.com/us, and so on across the 96 stores in the dropdown
- 🧹 **Deduplicated**: the same product reached from two categories is counted and charged once
- 📉 **Honest run summary**: products pushed, duplicates skipped, ids that no longer exist, and fetches that genuinely failed — reported apart, never merged

### 🎬 Quick Start

Pick a market, leave the category sweep on, cap the run, and press Run. That is the whole setup.

```bash
curl -X POST 'https://api.apify.com/v2/acts/sian.agency~zara-product-scraper/runs?token=YOUR_TOKEN' \
-H 'Content-Type: application/json' \
-d '{
  "mode": "overview",
  "country": "de",
  "allCategories": true,
  "maxItems": 100
}'
```

### 🚀 Getting Started (3 Simple Steps)

#### Step 1: Choose your market

Set **Market** to the first segment of a Zara URL — `de` for zara.com/de, `us` for zara.com/us, `gb`, `jp`, and so on. Prices, names and stock are per market, and the `country` column travels with every row so a multi-market dataset stays honest.

#### Step 2: Choose what to scrape

Leave **Sweep All Categories** on for the catalogue. Turn it off and fill **Single Category** to take one grid. Or switch **Run Mode** to `detail` and paste product URLs. Turn on **Fetch Sizes & SKUs** when you need sizes, stock and descriptions.

#### Step 3: Run and download

Set **Max Products** so the first run is cheap, press Run, and export as JSON, CSV or Excel from the dataset tab.

**That's it. Within a couple of minutes you'll have:**

- Every product in your market with price, old price, discount and currency
- Colours, full image galleries and the complete category path
- Sizes with per-SKU stock, when you asked for them
- A run summary telling you exactly what was and was not fetched

### 📥 Input Configuration

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| mode | string | No | `overview` walks the categories, `detail` reads the URLs you paste. Default `overview` |
| country | string | No | zara.com market segment, lowercase — `de`, `us`, `gb`, `jp`. Default `de` |
| language | string | No | Two-letter language for names and descriptions. Empty takes the market default |
| allCategories | boolean | No | Sweep every category. On by default, and it wins over Single Category |
| category | string | No | One Zara category by numeric id or slug. Only used when the sweep is off |
| fromSitemap | boolean | No | Also crawl the product sitemap for anything the categories missed. Bills at the detail rate |
| maxItems | integer | No | Stop after this many distinct products. `0` means no cap. Default `100` |
| withSizes | boolean | No | Fetch per-SKU sizes, stock and the description and merge them into each row. Charges both events |
| productUrls | array | No | Product URLs or bare `?v2=` ids, one per line. Required in `detail` mode |
| sort | string | No | `default`, `price-asc`, `price-desc` or `novelty`. Options vary per category |
| filters | array | No | Facet filters as `GROUP=VALUE`, one per line. Same group OR-ed, different groups AND-ed |
| minPrice | integer | No | Drop products below this price, in the market's major units |
| maxPrice | integer | No | Drop products above this price, in the market's major units |
| jitterMs | integer | No | Random pause before each request, in milliseconds. Default `0` |
| proxyConfiguration | object | No | Leave it off. The Actor reaches Zara directly and a proxy adds cost without adding success |

**Example — sweep the German store:**

```json
{
  "mode": "overview",
  "country": "de",
  "allCategories": true,
  "maxItems": 500
}
```

**Example — one category, discounted items only, with sizes:**

```json
{
  "mode": "overview",
  "country": "gb",
  "allCategories": false,
  "category": "2546081",
  "withSizes": true,
  "maxPrice": 50
}
```

**Example — specific products:**

```json
{
  "mode": "detail",
  "country": "us",
  "productUrls": [
    "https://www.zara.com/us/en/ribbed-tank-top-p04424016.html?v2=418123456",
    "418123456"
  ]
}
```

### 📤 Output

Results are saved to the Apify dataset with **58 columns per product**. Export as JSON, CSV or Excel.

| Field | Type | Description |
|-------|------|-------------|
| brand | string | Brand key stamped on every row. Always `zara` on this Actor |
| product\_id | integer/string | Catalogue id. The only column that is never null — the join key for everything else |
| url | string | Canonical product page for the market you scraped |
| source | string | Which call produced the row: `overview`, `detail`, or `overview+detail` |
| url\_id | integer/string | Numeric URL id used by the six shared-catalogue brands. Null on Zara |
| reference | string | Internal style reference, stable across markets |
| display\_reference | string | The shorter reference printed on the page and the label |
| seo\_product\_id | string | Id used in Zara SEO URLs |
| seo\_keyword | string | URL slug for the product |
| name | string | Product name in the market language |
| name\_en | string | Shared-catalogue brands only, null here |
| product\_type | string | Catalogue type of the record, e.g. Product or Bundle |
| kind | string | Zara grid classification of the tile, e.g. Wear |
| country | string | Market the prices and names belong to |
| language | string | Language the names and descriptions came back in |
| store\_id | integer/string | Internal store id. Shared-catalogue brands only, null here |
| catalog\_id | integer/string | Internal catalogue id. Shared-catalogue brands only, null here |
| section\_name | string | Top level of the catalogue tree, e.g. WOMAN |
| section\_name\_en | string | Shared-catalogue brands only, null here — Zara publishes the section in `section_name` |
| family\_name | string | Product family in the market language |
| family\_name\_en | string | Shared-catalogue brands only, null here — group on `family_name` |
| subfamily\_name | string | Sub-level of the family in the market language |
| subfamily\_name\_en | string | Shared-catalogue brands only, null here |
| categories | array | Shared-catalogue brands only, empty here — Zara reports the scraped category in `category_id` / `category_name` |
| category\_id | integer/string | Id of the category this row was scraped from |
| category\_name | string | Name of the category this row was scraped from |
| price | number | Current price in major units, divisor already applied |
| old\_price | number | Pre-discount price. Null when the product is not reduced |
| currency | string | ISO currency of the market, e.g. EUR, GBP, JPY |
| discount\_pct | number | Percentage off, computed from price and old price |
| on\_special | boolean | Shared-catalogue brands only, null here — use `old_price` and `discount_pct` |
| main\_image | string | First image of the shown colour, full resolution |
| images | array | Every image URL for the shown colour, in catalogue order |
| description | string | Long product description. Grid rows carry none — turn on the size fetch |
| additional\_info | string | Shared-catalogue brands only, null here |
| keywords | string | Shared-catalogue brands only, null here |
| assembly\_url | string | Shared-catalogue brands only, null here |
| color\_name | string | Name of the colour this row represents |
| colors | array | Colour objects with id, name, reference, price, availability and hex |
| available\_color\_names | array | Colour names the grid offers for this style |
| composition | array | Material breakdown per garment part, with the percentage of each fibre. Grid rows carry none — turn on the size fetch |
| care | array | Shared-catalogue brands only, empty here — Zara's care text arrives inside `description` |
| variants | array | One entry per colour and size — see the table below |
| size\_guide | string | Set to `enabled` when the product page offers a size guide. **Detail records only** |
| availability | string | Stock state of the shown colour, e.g. `in_stock`, `low_on_stock` |
| is\_buyable | boolean | Shared-catalogue brands only, null here — use `availability` and per-SKU `availability` |
| back\_soon | boolean | Shared-catalogue brands only, null here |
| visibility | string | Shared-catalogue brands only, null here |
| availability\_date | string | Shared-catalogue brands only, null here — see `first_visible_date` |
| first\_visible\_date | string | When the product first appeared in the catalogue. **Detail records only** |
| is\_continuity | boolean | Carryover line versus seasonal drop. Shared-catalogue brands only, null here |
| is\_pinned | boolean | Whether merchandising pinned the tile to a fixed slot |
| grid\_position | integer | Position of the tile inside the category grid — the raw merchandising rank |
| join\_life | string | Shared-catalogue brands only, null here |
| sustainability\_show | boolean | Shared-catalogue brands only, null here |
| sustainability | object | Shared-catalogue brands only, null here |
| traceability | object | Supply-chain traceability node. Shared-catalogue brands only, null here |
| certified\_materials | array | Certified material entries. Shared-catalogue brands only, null here |

**Inside `variants` — one entry per colour and size (Zara):**

| Field | Description |
|-------|-------------|
| sku | Stock-keeping unit id for this colour and size |
| color / color\_id | Colour name and id of the SKU |
| size / size\_id | Size label as the market prints it, plus Zara's size id |
| price / old\_price | SKU price and pre-discount price in major units |
| availability | Per-SKU stock state |
| reference | Per-SKU reference |
| demand | Zara's own sell-through signal for the SKU |
| equivalent\_size\_id | Cross-market size id — a German S and a US S resolve to the same value |
| twinned\_skus | The same physical SKU under sibling style ids |

**Example row (trimmed):**

```json
{
  "brand": "zara",
  "product_id": 418123456,
  "url": "https://www.zara.com/de/de/ribbed-tank-top-p04424016.html",
  "source": "overview+detail",
  "name": "ÄRMELLOSES RIPP-TOP",
  "price": 12.95,
  "old_price": 19.95,
  "currency": "EUR",
  "discount_pct": 35.1,
  "country": "de",
  "language": "de",
  "family_name_en": "TOPS",
  "color_name": "Ecru",
  "grid_position": 7,
  "first_visible_date": "2026-06-14T00:00:00Z",
  "variants": [
    { "sku": 419881234, "size": "S", "availability": "in_stock", "demand": "DEMAND_REGULAR", "equivalent_size_id": 4 },
    { "sku": 419881235, "size": "M", "availability": "low_on_stock", "demand": "DEMAND_HIGH", "equivalent_size_id": 5 }
  ]
}
```

**Columns to read carefully.** Zara's category grid ships no detail payload at all, so `description`, `variants`, `composition`, `size_guide` and `first_visible_date` are filled on detail records only — a plain overview sweep returns them empty. Switch on **Fetch Sizes & SKUs**, or use `detail` mode, if any of those five is why you came. A further set of columns belongs to the six shared-catalogue brands and is always null on Zara, because zara.com's API does not publish them: `url_id`, `store_id`, `catalog_id`, `name_en`, `section_name_en`, `family_name_en`, `subfamily_name_en`, `categories`, `on_special`, `additional_info`, `keywords`, `assembly_url`, `care`, `is_buyable`, `back_soon`, `visibility`, `availability_date`, `is_continuity`, `join_life`, `sustainability_show`, `sustainability`, `traceability` and `certified_materials`. They are in the schema so one table fits all seven brands.

### 💼 Use Cases & Examples

#### 1. Cross-market price comparison

**A pricing analyst wants to know what the same garment costs in six countries.**

**Input:** the same category id, run once per market
**Output:** price, old price, discount and currency per market, with `country` on every row
**Use:** grey-market spotting, launch pricing, currency-adjusted benchmarks

#### 2. New-arrivals and drop detection

**A trend researcher wants to know what entered the catalogue this week.**

**Input:** a scheduled run with **Fetch Sizes & SKUs** on
**Output:** `first_visible_date` per product
**Use:** diff two runs, keep the new ids, and you have the drop feed without watching the site

#### 3. Size and stock monitoring

**A reseller wants to know which sizes are actually available before sourcing.**

**Input:** product URLs in `detail` mode, or an overview sweep with sizes on
**Output:** per-SKU size, stock state and Zara's own demand signal
**Use:** sourcing decisions, restock alerts, sell-through estimates

#### 4. Assortment and merchandising analysis

**A category manager wants the shape of a competitor's range, not only its contents.**

**Input:** a full category sweep
**Output:** `grid_position`, `is_pinned`, family and subfamily taxonomy, colour counts
**Use:** range width by family, what Zara pushes to the top, colour and price architecture

#### 5. Discount and markdown tracking

**A retail analyst wants to see how deep the season's markdowns run.**

**Input:** a weekly sweep with `maxItems: 0`
**Output:** `old_price` and `discount_pct` across the catalogue
**Use:** markdown cadence, depth by family, comparison against your own calendar

#### 6. Catalogue enrichment

**A marketplace team has Zara references and needs the rest of the record.**

**Input:** references or URLs in `detail` mode
**Output:** description, composition, images, colours, per-SKU sizes
**Use:** filling product pages, feed enrichment, matching against your own catalogue

### 🔗 Integration Examples

#### JavaScript/Node.js

```javascript
import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: 'YOUR_TOKEN' });

const run = await client.actor('sian.agency/zara-product-scraper').call({
  mode: 'overview',
  country: 'de',
  allCategories: true,
  withSizes: true,
  maxItems: 200,
});

const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(`Got ${items.length} products`);
```

#### Python

```python
from apify_client import ApifyClient
client = ApifyClient('YOUR_TOKEN')

run = client.actor('sian.agency/zara-product-scraper').call(
    run_input={
        'mode': 'overview',
        'country': 'gb',
        'allCategories': True,
        'maxItems': 500,
        'maxPrice': 50,
    }
)

for item in client.dataset(run['defaultDatasetId']).iterate_items():
    print(item['name'], item['price'], item['currency'])
```

#### cURL

```bash
curl -X POST 'https://api.apify.com/v2/acts/sian.agency~zara-product-scraper/runs?token=YOUR_TOKEN' \
-H 'Content-Type: application/json' \
-d '{
  "mode": "detail",
  "country": "us",
  "productUrls": ["418123456"]
}'
```

#### Automation Tool Workflows (n8n, Zapier, Make, etc.)

1. **Trigger**: schedule or webhook
2. **HTTP Request**: start a run and wait for the dataset
3. **Process**: diff against last week's `product_id` and `price`
4. **Action**: write to your warehouse, or alert on new arrivals and markdowns

### 📊 Performance & Pricing

[💰 View current pricing](https://apify.com/sian.agency/zara-product-scraper?fpr=sian)

#### Performance

- \~20 products per second on the category sweep
- 512 MB memory, no proxy, no browser — direct API reads
- Duplicates removed before anything is charged, so you pay once per distinct product

#### How you are billed

Three events, and the `source` column on every row tells you which one applied. Count the rows by source and you have rebuilt your own invoice.

| What you ran | `source` on the row | Event | Price |
|---|---|---|--:|
| Run start | — | Actor start | $0.005 once |
| Category or grid sweep | `overview` | Scraped product | **$0.0025** |
| Pasted URL, or a sitemap row | `detail` | Scraped product detail | $0.0075 |
| Sweep row plus its SKU fetch (`withSizes`) | `overview+detail` | both | $0.01 |

**Two switches move a row onto the higher-priced event.** **Also Crawl the Sitemap** cannot use the bulk endpoint — it is one request per product, so those rows bill at $0.0075 instead of $0.0025. **Fetch Sizes & SKUs** genuinely costs both calls and charges both, so those rows cost $0.01. The category sweep is the default and the cheap path; use the sitemap when completeness matters more than price.

#### Cost examples

- **100 products, category sweep**: $0.255
- **1,000 products, category sweep**: $2.505
- **1,000 products with sizes and descriptions**: $10.005
- **100 pasted product URLs**: $0.755

Prices shown are the BRONZE tier. They step down at SILVER, GOLD, PLATINUM and DIAMOND, so heavier use costs less per row.

### ❓ Frequently Asked Questions

**Q: Why are sizes missing from my results?**
A: Zara's category grid genuinely does not carry sizes or descriptions — that is the site, not the scraper. Switch on **Fetch Sizes & SKUs** and each row is enriched with per-SKU sizes, stock and the description.

**Q: Can I search by keyword?**
A: No, and neither can anything else. Zara publishes no server-side search endpoint. Every "Zara search scraper" filters client-side over the category tree, so name a category or sweep them all and filter the results yourself.

**Q: Which markets are supported?**
A: The 96 markets zara.com publishes, read from Zara's own sitemap index rather than guessed. Set **Market** to the first segment of a Zara URL. Prices come back in that market's own currency with the correct divisor applied. (The sibling Actors for the other Inditex brands cover ~216 markets each — those catalogues are open in far more countries than zara.com is.)

**Q: Does it return customer reviews?**
A: No. Zara does not publish ratings or reviews on its product pages, so no scraper can return them. Any actor promising Zara reviews is promising an empty list.

**Q: How do I find a category id?**
A: Open a Zara category page and take the numeric id from the URL, or leave **Sweep All Categories** on and let the Actor walk the tree for you.

**Q: What does `first_visible_date` need?**
A: A detail record. Turn on **Fetch Sizes & SKUs** during a sweep, or use `detail` mode. An overview-only run leaves it null.

**Q: Is the price already converted?**
A: It is already in the market's major units with the correct divisor applied, and `currency` tells you which currency. No conversion between currencies is performed — a Japanese run returns JPY.

**Q: Do I need a proxy?**
A: No. Leave the proxy off. The Actor reaches Zara's endpoints directly from Apify, verified on the platform, and a proxy only adds cost.

**Q: What output formats are available?**
A: JSON, CSV and Excel, exported straight from the dataset. There is also a run summary in the key-value store with the counts for the run.

### 🐛 Troubleshooting

**Zero products returned**

- The category you named is a landing page, not a product grid — those return no ids
- Your filters or price bounds excluded everything; widen them
- Leave **Sweep All Categories** on and let the Actor find the grids

**The run summary says `complete: false`**

- Some fetches failed for transport reasons, so the dataset is short. Re-run to fill the gap
- Ids reported as gone are a different thing: those products no longer exist in that market

**A pasted URL is rejected**

- A Zara URL without `?v2=` carries only an SEO id, which no endpoint accepts. The Actor opens the page once to resolve it, so paste the full URL rather than a fragment
- A bare number is treated as the `?v2=` product id

**The sort or filter option stops the run, or the sweep came back short**

- Sort options and facet groups are published per category, and many Zara categories publish none at all
- If you named a single category and it does not offer the one you picked, the Actor stops and lists what is available there
- During a **Sweep All Categories** run it skips that category instead and counts it under `categoriesSkipped` — so a sort or filter can quietly shrink a sweep. Check that count in the run summary before concluding the catalogue is small

**Sitemap mode is slower and dearer than expected**

- That is the trade: it is one request per product instead of one per hundred, and those rows bill at the detail rate. Use the category sweep unless you need the products no category lists

***

### ⚖️ Is it legal to scrape data?

Our actors are ethical and do not extract any private user data, such as email addresses, gender, or location. They only extract what the user has chosen to share publicly. We therefore believe that our actors, when used for ethical purposes by Apify users, are safe.

However, you should be aware that your results could contain personal data. Personal data is protected by the **GDPR** in the European Union and by other regulations around the world. You should not scrape personal data unless you have a legitimate reason to do so. If you're unsure whether your reason is legitimate, consult your lawyers.

You can also read Apify's blog post on the [legality of web scraping](https://blog.apify.com/is-web-scraping-legal/).

**Trademarks.** Zara is a trademark of Industria de Diseño Textil, S.A. This Actor is an independent tool. It is not affiliated with, endorsed by or sponsored by Inditex or any of its brands, and it reads only publicly available catalogue pages.

***

### 🤝 Support

[![Telegram Support](https://img.shields.io/badge/Telegram-Support%20Group-0088cc?logo=telegram)](https://t.me/+vyh1sRE08sAxMGRi)

**Join our active support community**

- 🐛 Found a bug? File an issue in the Apify Console Issues tab
- ⭐ Loving the tool? Leave a 5-star review — it helps us build more
- Check [SIÁN Agency Store](https://apify.com/sian.agency?fpr=sian) for more automation tools
- 📧 <apify@sian-agency.online>

***

**Built by [SIÁN Agency](https://www.sian-agency.online)** | **[More Tools](https://apify.com/sian.agency?fpr=sian)**

# Actor input Schema

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

**Overview** walks the category tree (and optionally the sitemap) and returns every product it finds.

**Detail** takes the product URLs you paste below and returns one full record each. Detail mode needs at least one URL or it stops immediately.

## `country` (type: `string`):

Two-letter zara.com market, lowercase — the first segment of a Zara URL. `de` for zara.com/de, `us` for zara.com/us.

Prices, names and stock are per market, so the `country` column travels with every row.

## `language` (type: `string`):

Two-letter language for names and descriptions. Leave empty to take the market default: `de` on zara.com/de, `en` on most other stores.

An unsupported code stops the run with the list the market does support.

## `allCategories` (type: `boolean`):

Walk every category in the tree. On by default so a bare run returns data.

**This wins over the single category below.** Turn it off to scrape one category.

Categories that are containers rather than product grids return nothing and are skipped, which is normal — the run summary counts them under `categoriesSkipped`.

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

One Zara category, by numeric id or slug. Only grid categories hold products; landing pages return nothing.

Turn off **Sweep All Categories** above or this field is ignored.

## `fromSitemap` (type: `boolean`):

After the categories, read the product sitemap and fetch everything the categories missed.

This is the expensive half of a full-catalogue run: each sitemap product costs two extra requests instead of riding a bulk call, so those rows are charged as the "Scraped product detail" event at $0.0075 instead of $0.0025 — 3× the category-sweep price.

Use it when you want the complete catalogue rather than what merchandising currently surfaces.

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

Stop after this many products. `0` means no cap — the run goes until the catalogue is exhausted.

Duplicates are removed before the cap is counted, so the number you set is the number of distinct products you get.

## `withSizes` (type: `boolean`):

Zara's grid ships no sizes and no description. Switch this on and the actor fetches the detail record for every product, ten ids per request, and merges it into the grid row.

That adds per-SKU sizes, stock, the description, Zara's demand signal, twinned SKUs and the first-seen date. It costs one request per ten products.

Billing: these rows genuinely cost both calls and are charged both events — $0.0025 + $0.0075 = $0.01 per product.

## `productUrls` (type: `array`):

One product per line. A full Zara product URL works, and so does the bare `?v2=` number.

A Zara URL without `?v2=` carries only the SEO id, which no endpoint accepts, so the actor opens the page once to resolve it. That is one extra request per URL.

## `sort` (type: `string`):

Zara publishes a pre-sorted id list per sort option; there is no server-side sort parameter. Sort options are per category, and many categories publish none at all.

If you named a single category and it does not offer the sort you picked, the run stops and prints what it does offer. During a **Sweep All Categories** run the category is skipped instead and counted under `categoriesSkipped`, so a sort can quietly shrink a sweep — check that count in the run summary.

## `filters` (type: `array`):

Facet filters as `GROUP=VALUE`, one per line. Values in the same group are OR-ed, different groups are AND-ed.

Zara ships each facet value with its own product ids, so filtering is a set intersection, not a query parameter. Use the group ids Zara publishes — `color`, `size` and the dynamic grid groups.

Groups and values are per category, and many publish none. A group the category does not offer stops the run and prints the ones it does. For price, use Min and Max below.

## `minPrice` (type: `integer`):

Drop products cheaper than this, in major units of the market currency. Leave empty for no floor.

## `maxPrice` (type: `integer`):

Drop products dearer than this, in major units of the market currency. Leave empty for no ceiling.

## Actor input object example

```json
{
  "mode": "overview",
  "country": "de",
  "language": "",
  "allCategories": true,
  "category": "2546081",
  "fromSitemap": false,
  "maxItems": 100,
  "withSizes": false,
  "sort": "default",
  "filters": [
    "color=Schwarz"
  ]
}
```

# Actor output Schema

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

One row per product: price, old price, currency, discount, images, taxonomy, colours, per-SKU sizes and stock.

## `runSummary` (type: `string`):

Your run at a glance: products returned, ids that no longer exist, fetches that failed and how to retry them, how each row was fetched, and an itemized statement of what you paid.

# 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": "overview",
    "country": "de",
    "language": "",
    "maxItems": 100,
    "sort": "default"
};

// Run the Actor and wait for it to finish
const run = await client.actor("sian.agency/zara-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 = {
    "mode": "overview",
    "country": "de",
    "language": "",
    "maxItems": 100,
    "sort": "default",
}

# Run the Actor and wait for it to finish
run = client.actor("sian.agency/zara-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 '{
  "mode": "overview",
  "country": "de",
  "language": "",
  "maxItems": 100,
  "sort": "default"
}' |
apify call sian.agency/zara-product-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,sian.agency/zara-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/8Tnsw9dJTE5zrpzhE/builds/TDSi7loXYrgNdWX00/openapi.json
