Tony Wang6 min readHow to Scrape H&M in 2026 (API & Python)
Scrape H&M product search, category listings, and per-color pricing and stock in 2026 — DIY Python, no-code tools, or a structured API.
The fastest way to scrape H&M in 2026 is to call a structured API that returns normalized JSON for keyword search, category listings, and full product detail — instead of parsing H&M's storefront pages yourself. H&M's app-backend data is rich (per-color pricing, live per-size stock, real customer reviews) but there's no public developer program to request it through, no category-tree endpoint to discover what's browsable, and the site runs real anti-bot infrastructure in front of it. This guide covers the DIY approach and where it breaks, a no-code option, and a structured H&M API, plus what's actually legal to collect.
Why scrape H&M?
- Pricing intelligence — track how a garment's price moves across colors and over time, including markdowns.
- Assortment and category research — see what a category actually carries and how counts shift by season.
- Size-level stock monitoring — per-size, per-color availability tells you which sizes sell out first, not just whether a product is "in stock."
- Review and sentiment analysis — pull rating trends and review text for a specific product or product line.
- Fashion-retail competitive benchmarking — compare H&M's catalog breadth and pricing against Zara, Zalando, and other fast-fashion retailers.
Is it legal to scrape H&M?
Option 1: DIY in Python (and why it breaks)
H&M's product pages don't expose a stable public JSON endpoint, so a DIY scraper has to fetch and parse the rendered page:
import requests
from bs4 import BeautifulSoup
resp = requests.get(
"https://www2.hm.com/en_us/productpage.1227171001.html",
headers={"User-Agent": "Mozilla/5.0 (compatible; research-bot/1.0)"},
)
soup = BeautifulSoup(resp.text, "html.parser")
# Per-color price, per-size stock, and reviews are hydrated from
# app-backend calls, not consistently exposed as selectable markup
It demos and then breaks:
- The Terms explicitly ban bots and crawlers. H&M's ToS names "spiders, bots, crawlers, avatars or intelligent agents" directly — this isn't a vague clause you can argue around, and violating it risks an immediate access bar.
- Real anti-bot infrastructure fronts the site. A naive, unauthenticated
requestscall gets challenged or blocked quickly, and a browser-based scraper needs ongoing upkeep as the defense updates. - No category-tree endpoint to discover what's browsable. H&M doesn't publish a nav-tree or category lookup call — you either already know the category slug (from a storefront URL like
ladies_jeansormen_newarrivals_all) or you don't have a way in. - Per-color, per-size data isn't in one flat field. A product page's real detail — each purchasable color with its own price and per-size stock — is structured data hydrated client-side, not a value you can grab with one selector.
- No official developer program. H&M has no self-serve public API for its storefront catalog, so there's no sanctioned channel to request programmatic access as an outside developer.
Option 2: No-code tools
Browser extensions and point-and-click scrapers can export a page of H&M search results for a one-off pull, but they don't resolve category slugs for you, don't normalize per-color/per-size structure, and inherit the same anti-bot fragility as DIY — not something you'd want to run on a schedule.
Option 3: A structured H&M API
For a repeatable pipeline, Crawlora's H&M API turns H&M's own app-backend storefront data into structured JSON — keyword search, category listings, and full product detail — without page parsing or bot-defense upkeep. Search by keyword:
curl "https://api.crawlora.net/api/v1/hm/search?query=denim%20jacket" \
-H "x-api-key: $CRAWLORA_API_KEY"
{
"code": 200,
"msg": "OK",
"data": {
"query": "denim jacket",
"count": 24,
"total_count": 187,
"products": [
{
"id": "1227171001",
"name": "Relaxed Fit Denim Jacket",
"price": 44.99,
"currency": "USD",
"url": "https://www2.hm.com/en_us/productpage.1227171001.html",
"image": "https://lp2.hm.com/hmgoepprod?set=source[/33/44/example.jpg]",
"colors": [
{ "color": "Denim blue", "product_id": "1227171001", "in_stock": true },
{ "color": "Black", "product_id": "1227171002", "in_stock": true }
]
}
]
}
}
Unlike category browsing, search is honest about a dead end — pass an obscure or nonsense keyword and you get a genuine empty result, not a recommended-products fallback.
Browse a category by slug (there's no discovery endpoint for this — category_id values come from known storefront paths, not a lookup call):
import requests
h = {"x-api-key": "YOUR_API_KEY"}
base = "https://api.crawlora.net/api/v1/hm"
listing = requests.get(f"{base}/listing", headers=h, params={"category_id": "ladies_jeans"}).json()["data"]
product_id = listing["products"][0]["id"]
detail = requests.get(f"{base}/product/{product_id}", headers=h).json()["data"]
A product-detail response is where the real structure lives — every purchasable color grouped with its own real per-size price and live availability, plus reviews when the product has any (confirm exact fields in the docs):
{
"code": 200,
"msg": "OK",
"data": {
"product_id": "1227171001",
"name": "Relaxed Fit Denim Jacket",
"colors": [
{
"color": "Denim blue",
"product_id": "1227171001",
"price": 44.99,
"currency": "USD",
"sizes": [
{ "size": "XS", "in_stock": true, "stock_quantity": 12 },
{ "size": "S", "in_stock": true, "stock_quantity": 4 },
{ "size": "M", "in_stock": false, "stock_quantity": 0 }
]
},
{
"color": "Black",
"product_id": "1227171002",
"price": 44.99,
"currency": "USD",
"sizes": [
{ "size": "XS", "in_stock": true, "stock_quantity": 7 }
]
}
],
"rating": 4.2,
"review_count": 38,
"reviews": [
{
"author": "J.",
"rating": 5,
"text": "True to size, good quality denim for the price.",
"date": "2026-06-02"
}
]
}
}
Search and listing only give you one representative price and a per-color stock count — call product detail on the id (or the digits from a productpage.<id>.html URL) whenever you need real per-size price and stock. Store one row per color per pull, keyed by product_id, and re-run on a schedule to track price changes and size sellouts.
What you can collect
Public storefront data: search results (id, name, price, currency, image, per-color stock count) with a genuine empty result on a bad query; category listings by known category_id slug; and full product detail — every color's real per-size price and live availability, plus aggregate rating and customer reviews when the product has any. Public product-page data only — not account, cart, or checkout information.
Limitations and common challenges
- No category-tree discovery endpoint. H&M doesn't expose a way to enumerate categories —
category_idslugs likeladies_jeansormen_newarrivals_allhave to be sourced from known storefront paths, so build and maintain your own slug list. - Real anti-bot infrastructure on the front end. Expect challenges on naive or high-volume automated requests directly against H&M's site.
- Search and listing aren't the full picture. They carry one representative price and a stock count per color — treat them as a discovery layer and pull product detail for accurate per-size price and availability.
- Reviews aren't guaranteed. Many products have none; check
review_countbefore assuming review data will be present. - The ToS explicitly names bots and crawlers. Treat that as a real constraint, not boilerplate — stay within public product-page facts and respect rate limits.
Where this gets used
- Pricing intelligence — track per-color
priceand markdowns on a product line over a season. - Size-level stock monitoring — watch
sizes[].in_stockandstock_quantityto see which sizes sell out first. - Fast-fashion competitive benchmarking — compare category assortment and pricing against Zara and Zalando.
Sources
Start collecting
Try it first, free: run any public URL through the Free Web Scraper, or check whether a site blocks bots with the Anti-Bot Checker — no signup.
H&M data pairs well with other fashion-retail APIs for cross-platform research — see how to scrape Zalando for a 25-market fashion marketplace, or how to scrape Zara for the closest fast-fashion comparison. Test the search, listing, and product endpoints in the Playground, check the schema in the API docs, and review pricing. See also how to choose a web scraping API and is web scraping legal.
Part of our how-to-scrape guide series — every platform we cover, in one index.
Frequently asked questions
How do I browse H&M categories with an API?
Pass a known category slug to Crawlora's /hm/listing endpoint — H&M doesn't expose a category/nav-tree discovery call, so category_id values (e.g. ladies_jeans, men_newarrivals_all) are sourced from known storefront paths rather than a lookup call.
Does H&M search return empty results for an obscure keyword?
Yes — unlike category browsing, /hm/search returns a genuine empty result (zero products) for an obscure or nonsense keyword, rather than falling back to a recommended set.
Can I get per-size stock and customer reviews for an H&M product?
Yes — /hm/product/{product_id} returns every purchasable color grouped with its own real per-size price and live availability, plus an aggregate rating and customer reviews when the product has any. /hm/listing and /hm/search only carry one representative price and a per-color stock count.