Zara Products Scraper
Pricing
from $1.75 / 1,000 results
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
Maintained by CommunityActor 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 tracking —
onlyDiscountedreturns 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
| field | what it does |
|---|---|
country | Two-letter code as in a Zara URL: us, gb, de, fr, jp, kr, br… |
language | Language segment for that store: en, de, ja, ko… |
categoryIds | Zara's internal numeric category ids. |
categoryUrls | Zara category pages — the id is resolved through the store's own tree. |
sections | Discovery only: narrow to WOMAN, MAN, KIDS, … |
onlyDiscounted | Keep only products with a previous price. |
includeBundles | Include "look" bundles, which are not garments. |
maxItems, maxConcurrency, minRequestInterval | Limits 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:
| requested | store that actually answered | currency |
|---|---|---|
us | us (11719) | USD |
de | de (10705) | EUR |
jp | jp (11723) | JPY |
zz, qq, aa | es (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:
| store | prices end in | reading |
|---|---|---|
| us | 90 (39/40) | $39.90 — divide by 100 |
| gb | 99 (40/40) | £29.99 — divide by 100 |
| de | 95 (40/40) | €19.95 — divide by 100 |
| jp | 1590 … 7990 | ¥1,590 — do not divide |
| kr | 15900 … 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
| tree | distinct ids |
|---|---|
/{cc}/{lang}/categories?ajax=true | 2,199 |
/itxrest/1/catalog/store/{id}/category | 1,922 |
| in both | 853 |
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[], resolvedimages[],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_cffiwithchrome124. 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
maxConcurrencylow: 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/*/availabilityand/itxrest/*/sizing-infoare disallowed by Zara's robots.txt, so availability is reported only at the coarse level the listing itself publishes (in_stockand 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.