Retail pricing and availability monitoring
Use H&M endpoints to turn retail pricing and availability monitoring into repeatable API requests with documented inputs and JSON responses.
Turn H&M's own app-backend storefront data into structured retail data — keyword product search, category listing pages, and per-product detail with every color's live per-size price and stock plus real customer reviews, all as normalized JSON. Credential-free.
Search H&M products, browse category listings, and get full product detail — per-color pricing, live per-size stock, and customer reviews — as structured JSON.
Endpoint families
5
Documented params
23
Examples
7
Live catalog snapshot
Active endpoints
7
Methods
GET
Required params
11
Schema refs
7
{
"platform": "H&M",
"endpoint": "hm-search",
"method": "GET",
"path": "/hm/search",
"auth": "apiKey"
}Use cases
Search H&M products, browse category listings, and get full product detail — per-color pricing, live per-size stock, and customer reviews — as structured JSON.
Use H&M endpoints to turn retail pricing and availability monitoring into repeatable API requests with documented inputs and JSON responses.
Use H&M endpoints to turn category catalog and product research into repeatable API requests with documented inputs and JSON responses.
Use H&M endpoints to turn review and rating tracking into repeatable API requests with documented inputs and JSON responses.
Managed execution
Every figure below is read from the live H&M endpoint catalog — 7 endpoints, 23 documented request parameters, and 7 published response schemas — the same catalog Docs and Playground run against.
7 documented H&M endpoints, grouped into 5 request families — Product, Search and Categories, plus 2 more.
23 request parameters are documented across those H&M endpoints, 11 of them required — the full input contract is public before you write any integration code.
7 of the 7 H&M endpoints ship a recorded example response, and 7 carry a documented response schema — you can code against the real JSON before the first request.
H&M endpoints document their error responses (400, 404, 429 and 503) alongside the success schema, so a block, a rate limit, or a missing record comes back as a typed error rather than silently empty data.
7 hosted MCP tools back the H&M endpoints, so an agent can call the same routes with the same parameters and the same JSON contract, with no custom glue.
Coverage map
These cards are generated from the active endpoint catalog, so the landing page reflects the same API surface used by Docs and Playground.
/hm/product/{product_id}
/hm/search
/hm/categories
/hm/listing
/hm/stores
Endpoint catalog
/hm/searchRuns a free-text keyword search against H&M's own app-backend search data and returns normalized products with pricing, images, colors, and per-size stock, plus search-quality metadata (a spelling-correction suggestion, related searches, and a content-filter flag). Unlike category browsing, an obscure or nonsense keyword returns a genuine empty result (zero products) rather than a fallback set. Pagination is page-based and real: requesting a page beyond the real last page returns a normal response with an empty products array rather than an error.
Response notes
- Unlike category browsing, an obscure or nonsense keyword returns a genuine empty result (`total_pages`, `total_hits`, and `products` all zero/empty) rather than a fallback or recommended set. - Pagination is real and page-based: the same `page` returns identical results on repeat requests, and different pages return different, non-overlapping products. - Requesting a `page` beyond the real last page returns a normal `200` with an empty `products` array. `total_pages` and `total_hits` stay at their real, nonzero values in that case, distinguishing it from a genuinely empty search, where both are `0`. - `search_meta.did_you_mean` and `search_meta.related_searches` are spelling-correction and related-query suggestions from H&M's own search backend -- they are commonly empty arrays. - `search_meta.blocked` reflects H&M's own content-filter flag for the query; its exact trigger conditions are not documented by H&M. - `products[].id` can carry a leading zero, so it is returned as a string, not a number. - `products[].colors[]` lists every purchasable color for that product's own search entry, each with its own image and product-page URL. - `products[].sizes[]` lists every size H&M's search result offers for the displayed color, each with its own live stock count. Example response: ```json {"code":200,"msg":"OK","data":{"query":"jeans","page":1,"page_size":2,"total_pages":428,"total_hits":1282,"count":2,"search_meta":{"query":"jeans","blocked":false},"source_url":"https://api.hm.com/search-services/v1/en_us/search/resultpage?query=jeans...","fetched_at":"2026-08-10T07:20:00Z","products":[{"id":"1353272003","name":"Loose-Fit Wide-Leg Jeans","brand":"H&M","url":"https://www2.hm.com/en_us/productpage.1353272003.html","image_url":"https://image.hm.com/assets/hm/f0/6c/f06c95bea9e108346fe16cbeea3b3a29b6e93c55.jpg","price":19.99,"formatted_price":"$19.99","currency":"USD","availability":"Available","colors":[{"article_id":"1353272003","name":"Light denim blue/polka dot","color_code":"80AAD8","url":"https://www2.hm.com/en_us/productpage.1353272003.html","image_url":"https://image.hm.com/assets/hm/f0/6c/f06c95bea9e108346fe16cbeea3b3a29b6e93c55.jpg"}],"sizes":[{"id":"008","label":"1½-2Y","stock":2}]}]}} ```
MCP tool hm_search
/hm/listingReturns one H&M category's product listing page: normalized products with pricing, images, colors, and per-size stock, sourced from H&M's own app-backend listing data. category_id is an H&M category slug (e.g. ladies_newarrivals_all, men_newarrivals_all, ladies_jeans) -- this build does not expose a category/nav-tree discovery endpoint, so category_id values are currently sourced from known H&M storefront paths rather than a lookup call. Pagination is page-based and real: requesting a page beyond the category's real last page returns a normal response with an empty products array rather than an error.
Response notes
- Pagination is real and page-based: the same `page` returns identical results on repeat requests, and different pages return different, non-overlapping products. - Requesting a `page` beyond the category's real last page returns a normal `200` with an empty `products` array. `total_pages` and `total_hits` stay at their real, nonzero values in that case, distinguishing it from `category_id` pointing at an invalid or empty category, where both are genuinely `0`. - `products[].id` can carry a leading zero, so it is returned as a string, not a number. - `products[].colors[]` lists every purchasable color for that product's own listing entry, each with its own image and product-page URL. - `products[].sizes[]` lists every size H&M's listing offers for the displayed color, each with its own live stock count. Example response: ```json {"code":200,"msg":"OK","data":{"category_id":"ladies_jeans","page":1,"page_size":2,"sort":"RELEVANCE","total_pages":195,"total_hits":585,"count":2,"source_url":"https://api.hm.com/search-services/v1/en_us/listing/resultpage?categoryId=ladies_jeans...","fetched_at":"2026-08-10T06:00:00Z","products":[{"id":"1045459086","name":"Harper High Rise Wide Leg Jeans","brand":"H&M","url":"https://www2.hm.com/en_us/productpage.1045459086.html","image_url":"https://image.hm.com/assets/hm/d9/cb/d9cbd5615ab3ae695b2ffee69245ef11a800d424.jpg","price":34.99,"formatted_price":"$34.99","currency":"USD","availability":"Available","new_arrival":false,"category_code":"ladies_jeans_wide","colors":[{"article_id":"1045459086","name":"Dark brown","color_code":"54443D","url":"https://www2.hm.com/en_us/productpage.1045459086.html","image_url":"https://image.hm.com/assets/hm/d9/cb/d9cbd5615ab3ae695b2ffee69245ef11a800d424.jpg"}],"sizes":[{"id":"003","label":"4","stock":2}]}]}} ```
MCP tool hm_listing
/hm/product/{product_id}Returns one H&M product's full detail: every purchasable color grouped with its own per-size price and live availability, plus an aggregate rating and real customer reviews (author label, date, body, rating, and any fit-feedback tags the reviewer left, such as "True to Size") when the product has any. This data is not available from hm-listing or hm-search, which only carry one representative price and a per-color stock count. product_id is the numeric id from a listing/search result's id field or its url field's productpage.<id>.html segment. An unrecognized product_id returns 404.
Response notes
- `colors` groups every purchasable color of the base product, with each color's `sizes[]` carrying its own real per-SKU price and live availability -- unlike listing/search, which only carry one representative price and a per-color stock count for the whole product. - A product that only varies by size, not color, groups under a single `colors[0]` entry with an empty `name`. - `rating` is present only when the product has at least one review; a product with none omits it entirely rather than sending a zero value. Responses can come from either of two sources depending on upstream availability; one of them never carries rating/review data, so its absence does not always mean the product genuinely has none. - `reviews[].author` is a plain display label (e.g. `"Verified Buyer"`), not a personal name -- H&M does not expose reviewer names through this data. - `reviews[].dimensions[]`, when present, is fit feedback the reviewer left alongside their review text (e.g. `{"label":"True to Size","value":"True to Size"}`) -- not every review carries this. - `availability` values are normalized from schema.org's full URL form (e.g. `https://schema.org/InStock`) down to the bare name (e.g. `InStock`, `OutOfStock`). - An unrecognized `product_id` returns `404`. A non-numeric or missing `product_id` returns `400` before any upstream request is made. Example response: ```json {"code":200,"msg":"OK","data":{"product_id":"1268470004","name":"Finn Relaxed Fit Jeans","description":"Relaxed-fit jeans in washed cotton denim.","brand":"H&M","material":"Cotton","pattern":"Solid-color","gender":"male","url":"https://www2.hm.com/en_us/productpage.1268470004.html","source_url":"https://www2.hm.com/en_us/productpage.1268470004.html","fetched_at":"2026-08-10T08:00:00Z","rating":{"value":5,"count":10},"reviews":[{"author":"Verified Buyer","date":"2025-10-31","body":"Great fit, true to size.","rating":5,"dimensions":[{"label":"True to Size","value":"True to Size"}]}],"colors":[{"name":"Dark denim blue","image_url":"https://image.hm.com/assets/hm/...jpg","sizes":[{"sku":"1268470001008","size":"1½-2Y","price":19.99,"currency":"USD","availability":"OutOfStock","url":"https://www2.hm.com/en_us/productpage.1268470001.html"}]}]}} ```
MCP tool hm_product
/hm/categoriesReturns H&M's own storefront category navigation, department by department: every direct nav item and subcategory currently shown in the site's own menu, with its display name and storefront URL. Where this build has separately verified the value against hm-listing's own category_id parameter, that id is included too; category_id is omitted for entries not yet verified rather than guessed, since the visible category label is confirmed NOT a reliable way to derive H&M's real listing category ids for every category. department, when given, filters the result to one department.
Response notes
- Each entry's `section` is the nav group it lives under (e.g. `"Clothing"`, `"Accessories"`, `"Shoes"`), and is empty for a department's own direct nav item (e.g. `"New in"`). - `category_id`, when present, is the value to pass as `hm-listing`'s own `category_id` query parameter. It is included only where separately verified against `hm-listing`'s upstream, and is omitted -- not guessed -- for every other live nav entry, since the visible category label is confirmed not to reliably derive H&M's real listing category id for every category (for example, "T-shirts & Tops" resolves to `men_tshirtstanks`, not a slug built from the label). - Nav depth genuinely differs by department: Women and Men are two levels deep (department > group > leaf), Home and Beauty are one level deep (department > leaf directly), and Kids is deeper still (department > age/gender group > age-band group > leaf). A group node that is itself a real, directly browsable page (for example Kids's "2-8 years") appears both as its own entry and as the `section` for its own children. - The navigation itself reflects H&M's live site on every request; only the `category_id` enrichment is a periodically-refreshed reference table, so a brand-new category may appear with a name and URL before its `category_id` has been separately verified. - `source_url` reflects which of two upstream sources actually served the request: H&M's own credential-free Android-app navigation feed (`source_url` starting `https://app2.hm.com/...`), tried first, or the www2.hm.com web storefront's own shared header nav (`source_url` starting `https://www2.hm.com/...`), used as a fallback only if the app feed is unavailable. Both sources are kept in sync with the live site and produce the same response shape. Example response: ```json {"code":200,"msg":"OK","data":{"source_url":"https://app2.hm.com/content/hmonline/en_us/apis/navigation/v5/nav-data.json","fetched_at":"2026-08-15T08:00:00Z","categories":[{"department":"women","section":"","name":"New in","url":"https://www2.hm.com/en_us/ladies/new-arrivals.html"},{"department":"women","section":"Clothing","name":"Dresses","url":"https://www2.hm.com/en_us/ladies/shop-by-product/dresses.html","category_id":"ladies_dresses"}]}} ```
MCP tool hm_categories
/hm/product/{product_id}/relatedReturns every product-detail recommendation list H&M's own app shows for one product (which lists are present genuinely varies by product -- for example "more from series" and "style with" appear only when the product has one, while "alternatives" and "upsell" are more consistently present). An unrecognized product_id returns a well-formed empty result rather than an error.
Response notes
- Which lists are present genuinely varies by product, not a fixed set. A product with a same-series companion piece returns all four kinds seen so far -- `product-page-more_from_series`, `product-page-style_with`, `product-page-alternatives`, `product-page-upsell` -- while a product without one (for example jeans, tested live) returns only `product-page-alternatives` and `product-page-upsell`. - `lists[].products[]` uses the same normalized product shape `hm-listing`/`hm-search` already establish (pricing, images, colors, per-size stock). - An unrecognized `product_id` returns a well-formed empty `lists` array rather than an error. Example response: ```json {"code":200,"msg":"OK","data":{"product_id":"1268470004","source_url":"https://api.hm.com/search-services/v1/en_us/recos/product-page?productKey=1268470004...","fetched_at":"2026-08-18T00:00:00Z","lists":[{"label":"product-page-alternatives","products":[{"id":"1351472002","name":"Knit Polo Shirt","brand":"H&M","url":"https://www2.hm.com/en_us/productpage.1351472002.html","image_url":"https://image.hm.com/assets/hm/aa/2f/aa2fdf2440fa3bb4ca4c494b8dbbec2549ce1ae8.jpg","price":19.99,"formatted_price":"$19.99","currency":"USD","availability":"Available"}]}]}} ```
MCP tool hm_product_related
/hm/search/suggestionsReturns H&M's own search-box typeahead suggestions, sourced from the same credential-free app-backend host as hm-listing/hm-search. When query is given, returns spelling-complete phrase suggestions and merchandised content results. When query is omitted or empty, instead returns trending searches and popular-search shortcuts (phrase/content suggestions are both empty in that mode). search_history is part of the real upstream response but confirmed NOT session-scoped -- it returned the identical list across separate cookie-free requests, so treat it as fixed default content rather than a real per-caller history.
Response notes
- With `query` given, the response carries `phrase_suggestions` (spelling-complete phrases) and `content_suggestions` (merchandised results). `trending_searches` and `popular_searches` are both empty in this mode. - With `query` omitted or empty, the response instead carries `trending_searches` and `popular_searches`. `phrase_suggestions` and `content_suggestions` are both empty in this mode. - `search_history` is part of the real upstream response but confirmed NOT session-scoped: separate cookie-free requests returned the identical list, so treat it as fixed default content, not a real per-caller search history, despite the field name. - `blocked` mirrors the same content-filter flag `hm-search`'s own `search_meta.blocked` documents; its exact trigger conditions are not documented by H&M. - `content_suggestions[]`/`popular_searches[]` entries do not all carry every field -- `link`, `deep_link`, `image_url`, and `content_type` are each populated only when H&M's own response includes them. Example response: ```json {"code":200,"msg":"OK","data":{"query":"jean","phrase_suggestions":["jeans","jeans women","jeans men","jean shorts","jeans girls"],"blocked":false,"source_url":"https://api.hm.com/search-services/v1/en_us/search/suggestions?query=jean...","fetched_at":"2026-08-15T06:37:00Z"}} ``` ```json {"code":200,"msg":"OK","data":{"query":"","trending_searches":["back to school","sweatpants","shorts","dress","socks"],"popular_searches":[{"title":"Back to school "},{"title":"Spiderman","deep_link":"/content/hmonline/en_us/kids/seasonal-trending/character/boys","link":"/en_us/kids/seasonal-trending/character/character-youngboy.html"}],"search_history":["jeans","shirt","t-shirt"],"blocked":false,"source_url":"https://api.hm.com/search-services/v1/en_us/search/suggestions?query=...","fetched_at":"2026-08-15T06:37:00Z"}} ```
MCP tool hm_search_suggestions
/hm/storesReturns H&M physical retail store locations near a point: name, phone, full address, and coordinates. Either search, or both lat and lng, is required. search is a free-text zip code or place name that is first resolved to coordinates; if it does not resolve to any location, a well-formed empty result is returned rather than an error. lat and lng, when given directly, skip that resolution step. radius_meters is optional (1000 to 50000, defaults to 10000). A location with no stores within the radius returns a well-formed empty result rather than an error.
Response notes
- Each store includes its name, phone number, full street address, and coordinates. - `lat`/`lng` in the response always reflect the coordinates actually searched -- the caller's own values when given directly, or the coordinates resolved from `search` otherwise. - A `search` value that does not resolve to any location returns a well-formed empty result (`count: 0`, `stores: []`), not an error. - A location with no stores within the radius returns a well-formed empty result, not an error. Example response: ```json { "code": 200, "msg": "OK", "data": { "lat": 41.8781, "lng": -87.6298, "radius_meters": 15000, "count": 2, "stores": [ { "store_code": "US0181", "store_class": "Red", "name": "Roosevelt Collection", "phone": "+1-855-466-7467", "address": "150 W Roosevelt Rd", "city": "Chicago", "state": "Illinois", "postal_code": "60605", "country": "USA", "latitude": 41.868378, "longitude": -87.632216 } ] } } ```
MCP tool hm_stores
Related APIs
Marketplaces & Retail
Collect marketplace product signals from Amazon without building brittle storefront scrapers.
Marketplaces & Retail
Build resale, pricing, and marketplace workflows from structured eBay data.
Marketplaces & Retail
Turn public Shop.app product and merchant pages into structured JSON for e-commerce product intelligence, price research, shop monitoring, and marketplace discovery workflows.
How to scrape H&M
Crawlora's H&M endpoints return search, category listings, and product detail as normalized JSON with one API key — no H&M account required.
Send a free-text keyword to /hm/search for paginated, normalized products with pricing, images, and per-color stock.
Pass a known category slug (e.g. ladies_jeans, men_newarrivals_all) to /hm/listing for that category's product listing — H&M doesn't publish a category/nav-tree lookup call, so category_id values come from known storefront paths, not a discovery endpoint.
Pass a product_id (a listing/search result's id, or the digits in a product page's productpage.<id>.html URL) to /hm/product/{product_id} for every color's real per-size price and live availability, plus customer reviews when the product has any.
FAQ
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.
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.
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.