# Sephora Scraper (`crawlerbros/sephora-scraper`) Actor

Scrape Sephora - the largest US beauty retailer's online catalog. Search products by keyword, brand, rating and price, get product IDs, SKU data, ratings, review counts and images. HTTP-only via Sephora's public catalog search API. No auth required.

- **URL**: https://apify.com/crawlerbros/sephora-scraper.md
- **Developed by:** [Crawler Bros](https://apify.com/crawlerbros) (community)
- **Categories:** E-commerce, Automation, Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $3.00 / 1,000 results

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.
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 web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — 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

## Sephora Scraper

Scrape **Sephora** — the largest US beauty retailer's online catalog of 100,000+ products. Search by keyword, brand, rating and price; get product IDs, SKU data, prices, ratings, review counts, product flags (new / bestseller / Sephora exclusive) and images. HTTP-only via Sephora's public catalog search API. No auth, no proxy required.

### What this actor does

- **Three modes:** `search`, `bestsellers`, `newArrivals`
- **Rich product records:** product ID, brand, name, rating, review count, price range
- **Product flags:** new, bestseller, Sephora-exclusive, limited edition, online-only
- **Filters:** min rating, brand keyword, price range, new-only, bestseller-only, sale-only
- **Images:** rehosted into a public key-value store so they never break (Sephora's image CDN blocks hotlinking)
- **Empty fields are omitted**

### Output per product

- `productId` — Sephora product ID (e.g. `P427419`)
- `brandName`, `displayName`, `productName`
- `rating` — average rating (0–5), `reviews` — review count
- `skuId`, `imageAltText`
- `priceMin`, `priceMax` — parsed list price range (USD)
- `imageUrl` — rehosted, permanently accessible image; `imageOriginal` — upstream CDN URL
- `altImage` — alternate product shot
- `isNew`, `isBestseller`, `isSephoraExclusive`, `isLimitedEdition`, `isLimitedTimeOffer`, `isOnlineOnly`
- `isOnSale` — true when the product is currently on sale; `sponsored` — true for sponsored listings
- `pickupEligible`, `pickupNearbyEligible`, `sameDayEligible`, `nextDayEligible`, `shipToHomeEligible`
- `productUrl` — canonical product page, `sourceUrl` — API record URL
- `recordType: "product"`, `scrapedAt`

### Input

| Field | Type | Default | Description |
|---|---|---|---|
| `mode` | string | `search` | `search` / `bestsellers` / `newArrivals` |
| `searchQuery` | string | `moisturizer` | Keyword (required for mode=search) |
| `sortBy` | string | `relevance` | `relevance` / `best-selling` / `newest` (mode=search) |
| `minRating` | int | – | Min average rating (1–5) |
| `brandContains` | string | – | Brand name must contain this text |
| `priceMin` | int | – | Min list price (USD) |
| `priceMax` | int | – | Max list price (USD) |
| `includeNewOnly` | bool | `false` | Only products flagged new |
| `includeBestsellersOnly` | bool | `false` | Only products flagged bestsellers |
| `saleOnly` | bool | `false` | Only products currently on sale |
| `includeImages` | bool | `true` | Rehost images into public key-value store |
| `maxItems` | int | `50` | Hard cap (1–2000) |
| `proxyConfiguration` | object | off | Optional Apify proxy (AUTO group or custom); not needed for normal use |

#### Example: search moisturizers from a specific brand

```json
{
  "mode": "search",
  "searchQuery": "moisturizer",
  "brandContains": "the ordinary",
  "minRating": 4,
  "maxItems": 20
}
```

#### Example: bestsellers over $10

```json
{
  "mode": "bestsellers",
  "priceMin": 10,
  "maxItems": 30
}
```

#### Example: new arrivals with images disabled

```json
{
  "mode": "newArrivals",
  "includeImages": false,
  "maxItems": 10
}
```

### Use cases

- **Price monitoring** — track Sephora list prices and availability flags for your portfolio
- **Competitive intelligence** — benchmark brands by rating and review volume
- **Trend discovery** — mine bestseller and new-arrival feeds for emerging products
- **Beauty e-commerce research** — SKU-level catalog snapshots for market analysis
- **Brand tracking** — monitor a brand's catalog expansion and product flags

### FAQ

**What is the data source?** Sephora's public catalog search API (`www.sephora.com/api/v2/catalog/search/`), the same endpoint their own search page uses.

**Do I need an account or API key?** No. The catalog search API is public and requires no authentication.

**Why do some products have no image?** Images are rehosted from Sephora's CDN, which rate-limits/block certain requests. If a rehost fails, the image fields are omitted — the record still contains full product data.

**Why do some price ranges show two values?** Sephora lists multi-SKU products as a range (e.g. `$9.90 - $17.50`); we emit the parsed `priceMin`/`priceMax`.

**How fresh is the data?** Sephora's catalog search returns live data per request.

**Is this affiliated with Sephora?** No. This is a third-party actor using Sephora's public search API.

**Why can't I scrape product detail pages?** Sephora's Akamai protection blocks browse/detail page access from datacenter IPs. The catalog search API (which powers search results) is reliably accessible and includes all core product fields.

**Why is there no price sort?** `sortBy` only supports `relevance` / `best-selling` / `newest`. Sephora's API accepts a `price-low-high` sort flag, but its results are not actually price-ordered (verified against live responses), so exposing it would violate the sort contract. Use `priceMin`/`priceMax` to bound results instead.

**Does the actor support special characters in queries?** Yes — search queries (spaces, accents, quotes, `&`, emoji) are URL-encoded before hitting the API, so `searchQuery: "shampoo & conditioner"` and `brandContains: "kérastase"` work as-is.

### Data Source

- **Site:** www.sephora.com
- **Access:** public catalog search API (JSON), no authentication
- **Anti-bot:** Akamai protects browse/product pages; the search API accepts standard browser TLS fingerprints. The actor uses browser-grade TLS impersonation and optional Apify proxy (AUTO) escalation on 403.
- **Media:** product images are hotlink-protected from plain HTTP clients, so the actor rehosts them into its key-value store (`imageUrl`) and keeps the upstream URL as `imageOriginal`.

### Limitations

- Browse pages (`/shop/*`) and product detail pages are Akamai-protected and are not scraped; the actor uses the catalog search API, which returns the same products with core fields (price, rating, flags, images).
- Multi-SKU products report a price range rather than a single price.
- Some eligibility flags (e.g. `shipToHomeEligible`) can be `false` for regional stock reasons — omitted when absent.

# Actor input Schema

## `mode` (type: `string`):

What to fetch.

## `searchQuery` (type: `string`):

Free-text keyword (mode=search). For bestsellers / newArrivals this is optional.

## `sortBy` (type: `string`):

Result ordering (mode=search).

## `minRating` (type: `integer`):

Only emit products with an average rating at or above this (1-5).

## `brandContains` (type: `string`):

Only emit products whose brand name contains this text (case-insensitive), e.g. `the ordinary`.

## `priceMin` (type: `integer`):

Only emit products with a list price at or above this.

## `priceMax` (type: `integer`):

Only emit products with a list price at or below this.

## `includeNewOnly` (type: `boolean`):

Only emit products flagged as new by Sephora.

## `includeBestsellersOnly` (type: `boolean`):

Only emit products flagged as bestsellers by Sephora.

## `saleOnly` (type: `boolean`):

Only emit products currently marked on sale by Sephora.

## `includeImages` (type: `boolean`):

Rehost product images into the actor's key-value store so they are publicly accessible (Sephora's image CDN blocks direct hotlinking).

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

Hard cap on emitted records.

## `proxyConfiguration` (type: `object`):

Optional Apify proxy. Sephora generally does not require it; enable it if you see 403 responses.

## Actor input object example

```json
{
  "mode": "search",
  "searchQuery": "moisturizer",
  "sortBy": "relevance",
  "includeNewOnly": false,
  "includeBestsellersOnly": false,
  "saleOnly": false,
  "includeImages": true,
  "maxItems": 50,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

## `products` (type: `string`):

Dataset containing all scraped Sephora products.

# 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 = {
    "mode": "search",
    "searchQuery": "moisturizer",
    "sortBy": "relevance",
    "includeNewOnly": false,
    "includeBestsellersOnly": false,
    "saleOnly": false,
    "includeImages": true,
    "maxItems": 50,
    "proxyConfiguration": {
        "useApifyProxy": false
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("crawlerbros/sephora-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 = {
    "mode": "search",
    "searchQuery": "moisturizer",
    "sortBy": "relevance",
    "includeNewOnly": False,
    "includeBestsellersOnly": False,
    "saleOnly": False,
    "includeImages": True,
    "maxItems": 50,
    "proxyConfiguration": { "useApifyProxy": False },
}

# Run the Actor and wait for it to finish
run = client.actor("crawlerbros/sephora-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 '{
  "mode": "search",
  "searchQuery": "moisturizer",
  "sortBy": "relevance",
  "includeNewOnly": false,
  "includeBestsellersOnly": false,
  "saleOnly": false,
  "includeImages": true,
  "maxItems": 50,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}' |
apify call crawlerbros/sephora-scraper --silent --output-dataset

```

## MCP server setup

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

```

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/qKcrd8XoKUh6DMRWo/builds/he0gBjvbacxT7xgxQ/openapi.json
