Ulta Beauty API endpoint
Lists 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.
/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. Use this endpoint to discover valid category paths without already knowing one.
Query parameters:
department (optional): filter the result to one storefront department. Allowed values: makeup-nails, skin-care, hair-care, fragrance, body-care, wellness, mens-care, tools-brushes.Notable response behavior:
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.| Field | Filled in, of 51 checked | Values in the sample |
|---|---|---|
| department | 51 | makeup-nails in all 51 |
| name | 51 | “Shop All Makeup & Nails” and 50 other values |
| url | 51 | ulta.com |
| group | 42 | Face (12), Lips (8), Eyes (8) and 2 more |
| Parameter | Type | Required | Default | Description | Example |
|---|---|---|---|---|---|
| department | string | No | Filter to one department Allowed values: makeup-nails, skin-care, hair-care, fragrance, body-care, wellness, mens-care, tools-brushes. | makeup-nails | |
| x-api-key (header) | string | Yes | API key required |
curl -X GET "https://api.crawlora.net/api/v1/ulta/categories?department=makeup-nails" \ -H "x-api-key: $CRAWLORA_API_KEY"
{
"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"
}
]
}
}Request schema
No body schema
Response schema
#/definitions/ulta.categoriesResponseDoc
| Field | Type | Required | Enum | Bounds | Example | Description |
|---|---|---|---|---|---|---|
| code | integer | No | 200 | |||
| data | ulta.CategoriesResponse | No | ||||
| data.categories | array | No | ||||
| data.categories[].department | string | No | makeup-nails | |||
| data.categories[].group | string | No | Eyes | |||
| data.categories[].name | string | No | Mascara | |||
| data.categories[].url | string | No | https://www.ulta.com/shop/makeup/eyes/mascara | |||
| data.fetched_at | string | No | ||||
| data.source_url | string | No | ||||
| msg | string | No | OK |
| Status | Description | Schema |
|---|---|---|
| 400 | Bad Request | #/definitions/app.Response |
| 429 | Too Many Requests | #/definitions/app.Response |
| 503 | Service Unavailable | #/definitions/app.Response |
Use environment variables for secrets and keep Crawlora API keys server-side.
curl -X GET "https://api.crawlora.net/api/v1/ulta/categories?department=makeup-nails" \
-H "x-api-key: $CRAWLORA_API_KEY"