# Ulta Product Reviews Scraper (`automation-lab/ulta-product-reviews-scraper`) Actor

Scrape Ulta products, prices, ratings, availability, and recent customer reviews from public Ulta category/search/product pages.

- **URL**: https://apify.com/automation-lab/ulta-product-reviews-scraper.md
- **Developed by:** [Stas Persiianenko](https://apify.com/automation-lab) (community)
- **Categories:** E-commerce
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per event

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are a software tools running on the Apify platform, for all kinds of web data extraction and automation use cases.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp.md).

If your project is in a different language, use the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).


# README

## Ulta Product Reviews Scraper

Scrape Ulta product listings, prices, ratings, availability, and recent customer reviews from public Ulta pages.

Use this actor to monitor beauty products, price changes, merchandising, star ratings, and review sentiment without building your own Ulta parser.

### What does Ulta Product Reviews Scraper do?

Ulta Product Reviews Scraper extracts structured ecommerce data from Ulta category, search, and product pages.

It can collect product rows from pages such as `https://www.ulta.com/shop/makeup` and can also open product detail pages to collect recent review rows embedded in Ulta's public structured data.

Typical fields include:

- 💄 Brand and product name
- 🏷️ Regular price and sale price
- ⭐ Rating and review count
- 🛒 Availability
- 🖼️ Image URL
- 🔗 Product URL, product ID, and SKU
- 📝 Review title, body, rating, author, location, and date

### Who is it for?

#### Beauty brands

Track how your products appear on Ulta, watch ratings, and collect recent review language for voice-of-customer analysis.

#### Retail analysts

Monitor assortment, discounting, new launches, product availability, and category-level pricing across Ulta pages.

#### Reputation intelligence teams

Collect recent review text and star ratings for recurring sentiment monitoring.

#### Price intelligence vendors

Use category and product URLs as repeatable inputs for scheduled price and promotion checks.

### Why use this Ulta scraper?

- ✅ HTTP-first implementation for low compute cost
- ✅ Works with category/search pages and direct product URLs
- ✅ Product rows and review rows in one export
- ✅ Includes source URL and scrape timestamp for auditability
- ✅ Designed for recurring ecommerce monitoring workflows

### What data can I extract from Ulta?

| Field | Description |
| --- | --- |
| `recordType` | `product` or `review` |
| `brand` | Product brand when available |
| `productName` | Product name |
| `price` | Regular/list price |
| `salePrice` | Sale price when present |
| `rating` | Aggregate star rating |
| `reviewCount` | Aggregate review count |
| `availability` | Availability from product structured data |
| `productUrl` | Canonical Ulta product URL |
| `productId` | Ulta product ID, for example `pimprod2059833` |
| `skuId` | Ulta SKU from the URL or product data |
| `variant` | Shade, color, or variant label when available |
| `reviewTitle` | Review title |
| `reviewText` | Review body |
| `reviewRating` | Review star rating |
| `reviewAuthor` | Public review author name |
| `reviewLocation` | Public reviewer location |
| `reviewDate` | Review publication date |
| `sourceUrl` | Page where the row was discovered |
| `scrapedAt` | Actor run timestamp |

### How much does it cost to scrape Ulta products and reviews?

This actor uses pay-per-event pricing.

You pay a small start fee for each run and a per-result fee for each dataset row saved.

A row can be either:

- one product row, or
- one review row with product context.

Use a low `maxItems` value for first tests, then increase it for scheduled monitoring.

### How to scrape Ulta category pages

1. Open the actor on Apify.
2. Add an Ulta category or search URL to `startUrls`.
3. Keep `includeReviews` enabled if you want the actor to follow discovered product pages.
4. Set `maxItems` to the number of product/review rows you want.
5. Start the run and download the dataset as JSON, CSV, Excel, or via API.

### How to scrape one Ulta product's reviews

Use a direct product URL, for example:

```json
{
  "startUrls": [
    { "url": "https://www.ulta.com/p/soft-pinch-lip-oil-stick-pimprod2059833?sku=2658777" }
  ],
  "maxItems": 25,
  "includeReviews": true,
  "maxReviewsPerProduct": 20
}
````

The actor saves a product row and recent review rows available in the page's public structured data.

### Input options

| Input | Type | Default | Notes |
| --- | --- | --- | --- |
| `startUrls` | array | required | Ulta category, search, or product URLs |
| `maxItems` | integer | 20 | Total product + review rows to save |
| `includeReviews` | boolean | true | Follow product URLs and save review rows |
| `maxReviewsPerProduct` | integer | 10 | Cap embedded reviews per product |

### Output example

```json
{
  "recordType": "review",
  "brand": "Rare Beauty",
  "productName": "Soft Pinch Lip Oil Stick",
  "price": "25.00",
  "rating": 4.8,
  "reviewCount": 79,
  "reviewTitle": "Beautiful pigmentation",
  "reviewText": "The lip oil stick by Rare Beauty is such a smooth gliding...",
  "reviewRating": 5,
  "reviewAuthor": "Keetabeeta",
  "reviewLocation": "Buffalo, NY",
  "reviewDate": "2026-07-06",
  "productUrl": "https://www.ulta.com/p/soft-pinch-lip-oil-stick-pimprod2059833?sku=2658777",
  "productId": "pimprod2059833",
  "skuId": "2658777",
  "scrapedAt": "2026-07-08T00:00:00.000Z"
}
```

### Tips for best results

- Start with category URLs for product discovery.
- Use direct product URLs when you care about a known SKU.
- Keep `maxItems` small during testing.
- Schedule daily or weekly runs for price and reputation monitoring.
- Use `recordType` to split products and reviews in your BI tool.

### Integrations

Use the dataset with:

- 📊 Google Sheets dashboards for price checks
- 🧠 sentiment analysis pipelines for review text
- 🛒 retail intelligence systems
- 🔔 alerts when ratings or prices change
- 🧾 product catalog enrichment workflows

### API usage with Node.js

```js
import { ApifyClient } from 'apify-client';

const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('automation-lab/ulta-product-reviews-scraper').call({
  startUrls: [{ url: 'https://www.ulta.com/shop/makeup' }],
  maxItems: 100,
  includeReviews: true,
});
console.log(run.defaultDatasetId);
```

### API usage with Python

```python
from apify_client import ApifyClient

client = ApifyClient("<APIFY_TOKEN>")
run = client.actor("automation-lab/ulta-product-reviews-scraper").call(run_input={
    "startUrls": [{"url": "https://www.ulta.com/shop/makeup"}],
    "maxItems": 100,
    "includeReviews": True,
})
print(run["defaultDatasetId"])
```

### API usage with cURL

```bash
curl -X POST "https://api.apify.com/v2/acts/automation-lab~ulta-product-reviews-scraper/runs?token=$APIFY_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"startUrls":[{"url":"https://www.ulta.com/shop/makeup"}],"maxItems":100,"includeReviews":true}'
```

### MCP usage

Connect Apify MCP to use this scraper from Claude Desktop or Claude Code.

MCP endpoint:

```text
https://mcp.apify.com/?tools=automation-lab/ulta-product-reviews-scraper
```

Claude Code CLI setup:

```bash
claude mcp add apify-ulta --transport http "https://mcp.apify.com/?tools=automation-lab/ulta-product-reviews-scraper"
```

Claude Desktop JSON config:

```json
{
  "mcpServers": {
    "apify-ulta": {
      "url": "https://mcp.apify.com/?tools=automation-lab/ulta-product-reviews-scraper"
    }
  }
}
```

Example prompts:

- "Run the Ulta Product Reviews Scraper for this product URL and summarize negative review themes."
- "Scrape Ulta makeup category products and list the highest-rated items."
- "Monitor these Ulta product URLs weekly and flag price changes."

### Data quality notes

Ulta pages can contain several public data sources, including HTML product cards, hydration state, and JSON-LD structured data.

The actor prefers stable public data embedded in the initial page response.

Review pagination beyond embedded recent reviews may require a future API-specific enhancement.

### FAQ

#### Does this actor scrape full historical review pagination?

The MVP extracts recent reviews embedded in public product structured data. Full pagination can be added later if Ulta exposes a stable public endpoint.

#### Can I schedule recurring Ulta monitoring?

Yes. Use Apify schedules with category or product URLs and export the dataset to your warehouse, webhook, or dashboard.

### Troubleshooting

#### Why did I get fewer rows than expected?

Some category pages only embed a limited number of product cards in the initial HTML. Enable `includeReviews` or provide more category/product URLs to collect more rows.

#### Why are some fields empty?

Ulta does not expose every field on every page type. For example, category cards may have product information but not full review text.

#### Can I scrape private account data?

No. This actor is designed for public Ulta pages only.

### Legality and responsible use

This actor extracts publicly available product and review information from Ulta pages.

Make sure your use case complies with applicable laws, Ulta's terms, and privacy requirements.

Do not use scraped data for spam, harassment, or unlawful profiling.

### Related scrapers

You may also want these Automation Lab actors:

- https://apify.com/automation-lab/amazon-reviews-scraper
- https://apify.com/automation-lab/sephora-reviews-scraper
- https://apify.com/automation-lab/walmart-products-scraper
- https://apify.com/automation-lab/target-products-scraper

### Changelog

#### 0.1

Initial version with Ulta category/product extraction and recent review rows from product structured data.

### Support

If a public Ulta URL stops working or a field becomes unavailable, open an Apify issue with the run ID and input used.

# Actor input Schema

## `startUrls` (type: `array`):

Add Ulta category/search pages (for product discovery) or product URLs (for product details and reviews).

## `maxItems` (type: `integer`):

Maximum total rows to save. Product rows and review rows both count toward this limit.

## `includeReviews` (type: `boolean`):

Open product detail pages discovered from category/search pages and save available review rows.

## `maxReviewsPerProduct` (type: `integer`):

Limit review rows extracted from each product page. Ulta embeds recent reviews in product structured data.

## Actor input object example

```json
{
  "startUrls": [
    {
      "url": "https://www.ulta.com/shop/makeup"
    }
  ],
  "maxItems": 20,
  "includeReviews": true,
  "maxReviewsPerProduct": 10
}
```

# Actor output Schema

## `overview` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "startUrls": [
        {
            "url": "https://www.ulta.com/shop/makeup"
        }
    ],
    "maxItems": 20,
    "includeReviews": true,
    "maxReviewsPerProduct": 10
};

// Run the Actor and wait for it to finish
const run = await client.actor("automation-lab/ulta-product-reviews-scraper").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "startUrls": [{ "url": "https://www.ulta.com/shop/makeup" }],
    "maxItems": 20,
    "includeReviews": True,
    "maxReviewsPerProduct": 10,
}

# Run the Actor and wait for it to finish
run = client.actor("automation-lab/ulta-product-reviews-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "startUrls": [
    {
      "url": "https://www.ulta.com/shop/makeup"
    }
  ],
  "maxItems": 20,
  "includeReviews": true,
  "maxReviewsPerProduct": 10
}' |
apify call automation-lab/ulta-product-reviews-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=automation-lab/ulta-product-reviews-scraper",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "Ulta Product Reviews Scraper",
        "description": "Scrape Ulta products, prices, ratings, availability, and recent customer reviews from public Ulta category/search/product pages.",
        "version": "0.1",
        "x-build-id": "BywLT2T9XnFdEcAK8"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/automation-lab~ulta-product-reviews-scraper/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-automation-lab-ulta-product-reviews-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/acts/automation-lab~ulta-product-reviews-scraper/runs": {
            "post": {
                "operationId": "runs-sync-automation-lab-ulta-product-reviews-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor and returns information about the initiated run in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/runsResponseSchema"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/acts/automation-lab~ulta-product-reviews-scraper/run-sync": {
            "post": {
                "operationId": "run-sync-automation-lab-ulta-product-reviews-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "inputSchema": {
                "type": "object",
                "required": [
                    "startUrls"
                ],
                "properties": {
                    "startUrls": {
                        "title": "Ulta category, search, or product URLs",
                        "type": "array",
                        "description": "Add Ulta category/search pages (for product discovery) or product URLs (for product details and reviews).",
                        "items": {
                            "type": "object",
                            "required": [
                                "url"
                            ],
                            "properties": {
                                "url": {
                                    "type": "string",
                                    "title": "URL of a web page",
                                    "format": "uri"
                                }
                            }
                        }
                    },
                    "maxItems": {
                        "title": "Maximum dataset rows",
                        "minimum": 1,
                        "maximum": 5000,
                        "type": "integer",
                        "description": "Maximum total rows to save. Product rows and review rows both count toward this limit.",
                        "default": 20
                    },
                    "includeReviews": {
                        "title": "Include reviews",
                        "type": "boolean",
                        "description": "Open product detail pages discovered from category/search pages and save available review rows.",
                        "default": true
                    },
                    "maxReviewsPerProduct": {
                        "title": "Maximum reviews per product",
                        "minimum": 0,
                        "maximum": 50,
                        "type": "integer",
                        "description": "Limit review rows extracted from each product page. Ulta embeds recent reviews in product structured data.",
                        "default": 10
                    }
                }
            },
            "runsResponseSchema": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            },
                            "actId": {
                                "type": "string"
                            },
                            "userId": {
                                "type": "string"
                            },
                            "startedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "finishedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "status": {
                                "type": "string",
                                "example": "READY"
                            },
                            "meta": {
                                "type": "object",
                                "properties": {
                                    "origin": {
                                        "type": "string",
                                        "example": "API"
                                    },
                                    "userAgent": {
                                        "type": "string"
                                    }
                                }
                            },
                            "stats": {
                                "type": "object",
                                "properties": {
                                    "inputBodyLen": {
                                        "type": "integer",
                                        "example": 2000
                                    },
                                    "rebootCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "restartCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "resurrectCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "computeUnits": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "options": {
                                "type": "object",
                                "properties": {
                                    "build": {
                                        "type": "string",
                                        "example": "latest"
                                    },
                                    "timeoutSecs": {
                                        "type": "integer",
                                        "example": 300
                                    },
                                    "memoryMbytes": {
                                        "type": "integer",
                                        "example": 1024
                                    },
                                    "diskMbytes": {
                                        "type": "integer",
                                        "example": 2048
                                    }
                                }
                            },
                            "buildId": {
                                "type": "string"
                            },
                            "defaultKeyValueStoreId": {
                                "type": "string"
                            },
                            "defaultDatasetId": {
                                "type": "string"
                            },
                            "defaultRequestQueueId": {
                                "type": "string"
                            },
                            "buildNumber": {
                                "type": "string",
                                "example": "1.0.0"
                            },
                            "containerUrl": {
                                "type": "string"
                            },
                            "usage": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "usageTotalUsd": {
                                "type": "number",
                                "example": 0.00005
                            },
                            "usageUsd": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "number",
                                        "example": 0.00005
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
