Beauty retail pricing and availability monitoring
Use Ulta Beauty endpoints to turn beauty retail pricing and availability monitoring into repeatable API requests with documented inputs and JSON responses.
Turn Ulta Beauty's own storefront data into structured beauty-retail data — keyword product search with real pagination, and per-product detail with pricing, rating, review count, images, and every purchasable color/shade variant, all as normalized JSON. Credential-free.
Search Ulta Beauty's product catalog and get full product detail — pricing, ratings, reviews, and every color/shade variant — as structured JSON.
Endpoint families
6
Documented params
25
Examples
8
Live catalog snapshot
Active endpoints
8
Methods
GET
Required params
14
Schema refs
8
{
"platform": "Ulta Beauty",
"endpoint": "ulta-search",
"method": "GET",
"path": "/ulta/search",
"auth": "apiKey"
}Use cases
Search Ulta Beauty's product catalog and get full product detail — pricing, ratings, reviews, and every color/shade variant — as structured JSON.
Use Ulta Beauty endpoints to turn beauty retail pricing and availability monitoring into repeatable API requests with documented inputs and JSON responses.
Use Ulta Beauty endpoints to turn product catalog research into repeatable API requests with documented inputs and JSON responses.
Use Ulta Beauty endpoints to turn shade/color-variant tracking into repeatable API requests with documented inputs and JSON responses.
Managed execution
Every figure below is read from the live Ulta Beauty endpoint catalog — 8 endpoints, 25 documented request parameters, and 8 published response schemas — the same catalog Docs and Playground run against.
8 documented Ulta Beauty endpoints, grouped into 6 request families — Product, Categories and Category, plus 3 more.
25 request parameters are documented across those Ulta Beauty endpoints, 14 of them required — the full input contract is public before you write any integration code.
8 of the 8 Ulta Beauty endpoints ship a recorded example response, and 8 carry a documented response schema — you can code against the real JSON before the first request.
Ulta Beauty 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.
8 hosted MCP tools back the Ulta Beauty 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.
/ulta/product/{productId}
/ulta/categories
/ulta/category
/ulta/search
/ulta/stores
/ulta/suggest
Endpoint catalog
/ulta/searchSearches Ulta Beauty's product catalog by keyword, with real page-based pagination. Returns normalized products with brand, pricing, rating, and review count. An unrecognized/nonsense keyword returns a genuine empty result rather than a fallback set. Requesting a page beyond the available results returns a normal, empty result rather than an error.
Response notes
- Pagination is real and page-based, 64 results per page. `has_more` is the upstream's own genuine "more pages available" marker: `true` on every page with more results after it, `false` on the real last page and on any page beyond it. - Requesting a `page` beyond the available results returns a normal `200` with an empty `products` array and `has_more: false`, not an error. - An unrecognized/nonsense `query` returns a genuine empty result (`count: 0`, `result_count: 0`) rather than a fallback set. - `list_price`/`sale_price` are Ulta's own display-formatted price strings (e.g. `"$12.99 - $13.99"`), since a search card's list price is often a range across a product's own color/shade variants -- use `/ulta/product/{productId}` for one variant's single resolved price. Example response: ```json {"code":200,"msg":"OK","data":{"query":"mascara","page":1,"page_size":64,"count":3,"result_count":382,"has_more":true,"products":[{"product_id":"pimprod2020260","sku_id":"2574523","brand_name":"Maybelline","product_name":"Lash Sensational Sky High Mascara","list_price":"$12.99 - $13.99","rating":4.5,"review_count":11861,"variant_label":"9 colors","image_url":"https://media.ulta.com/i/ulta/2574523","url":"https://www.ulta.com/p/lash-sensational-sky-high-mascara-pimprod2020260?sku=2574523"}],"source_url":"https://www.ulta.com/dxl/graphql?...","fetched_at":"2026-08-10T10:00:00Z"}} ```
MCP tool ulta_search
/ulta/product/{productId}Returns one Ulta Beauty product's full detail: name, brand, description, category, pricing, rating, review count, images, and every purchasable color/shade variant. productId is taken from a search result's product_id field or a product page's URL (e.g. pimprod2020260). sku is optional and selects a specific color/shade variant; an omitted or invalid sku still resolves the base product using its own default variant. An unrecognized productId returns 404.
Response notes
- `category` lists the product's category breadcrumb (e.g. `["Makeup", "Eyes", "Mascara"]`). - `variants` lists every purchasable color/shade of the base product, each with its own `product_id`/`sku_id`/`name`. - `images` is the featured variant's image gallery as absolute URLs. - `sale_price` is only present when the product is currently on sale. - An unrecognized `productId` returns `404`. A malformed `productId` returns `400` before any upstream request is made. Example response: ```json {"code":200,"msg":"OK","data":{"product_id":"pimprod2020260","sku_id":"2574523","brand_name":"Maybelline","product_name":"Lash Sensational Sky High Mascara","description":"#### Benefits\n\n- Sky high lash impact from every angle\n- Soft, lightweight lashes with no flaking or smudging","category":["Makeup","Eyes","Mascara"],"currency_code":"USD","list_price":"$13.99","unavailable":false,"rating":4.5,"review_count":11861,"images":["https://media.ulta.com/i/ulta/2574523","https://media.ulta.com/i/ulta/2574523_sm"],"variants":[{"product_id":"pimprod2020260","sku_id":"2574523","name":"Blackest Black"},{"product_id":"pimprod2020260","sku_id":"2617940","name":"Burgundy Haze"}],"url":"https://www.ulta.com/p/product-pimprod2020260?sku=2574523","source_url":"https://www.ulta.com/dxl/graphql?...","fetched_at":"2026-08-10T10:00:00Z"}} ```
MCP tool ulta_product
/ulta/categoriesLists Ulta Beauty's own storefront category navigation: department, group, name, and a URL usable directly as GET /ulta/category's own category parameter. Closes the discovery gap of not already knowing a category path. department, if set, filters to just that department's entries. group is empty for a department's own top-level link or a group's own heading link, and set to that group's name for the leaf categories nested under it. The exact same real category can legitimately appear more than once under a different department/group when the site's own navigation cross-lists it.
Response notes
- `group` is empty for two kinds of entries: a department's own top-level link (e.g. "All Makeup & Nails"), and a group's own heading link (e.g. "Face"), which is itself a real, browsable category one level above its own leaf items. Every leaf item nested under a group carries that group's name as `group` (e.g. "Foundation" carries group `"Face"`). - `department`/`group` reflect the site's own navigation grouping, not a slug derived from the returned URL's path. Some categories are cross-listed by Ulta's own navigation under more than one department -- for example "Tinted Moisturizer" and "Makeup Remover" appear under the Makeup & Nails department's "Face" group, but their URLs resolve under `shop/skin-care/...`, and the same two categories also appear separately under the Skin Care department's own "Moisturizers"/"Cleansers" groups. This is expected: the same real category can legitimately appear more than once with a different `department`/`group` pairing. - A small number of groups have a heading link but no nested leaf items at all (for example Men's Care's "Cologne") and surface as a single group-empty entry, the same shape as a department's own top-level link. Example response: ```json {"code":200,"msg":"OK","data":{"source_url":"https://www.ulta.com/","fetched_at":"2026-08-11T12:00:00Z","categories":[{"department":"makeup-nails","name":"All Makeup & Nails","url":"https://www.ulta.com/shop/makeup"},{"department":"makeup-nails","name":"Eyes","url":"https://www.ulta.com/shop/makeup/eyes"},{"department":"makeup-nails","group":"Eyes","name":"Mascara","url":"https://www.ulta.com/shop/makeup/eyes/mascara"},{"department":"makeup-nails","group":"Face","name":"Tinted Moisturizer","url":"https://www.ulta.com/shop/skin-care/moisturizers/tinted-moisturizer"}]}} ```
MCP tool ulta_categories
/ulta/categoryBrowses an Ulta Beauty category page's product grid, with real page-based pagination and the category's own guided-navigation refinement options. category accepts a category path or full URL copied from Ulta's own site navigation (e.g. shop/makeup/eyes/mascara). filter narrows results using Ulta's own guided-navigation facet-code shape (e.g. BENEFIT--WATERPROOF, or a comma-joined combination of codes) -- discover valid codes for a category from that category's own response facets field, whose value is ready to use directly as this parameter. An unrecognized category returns 404.
Response notes
- Pagination is real and page-based, 64 results per page. `has_more` is the upstream's own genuine "more pages available" marker, the same as `/ulta/search`. - `facets` lists the category's own guided-navigation refinement options (label, a ready-to-use `value`, and whether it is already applied) -- present whenever the upstream returns them. An already-selected facet carries an empty `value`, since the caller already knows they set that filter themselves. - An unrecognized `category` returns `404`. - `list_price`/`sale_price` are Ulta's own display-formatted price strings, the same as `/ulta/search`. Example response: ```json {"code":200,"msg":"OK","data":{"category":"shop/skin-care/cleansers","page":1,"page_size":64,"count":2,"result_count":1161,"has_more":true,"products":[{"product_id":"xlsImpprod5140065","sku_id":"2254420","brand_name":"CeraVe","product_name":"Foaming Facial Cleanser","list_price":"$5.99 - $18.99","rating":4.6,"review_count":19250,"variant_label":"4 sizes","image_url":"https://media.ultainc.com/i/ulta/2254420","url":"https://www.ulta.com/p/foaming-facial-cleanser-xlsImpprod5140065?sku=2254420"}],"facets":[{"label":"Combination Skin Type","value":"SKIN_TYPE--COMBINATION"},{"label":"On Sale","value":"SPECIAL_OFFER--SALE"}],"source_url":"https://www.ulta.com/dxl/graphql?...","fetched_at":"2026-08-11T10:00:00Z"}} ```
MCP tool ulta_category
/ulta/product/questionsReturns one page of an Ulta Beauty product's normalized customer questions, each with every answer it received. product_id is taken from a search result's product_id field or a product page's URL. A product with zero questions, or a well-formed but unrecognized product_id, returns a normal, empty result rather than an error.
Response notes
- Each question's `answers` lists every answer it received, in the order the source returns them. `is_expert` marks an answer from a brand representative rather than a fellow customer. - A product with zero questions, or a well-formed but unrecognized `product_id`, returns a normal, empty result (`count: 0`, `total_questions: 0`) rather than an error -- the review source does not distinguish an unknown product id from a real, question-free product. - A malformed `product_id` returns `400` before any upstream request is made. Example response: ```json {"code":200,"msg":"OK","data":{"product_id":"pimprod2020260","page":1,"page_size":10,"total_pages":3,"total_questions":62,"count":10,"source_url":"https://display.powerreviews.com/...","fetched_at":"2026-08-11T10:00:00Z","questions":[{"id":"11248885","text":"Is this a tubing mascara?","author":"Ace","location":"fl","created_at":"2026-01-15T18:32:15Z","answer_count":1,"answers":[{"id":"571075350","text":"Hi Ulta Customer. Thank you for reaching out...","author":"Maybelline","is_expert":true,"helpful_votes":16,"created_at":"2026-02-02T08:56:52Z"}]}]}} ```
MCP tool ulta_product_questions
/ulta/product/reviewsReturns one page of an Ulta Beauty product's normalized customer reviews, plus the retailer's own site-wide rating summary (rating count, average rating, recommended ratio, rating histogram) for the product. product_id is taken from a search result's product_id field or a product page's URL. A product with zero reviews, or a well-formed but unrecognized product_id, returns a normal, empty result rather than an error.
Response notes
- `rating_count`, `average_rating`, `recommended_ratio`, and `rating_histogram` are the product's site-wide aggregate rating summary, not just this page. `rating_histogram` is the count of ratings per star, ascending: index 0 is 1-star, index 4 is 5-star. - A product with zero reviews, or a well-formed but unrecognized `product_id`, returns a normal, empty result (`count: 0`, `total_reviews: 0`) rather than an error -- the review source does not distinguish an unknown product id from a real, reviewless product. - A malformed `product_id` returns `400` before any upstream request is made. Example response: ```json {"code":200,"msg":"OK","data":{"product_id":"pimprod2020260","page":1,"page_size":10,"total_pages":203,"total_reviews":2028,"rating_count":11861,"average_rating":4.45,"recommended_ratio":0.66,"rating_histogram":[428,380,825,2021,8207],"count":10,"source_url":"https://display.powerreviews.com/...","fetched_at":"2026-08-11T10:00:00Z","reviews":[{"id":"585043647","rating":5,"headline":"Best mascara","body":"I have fairly long, thick eyelashes...","author":"ollie","location":"NYC","verified_purchase":false,"created_at":"2026-08-01T12:30:29Z"}]}} ```
MCP tool ulta_product_reviews
/ulta/storesReturns Ulta Beauty physical retail store locations near a point: name, phone, full address, hours, services, and coordinates. Either search, or both lat and lng, is required. search is a free-text zip code, city, or address 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 25000). 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, hours of operation, in-store services, 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. - `hours` maps a three-letter day abbreviation (`Mon`..`Sun`) to that day's opening range, e.g. `"09:00-21:00"`. Example response: ```json { "code": 200, "msg": "OK", "data": { "search": "60601", "lat": 41.885769, "lng": -87.624599, "radius_meters": 25000, "count": 1, "stores": [ { "id": 2806899, "slug": "chicago-il-1357", "name": "Ulta Beauty", "phone": "+1 312-527-9045", "address": "430 North Michigan Avenue", "city": "Chicago", "state": "IL", "postal_code": "60611", "country": "US", "latitude": 41.8903696, "longitude": -87.6247778, "is_permanently_closed": false, "services": ["Hair Services", "Brow Services", "Makeup Services"], "hours": { "Mon": "09:00-21:00", "Sun": "10:00-20:00" }, "url": "https://www.ulta.com/stores/chicago-il-1357" } ] } } ```
MCP tool ulta_stores
/ulta/suggestReturns Ulta Beauty's own search-suggestion (typeahead) result for a partial search term: suggested search terms, each with its own top product matches, plus a featured top result matching what a real user sees at the top of the dropdown. A partial term with no matches returns a normal, empty result rather than an error.
Response notes
- `suggestions` lists each suggested search term with its own `label`, `url` (a category/search page), and `top_results` (up to a handful of matching products). - `first_top_result` mirrors what a real user sees featured at the top of the dropdown -- it is one of `suggestions`' own top results, not a separate search. - A partial term with no matches returns a normal, empty result (`count: 0`, empty `suggestions`) rather than an error. Example response: ```json {"code":200,"msg":"OK","data":{"query":"masc","count":10,"source_url":"https://www.ulta.com/dxl/graphql?...","fetched_at":"2026-08-11T10:00:00Z","suggestions":[{"label":"Mascara","url":"https://www.ulta.com/shop/makeup/eyes/mascara","top_results":[{"brand_name":"Tarte","product_name":"Tartelette Tubing Mascara","image_url":"https://media.ultainc.com/i/ulta/2596644","url":"https://www.ulta.com/p/tartelette-tubing-mascara-pimprod2033171?sku=2596644"}]}],"first_top_result":[{"brand_name":"Tarte","product_name":"Tartelette Tubing Mascara","image_url":"https://media.ultainc.com/i/ulta/2596644","url":"https://www.ulta.com/p/tartelette-tubing-mascara-pimprod2033171?sku=2596644"}]}} ```
MCP tool ulta_suggest
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.
Company coverage
Ulta Beauty, Inc. · ULTA
Ulta Beauty is operated by Ulta Beauty, Inc. (ULTA). Crawlora's SEC endpoints take the same company's CIK, so filings, financials, insider transactions and 13F holdings come from the same API key as the Ulta Beauty endpoints above.
SEC filings & financials API →How to scrape Ulta Beauty
Crawlora's Ulta Beauty endpoints return search and product detail as normalized JSON with one API key — no Ulta account required.
Send a free-text keyword to /ulta/search for paginated, normalized products with brand, pricing, rating, and review count.
Pass a product_id (from a search result, or a product page URL like pimprod2020260) to /ulta/product/{productId} for full detail — pricing, rating, review count, images, and every color/shade variant. Add an optional sku to select a specific variant; an omitted or invalid sku still resolves the base product using its own default variant.
FAQ
Yes — /ulta/search returns a genuine empty result for an unrecognized or nonsense keyword, and a normal empty result (not an error) when you request a page beyond the available results.
Yes — pass an optional sku to /ulta/product/{productId} to select a specific color/shade variant. An omitted or invalid sku still resolves the base product using its own default variant. An unrecognized productId returns 404.