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
Ulta Beauty's category tree spans nine departments, including a Wellness section covering vitamins, feminine hygiene, and sleep support alongside the expected makeup and skin care groups. A 2026-09-24 search for "moisturizer" reported 1,295 total results, led by a $12 Good Molecules moisturizer (4.4 stars, 1,176 reviews). Crawlora's eight Ulta Beauty endpoints turn that search, category browsing, product detail, reviews, Q&A, and the store locator into normalized JSON, no Ulta account required.
/ulta/search takes a free-text query and returns page-based results with brand, pricing, rating, and review count. A 2026-09-24 pull for "moisturizer" reported 1,295 total matches, 64 per page, with has_more true.
Pass a category path or url from /ulta/categories to /ulta/category, optionally narrowed with filter codes taken straight from that category's own facets field. Face Moisturizer alone exposed over 40 refinement codes, from SKIN_TYPE--DRY to PREFERENCE--fragrance+free, and reported 1,116 matching products in total.
Pass a product_id (and optional sku) to /ulta/product/{productId} for pricing, images, and every color/shade variant. A Good Molecules Lightweight Daily Moisturizer pull returned two size variants, 1.0 oz and 3.3 oz, each its own sku_id.
/ulta/product/reviews returns paginated reviews plus a rating_histogram and recommended_ratio, both taken from Ulta's review provider. That same moisturizer showed a 4.44 average from 1,176 ratings but a recommended_ratio of 0.44, so the star average and the would-recommend share are worth tracking separately.
/ulta/product/questions returns customer questions with every answer, including ones flagged is_expert when an Ulta or brand representative replies: 13 of them for that moisturizer, mostly staff-answered.
/ulta/stores takes a free-text search or a lat/lng pair and returns nearby locations with hours and services like Benefit_Brow_Services. A search for zip 10019 returned 18 stores within the default 25 km radius.
FAQ
count is the number of products on the page you received; result_count is the total across every page of that category. A 2026-09-24 pull of Face Moisturizer returned 71 products on the page against a result_count of 1,116.
Not necessarily. /ulta/product/reviews returns both separately, and one 4.4-star, 1,176-review moisturizer carried a recommended_ratio of 0.44 on 2026-09-24.
A mix of shoppers and staff. /ulta/product/questions flags staff replies with is_expert true, and on a bestselling product most answered questions carry that flag.
Read them off that category's own response rather than guessing. The facets field of /ulta/category returns ready-to-use codes like SKIN_TYPE--DRY or PREFERENCE--fragrance+free that pass directly into the filter parameter.
No. Every endpoint here reads Ulta's public storefront, review, Q&A, and store-locator data with only your Crawlora API key, no Ulta account needed.