Zara Products Scraper avatar

Zara Products Scraper

Pricing

from $1.75 / 1,000 results

Go to Apify Store
Zara Products Scraper

Zara Products Scraper

Zara catalogue products from any country store: price and currency, previous price and discount, colours, images and category path. The store that answered is verified on every run -- an unknown country code is served by Zara's Spanish store, at euro prices, without an error.

Pricing

from $1.75 / 1,000 results

Rating

0.0

(0)

Developer

Ibnu Adzim

Ibnu Adzim

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

3 days ago

Last modified

Categories

Share

Zara's catalogue, from any of its country stores: product name, reference, price in the store's own currency, the previous price and discount where there is one, every colourway, resolved image URLs, and the category path the product sits under.

Built on Zara's own storefront JSON. HTTP only — no browser, no JavaScript.

What it is for

  • Price monitoring across markets — the same garment at US, UK, German and Japanese prices, each in the right currency and the right units.
  • Sale trackingonlyDiscounted returns just the reduced items, with what they cost before and the percentage off.
  • Assortment analysis — which categories carry what, by section, with the full menu path.

Input

fieldwhat it does
countryTwo-letter code as in a Zara URL: us, gb, de, fr, jp, kr, br
languageLanguage segment for that store: en, de, ja, ko
categoryIdsZara's internal numeric category ids.
categoryUrlsZara category pages — the id is resolved through the store's own tree.
sectionsDiscovery only: narrow to WOMAN, MAN, KIDS, …
onlyDiscountedKeep only products with a previous price.
includeBundlesInclude "look" bundles, which are not garments.
maxItems, maxConcurrency, minRequestIntervalLimits and pacing.

Leave categoryIds and categoryUrls empty and the run becomes a discovery pass: it returns every category in the store with its id, name, full menu path and page URL. Pick the ids you want and run it again.

Four things about this data worth knowing before you trust a run

1. An unknown country code is served by Spain, not refused

/{cc}/{lang}/… accepts any two-letter code. Ones Zara does not operate are answered — HTTP 200, real products, real prices — by the Spanish store:

requestedstore that actually answeredcurrency
usus (11719)USD
dede (10705)EUR
jpjp (11723)JPY
zz, qq, aaes (10701)EUR

352 of the 374 product ids overlap the US set, so the names look right. Only the prices are from another country. A three-or-more-letter code 404s honestly, which is exactly what makes the two-letter case dangerous: it is the shape a real code has.

Every run therefore begins with one request that reads back which store actually answered, and stops if it is not the one you asked for.

2. The price is in cents — except where it is not, and nothing says which

"price": 3990 is $39.90 in the US store and ¥3,990 in the Japanese one. JPY and KRW have no minor unit, so the same integer means two things a hundredfold apart. Measured over one category's first 40 prices:

storeprices end inreading
us90 (39/40)$39.90 — divide by 100
gb99 (40/40)£29.99 — divide by 100
de95 (40/40)€19.95 — divide by 100
jp1590 … 7990¥1,590 — do not divide
kr15900 … 59900, all 00₩15,900 — do not divide

And the products payload contains no currency field at all — searching the whole 1.9 MB response for currency returns nothing. So there is no way to read the exponent from the data and no way to audit the arithmetic afterwards.

The currency comes from the same store probe as above, the exponent from the ISO 4217 table, and every row keeps priceMinorUnits — the untouched upstream integer — so you can check the division yourself without re-fetching.

3. The discount is not where the price is

The top-level price is already the reduced one. oldPrice, discountPercentage and discountLabel live a level down, per colour. A top-level read gets the right number and loses the entire fact that the item is on sale:

SHORT SLEEVE CUT OUT TOP price 23.94 oldPrice 39.90 -40%
COMBINATION KNIT TOP price 27.54 oldPrice 45.90 -40%

Both levels are read, and both are in the output.

4. There are two category trees and they disagree

treedistinct ids
/{cc}/{lang}/categories?ajax=true2,199
/itxrest/1/catalog/store/{id}/category1,922
in both853

Validating an id against either one alone rejects about half the real ones — id 2419939 is absent from the first, present in the second, and returns 374 products. Both are loaded and merged.

An id in neither is still fetched, because the 404 is not reliable either: 999999999 and 2419941 404, but 2419940 returns byte-for-byte the same payload as 2419939. An id adjacent to a real one silently serves its neighbour, and the response echoes nothing identifying what was requested. So every summary carries productGroupId — two targets that alias share it, which is the only way the collision is visible — and categoryIdVerified says whether the id was in a tree at all.

Output

Four record types in one dataset, told apart by recordType:

  • PRODUCT — name, reference, price + priceMinorUnits + currency, oldPrice / discountPercentage / discountLabel, colors[], availableColors[], resolved images[], productUrl, categoryPath.
  • CATEGORY — a discovery row: id, name, full menu path, section, isProductGrid, categoryUrl.
  • CATEGORY_SUMMARY — one per harvested category: storeCountry, currency, currencyIsZeroDecimal, componentsSeen, productsReturned, bundlesSkipped, discountedRows, productGroupId, categoryIdVerified, bytesRead.
  • ERROR — one row naming what went wrong, instead of a silent empty.

Technical notes

  • HTTP-only, curl_cffi with chrome124. Five TLS profiles were 200 cold on both the storefront and the JSON; Akamai fronts the site but neither surface challenged from a plain IP.
  • No pagination. A category arrives in one response — the largest measured was 4.5 MB for 802 products. Keep maxConcurrency low: the memory cost is per concurrent category, not per page.
  • Proxy is optional and off by default. If you enable it, leave the pool unpinned: the store is chosen by the country segment in the URL, not by the exit IP, and every run verifies which store answered anyway.
  • robots.txt was read in full on 2026-09-16, comments included. No AI-bot group, no blanket disallow. Both paths this Actor reads are allowed.

Known limits

  • No size-level stock. /itxrest/*/availability and /itxrest/*/sizing-info are disallowed by Zara's robots.txt, so availability is reported only at the coarse level the listing itself publishes (in_stock and similar). That is a policy limit, not a missing feature.
  • No keyword search. Zara's search runs on a separate host that does not resolve publicly; only category browsing is reachable.
  • Bundles ("looks") are excluded by default. They are not garments, and they come back both priced and price-less, so mixing them in distorts averages.