Sephora Scraper - Products, SKUs, Reviews & 21+ Stores avatar

Sephora Scraper - Products, SKUs, Reviews & 21+ Stores

Pricing

from $1.00 / 1,000 results

Go to Apify Store
Sephora Scraper - Products, SKUs, Reviews & 21+ Stores

Sephora Scraper - Products, SKUs, Reviews & 21+ Stores

From $1/1K. Scrape Sephora products across 21+ storefronts (US, AU, NZ, SG, MY, ID, TH, PH, MX, DE, RO, SE, GR, DK) with a unified schema. Extract brand, title, ingredients, claims, full SKU and shade variants, ratings histogram, top reviews, Q&A, and rich media.

Pricing

from $1.00 / 1,000 results

Rating

0.0

(0)

Developer

Abot API

Abot API

Maintained by Community

Actor stats

1

Bookmarked

9

Total users

3

Monthly active users

9 days ago

Last modified

Share

Sephora Scraper: Product Catalog, Variants, Prices & Reviews

Sephora Scraper turns 14 regional Sephora storefronts into one clean product data feed. Get brand, title, ingredients, claims, the full variant matrix with every shade, size and SKU, pricing and discount fields, ratings, top reviews and top questions and answers, all normalized into a single output shape. Search by keyword or category, paste a URL, or track the Sale collection, then export to JSON, CSV or Excel, or read the results through the API.

Why This Scraper?

  • 14 regional storefronts, one input form. United States, Australia, New Zealand, Singapore, Malaysia, Indonesia, Thailand, Philippines, Mexico, Germany, Romania, Sweden, Greece and Denmark, all normalized to the same output shape.
  • Three ways to find products. Search by keyword, browse by category slug, or paste any Sephora product, category, brand or search URL and let the scraper detect the storefront.
  • Full product detail on demand. Switch on the product detail fetch for ingredients, how-to-use text, claims and, on the US and Southeast Asia storefronts, the complete variant matrix (every shade, size, SKU and UPC). Leave it off for a search-results-only run so you only pay for the fields you actually use.
  • Ratings and voice of the customer. Pull the rating histogram, top reviews (with skin type and skin tone tags where available) and top questions and answers, each capped by you.
  • Built-in discount tracking. Every record carries isOnSpecial, wasPrice, savingsAmount and savingsPercent, always present, never guessed. A non-discounted product gets an explicit false/null rather than a missing field.
  • Resilient long walks. Forward-paginated result walks checkpoint themselves and resume automatically after a platform restart, and a delta-resume option skips everything a previous run already collected.
  • Built for monitoring. Incremental mode classifies every product as NEW, UPDATED or UNCHANGED against the previous run's state, so a recurring schedule returns only what changed.

Use Cases

  • Retail price and assortment monitoring: track price, stock status and the Sale collection across storefronts and currencies.
  • Beauty affiliate and comparison sites: pull brand, description, ingredients and claims to build product pages without manual entry.
  • Review and sentiment research: collect top reviews with skin type and skin tone context, plus the ratings histogram, for a brand's own SKUs or its competitors.
  • Variant and shade planning: build a full shade, size and SKU matrix per product for merchandising or QA.
  • Recurring monitoring: schedule the actor and use Incremental mode to see only new, changed or discontinued products since the last run.

Data You Get

Sample shape: values are illustrative placeholders, not from a live record.

FieldExample
market"sea-nz"
source.id / source.canonicalUrl500000001 / "https://www.sephora.nz/products/sample-foundation"
source.currency / source.locale"NZD" / "en-NZ"
brand"Sample Brand"
title / subtitle"Sample Foundation" / "30ml"
description"<p>A self-priming foundation, primes, covers and sets...</p>"
ingredients"Aqua, Cyclopentasiloxane, Glycerin, ..."
howToUse"Shake well. Apply a small amount onto the back of your hand..."
claims["Cruelty free", "Paraben free", "Vegan"]
currentSku"0000000"
price.current / price.original18.0 / 36.0
categories["Makeup", "Face", "Foundation"]
options[].values[].value"1 Fair Neutral"
variants[].sku / variants[].shade"0000000" / "1 Fair Neutral"
variants[].price.current / variants[].price.original18.0 / 36.0
variants[].price.stockStatus"IN_STOCK"
medias[].url"https://image.example.com/products/sample-zoom.jpg"
stats.rating / stats.reviewCount4.8 / 971
ratingHistogram[{"RatingValue": 5, "Count": 700}, ...] (when reviews are on)
topReviews[].rating / topReviews[].body5 / "Best foundation I have ever tried..." (when reviews are on)
topQuestions[].question"Is this product fragrance free?" (when Q&A is on)
isOnSpecial / wasPrice / savingsAmount / savingsPercenttrue / 36.0 / 18.0 / 50
soldOutfalse
frontend"sea" (also "us" or "scc" on a detail-enriched record; on a search-results-only record, the storefront's own code, e.g. "fr", "me", "mx", "br")
scrapedAt"2026-01-01T00:00:00.000Z"

The table above shows a detail-enriched Southeast Asia record. The shape varies by storefront and by whether details were fetched. With Fetch product details off, a record only carries the search-results fields: market, source, brand, title, top-level price, a priceText, thumbnail, rating, reviewCount, isNewArrival, soldOut, frontend and scrapedAt; it has no description, ingredients, howToUse, claims, options, variants or stats. Detail-enriched records from the European storefronts (Germany, Romania, Sweden, Greece, Denmark, plus France, Italy, Spain, Portugal, Poland and Brazil in url mode) have no variants, options, claims or subtitle. claims and subtitle are only produced for the Southeast Asia storefronts.

When Incremental mode is on, every record also carries changeType (NEW, UPDATED, UNCHANGED, REAPPEARED or EXPIRED), changedFields (the list of top-level fields that changed on an UPDATED record), and firstSeenAt/lastSeenAt timestamps; these four fields are absent on every normal (non-incremental) run.

How to Use

  1. Pick a mode: search (choose a storefront, then fill in keywords or category slugs) or url (paste one or more Sephora links; the scraper detects the storefront from the host).
  2. In search mode, narrow the results with the optional filters (brand, price range, minimum rating, new arrivals, exclusives). These filters also apply to a pasted category or search URL in url mode, but not to a single pasted product URL, which always returns that exact product.
  3. Switch on product details, reviews and Q&A for the fields you need, and set Max products (and optionally Max pages) to control the size and cost of the run.
  4. Set the connection to a residential proxy pinned to the storefront's country, then click Start. Download the dataset as JSON, CSV or Excel, or read it through the API.

The storefront dropdown covers the 14 sites above. Paste a URL from a Sephora site the dropdown does not list, such as France, Italy, Spain, Portugal, Poland, Brazil or the Middle East (UAE, Saudi Arabia, Qatar, Kuwait), and URL mode still detects the storefront from the link. Top reviews and top Q&A are only populated on the US storefront and the Southeast Asia storefronts today; other storefronts leave those fields empty even with the switches on.

Search by keyword:

{
"mode": "search",
"storefront": "us",
"queries": ["foundation", "mascara"],
"maxPages": 5,
"maxProducts": 100,
"fetchDetails": true,
"proxyConfiguration": {
"useApifyProxy": true,
"apifyProxyGroups": ["RESIDENTIAL"],
"apifyProxyCountry": "US"
}
}

Search by category, with filters, reviews and Q&A:

{
"mode": "search",
"storefront": "nz",
"categories": ["shop/skincare"],
"ratingMin": 4,
"maxPages": 3,
"maxProducts": 60,
"fetchDetails": true,
"fetchReviews": true,
"maxReviewsPerProduct": 10,
"fetchQna": true,
"maxQnaPerProduct": 5,
"proxyConfiguration": {
"useApifyProxy": true,
"apifyProxyGroups": ["RESIDENTIAL"],
"apifyProxyCountry": "NZ"
}
}

Specials (Sale collection, Southeast Asia storefronts):

{
"mode": "search",
"storefront": "com.au",
"specialsOnly": true,
"maxPages": 3,
"maxProducts": 60,
"proxyConfiguration": {
"useApifyProxy": true,
"apifyProxyGroups": ["RESIDENTIAL"],
"apifyProxyCountry": "AU"
}
}

URL mode (single product):

{
"mode": "url",
"urls": [
"https://www.sephora.nz/products/rare-beauty-true-to-myself-natural-matte-longwear-foundation"
],
"fetchDetails": true,
"fetchReviews": true,
"fetchQna": true,
"proxyConfiguration": {
"useApifyProxy": true,
"apifyProxyGroups": ["RESIDENTIAL"],
"apifyProxyCountry": "NZ"
}
}

Run it from your code

Python:

from apify_client import ApifyClient
client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("abotapi/sephora-product-scraper").call(run_input={
"mode": "search",
"storefront": "us",
"queries": ["foundation"],
"maxProducts": 20,
})
for product in client.dataset(run["defaultDatasetId"]).iterate_items():
print(product["brand"], product["title"])

JavaScript:

import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: '<YOUR_APIFY_TOKEN>' });
const run = await client.actor('abotapi/sephora-product-scraper').call({
mode: 'search',
storefront: 'us',
queries: ['foundation'],
maxProducts: 20,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();

Or connect it to Make, Zapier, n8n, Google Sheets or webhooks from the Integrations tab.

Specials, was-price and discount

Sephora's Southeast Asia storefronts (Australia, New Zealand, Singapore, Malaysia, Indonesia, Thailand, Philippines) have exactly one discount collection, the site's own "Sale" page. Set specialsOnly: true to scrape it. The Sale collection does not combine with queries or categories, so those inputs are ignored while it is on and the whole Sale collection is scraped instead. specialsOnly only affects those Southeast Asia storefronts; on any other storefront it is a no-op and your normal queries or categories run as usual.

Every product record, whether from a normal search, a URL, or a specialsOnly run, carries four additive, always-present discount fields: isOnSpecial (boolean), wasPrice (the strike-through original price, null when not discounted), savingsAmount and savingsPercent. A non-discounted product gets isOnSpecial: false and wasPrice: null, never a fabricated markdown. soldOut (boolean) reports stock status.

Resume and recurring updates

  • Resume (resumeFromRunId) continues one interrupted run: paste its run or dataset ID and the actor skips everything already collected there, so you don't pay twice.
  • Incremental mode (incrementalMode) is for scheduled runs over the same search, category or URL set. The first run returns everything as NEW. Later runs classify each product as NEW, UPDATED (with changedFields naming what changed) or UNCHANGED (suppressed and not billed unless emitUnchanged is on) against the state saved from the previous run. REAPPEARED and EXPIRED only enter the picture once you turn on emitExpired: a product is reported EXPIRED only after a run scans the entire tracked scope without a Max products cap and without Resume being used, and a product only comes back as REAPPEARED if it was previously marked EXPIRED this way. If you never turn emitExpired on, you will only ever see NEW, UPDATED and UNCHANGED. stateKey names or shares the stored state; leave it empty and the actor derives one automatically from the storefront, search terms and filters. With Incremental mode off, output is exactly as before.

Send results into your apps (MCP connectors)

Optionally pipe the scraped results into the apps you already use, via Model Context Protocol (MCP) connectors. This is an extra delivery step after the scrape, and the Apify dataset is never changed.

What gets written to the connector: a condensed, human-readable summary of each record, not the full JSON. Each item becomes one entry with a title and its key fields flattened to plain text. The complete record always stays in the Apify dataset.

  1. Authorize a connector once under Apify → Settings → Integrations (Notion, Linear, Airtable, or Apify).
  2. Select it in the "Pipe results into your apps" input field. If the picker is empty, you haven't authorized a connector yet.
  3. For Notion, also set notionParentPageUrl to the page where items should be created.

The connection is mediated by Apify's MCP proxy, so this actor never sees your third-party credentials. Leave the field empty to skip.

Input Parameters

ParameterTypeDefaultDescription
modestringsearchsearch or url.
storefrontstringusWhich of the 14 storefronts to scrape in search mode.
queriesarraynone (prefill: ["foundation"])Keywords to search; one search per query.
categoriesarraynone (prefill: empty)Category slugs from the storefront's navigation.
sortBystringrelevancerelevance, popular, rating, price-asc, price-desc, or newest.
specialsOnlybooleanfalseScrape the Sale collection instead of queries/categories (Southeast Asia storefronts only; a no-op elsewhere).
urlsarraynone (prefill: one example URL)One or more Sephora URLs to crawl in url mode.
brandsarraynone (prefill: empty)Brand slugs to filter results. Applies in both modes, except a single pasted product URL.
priceMinintegernoneMinimum product price in the storefront's currency.
priceMaxintegernoneMaximum product price in the storefront's currency.
ratingMininteger0Minimum average rating (0, 3, 4, or 5).
newOnlybooleanfalseOnly products marked as new arrivals.
exclusiveOnlybooleanfalseOnly products marked "Only at Sephora".
fetchDetailsbooleanfalseFetch the product detail page for ingredients, how-to-use, the full variant list and claims. Also required, in search mode, for reviews and Q&A to be fetched even when those are turned on.
fetchReviewsbooleanfalseFetch the top reviews per product. Populated today on the US and Southeast Asia storefronts. In search mode, also requires Fetch product details to be on.
maxReviewsPerProductinteger10Cap reviews per product (1 to 100). Ignored unless Fetch top reviews is on.
fetchQnabooleanfalseFetch top questions and answers per product. Populated today on the US and Southeast Asia storefronts. In search mode, also requires Fetch product details to be on.
maxQnaPerProductinteger5Cap Q&A entries per product (1 to 50). Ignored unless Fetch top Q&A is on.
maxPagesintegernone (unlimited)Optional bound on result pages walked per query, category or URL. Leave empty to walk every result page.
maxProductsinteger20Total cap across all queries/URLs. Set to 0 for unlimited.
proxyConfigurationobjectResidential (US)Connection settings. A residential connection is what the US and European storefronts need to load reliably.
resumeFromCheckpointbooleantrueResume a same-run migration or restart from the internal checkpoint.
resumeFromRunIdstringnonePaste a previous run or dataset ID to skip products it already collected.
incrementalModebooleanfalseTurn on for recurring monitoring of the same search, category or URL set.
stateKeystringnoneName or share an incremental-mode monitoring state. Leave empty to derive one automatically.
emitUnchangedbooleanfalseAlso return (and bill for) products unchanged since the last run, marked UNCHANGED.
emitExpiredbooleanfalseAlso return (and bill for) products no longer found, marked EXPIRED, once a run fully scans the tracked scope.
mcpConnectorsarraynoneOptional: send a summary of each record to apps you authorized under Integrations.
notionParentPageUrlstringnoneNotion connector only: page under which records are created.
maxNotifyListingsinteger50Cap on items written to each connector per run.

Output Example

Sample shape: values are illustrative placeholders, not from a live record.

{
"market": "sea-nz",
"source": {
"id": 500000001,
"crawlUrl": "https://www.sephora.nz/products/sample-foundation",
"canonicalUrl": "https://www.sephora.nz/products/sample-foundation",
"retailer": "SEPHORA",
"currency": "NZD",
"locale": "en-NZ"
},
"brand": "Sample Brand",
"title": "Sample Foundation",
"subtitle": "30ml",
"description": "<p>A self-priming foundation, primes, covers and sets...</p>",
"shortDescription": "<p>3-in-1 foundation primes, covers and sets...</p>",
"ingredients": "Aqua, Cyclopentasiloxane, Glycerin, ...",
"howToUse": "Shake well. Apply a small amount onto the back of your hand and use a brush or fingertips to blend onto skin.",
"claims": ["Cruelty free", "Paraben free", "Vegan"],
"currentSku": "0000000",
"price": {
"current": 18.0,
"original": 36.0,
"currency": "NZD",
"stockStatus": "IN_STOCK",
"available": true,
"inventory": 13
},
"categories": ["Makeup", "Face", "Foundation"],
"options": [
{
"name": "shade",
"id": "0",
"values": [{ "value": "1 Fair Neutral", "label": "1 Fair Neutral", "id": "0" }]
}
],
"variants": [
{
"id": "0",
"sku": "0000000",
"gtin": "000000000000",
"name": "1 Fair Neutral",
"shade": "1 Fair Neutral",
"size": "30ml",
"price": {
"current": 18.0,
"original": 36.0,
"currency": "NZD",
"stockStatus": "IN_STOCK",
"available": true,
"inventory": 13
},
"highlights": ["NEW", "Only at Sephora"],
"swatchUrl": "https://image.example.com/swatches/icon_swatch_0000.png",
"imageUrl": "https://image.example.com/products/sample.jpg"
}
],
"medias": [
{ "url": "https://image.example.com/products/sample-zoom.jpg", "type": "image", "role": "hero" }
],
"stats": {
"reviewCount": 971,
"rating": 4.8,
"recommendedCount": 800,
"totalPhotoCount": 100
},
"ratingHistogram": [
{ "RatingValue": 5, "Count": 700 },
{ "RatingValue": 4, "Count": 200 },
{ "RatingValue": 3, "Count": 50 },
{ "RatingValue": 2, "Count": 15 },
{ "RatingValue": 1, "Count": 6 }
],
"topReviews": [
{
"id": "0",
"rating": 5,
"title": "Best foundation I have ever tried",
"body": "Sample review text appears here...",
"publishedAt": "2026-01-01T00:00:00.000Z",
"skinType": "combination",
"skinTone": "fair"
}
],
"highlights": ["NEW", "Only at Sephora"],
"isOnSpecial": true,
"wasPrice": 36.0,
"savingsAmount": 18.0,
"savingsPercent": 50,
"soldOut": false,
"frontend": "sea",
"scrapedAt": "2026-01-01T00:00:00.000Z"
}

Plan Requirement

The default connection setting already uses a residential connection pinned to the United States, which is what the US and European storefronts (Germany, Romania, Sweden, Greece, Denmark, and the wider set reachable through URL mode) need to load reliably. The Southeast Asia storefronts and Mexico work with the default connection in most cases too. When you switch storefronts, pin the connection's country to that storefront's home market, for example NZ for sephora.nz or DE for sephora.de, for the most stable runs. If a request is refused, the actor automatically retries on a different connection rather than failing outright. See the Pricing tab for current rates.

FAQ

How much does it cost?

You pay per record returned, plus a small per-record surcharge when Fetch product details is on. The Pricing tab on the actor page shows the current rates. Use Max products to cap the cost of any run.

This actor collects only publicly available product data. You are responsible for how you use it: follow Sephora's terms and the laws that apply to you, and get legal advice if you plan commercial redistribution. Product descriptions, images and review text may be subject to Sephora's or its brands' own rights.

Can I get only new or changed products on a schedule?

Yes. Schedule the actor from the Schedules tab and turn on Incremental mode. Each run then returns only new and updated products by default, and unchanged ones are suppressed and not billed. A product that disappears is only reported (as EXPIRED) once you turn on Emit expired products and a run scans the full tracked scope without being capped by Max products or run with Resume. A product that comes back after being marked EXPIRED is then reported as REAPPEARED on the run where it reappears. Without Emit expired products turned on at some point, you will only ever see NEW, UPDATED and UNCHANGED.

Why did my run return no reviews or Q&A even though I turned them on?

Fetch top reviews and Fetch top Q&A currently return data on the US storefront and the Southeast Asia storefronts (Australia, New Zealand, Singapore, Malaysia, Indonesia, Thailand, Philippines). Other storefronts return an empty list for these fields even with the switches on, since their review platform is not wired up yet. In search mode, both switches also require Fetch product details to be on; otherwise they are silently ignored.

Why did my run fail instead of returning an empty dataset?

An unresolvable input, such as an empty search with no queries or categories, leaves the run SUCCEEDED with zero rows and a status message explaining why, so a first-time typo never gets billed for nothing. The run fails outright only for a genuine setup problem: a Resume from run ID that cannot be resolved to a run or dataset your account can read, or Incremental mode combined with a Resume from run ID when that search already has saved incremental state. If the site refuses every request, run it again in a few minutes.

Can I use it with AI agents or MCP?

Yes. Call it from any Apify integration or MCP client, and use the connector field to push a summary of each record into Notion, Linear or Airtable.

🔗 Want more e-commerce data?

Pair this actor with these related scrapers from the same team:

🥦 ALDI AU Scraper
Scrape ALDI Australia (aldi.com.au) products: name, brand, price, was-price, savings...
🛒 Douglas Germany Scraper
Scrape Douglas.de beauty and fragrance products by keyword, category, brand, or URL...
🛒 MUJI Scraper
Scrape MUJI products from the United States, Canada and Australia storefronts. Search by...
🛒 SHEIN Scraper
Scrape SHEIN product listings by keyword or from any category, sale or search link...
🛒 Lazada
Scrape Lazada products and reviews across SEA markets, including Malaysia, Singapore...
🛒 druni.es
Scrape Druni beauty, cosmetics and perfume products. Search by keyword, category, Ofertas...

👉 Browse all abotapi scrapers

💬 Support & custom scrapers

  • 🐞 Found a bug or a missing field? Open a ticket on the Issues tab. We usually reply within hours.
  • 🛠️ Need another site, extra fields or a private build? Email abotapi@proton.me or message Telegram @abotapi.
  • ⭐ Enjoying it? A quick review on the actor page helps other users find it.