# Notino Scraper \[$2.30/1K💰] | 27 Countries | Reviews (`ahmed_jasarevic/notino-scraper`) Actor

Scrape Notino's beauty catalog from 27 country shops - products, brands, variants, prices, currency, ratings and customer reviews. Paste a search or brand URL and get the full result set. No browser needed. Built for price monitoring and market research.

- **URL**: https://apify.com/ahmed_jasarevic/notino-scraper.md
- **Developed by:** [Ahmed Jasarevic](https://apify.com/ahmed_jasarevic) (community)
- **Stats:** 2 total users, 2 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.30 / 1,000 results

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/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
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.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## 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.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Notino Scraper — Beauty & Cosmetics Products, Prices and Reviews Across 27 Country Shops

Extract **Notino product catalog data** — product names, brands, prices, currency, variants, ratings and full customer reviews — from any of Notino's **27 country shops**. Paste a Notino search or brand URL and it walks the entire result set, then enriches every product from Notino's own backend API.

No browser is needed, and no proxy is needed for short runs. Built for **beauty price monitoring, MAP compliance, brand tracking, competitor analysis and affiliate catalogs**.

***

### Main use cases

- **Beauty price monitoring and MAP compliance** — daily runs on the same search URL, diffed on `variants[].price` per market
- **Multi-market pricing comparison** — mix `notino.de`, `notino.pl` and `notino.co.uk` URLs in one run and get EUR, PLN and GBP prices for the same product IDs
- **Brand catalog builds** — pull a brand page and get every product, variant, size and price
- **Review collection for sentiment and voice-of-customer analysis** — review text, star score and author, de-duplicated across pages
- **Competitor assortment tracking** — which SKUs a brand lists in one market but not another
- **Affiliate and aggregator catalog feeds** — product URLs, brand, description and images ready for a storefront

***

### Input

| Field | Type | Required | Default | Notes |
|---|---|---|---|---|
| `searchUrls` | array | no | `["https://www.notino.co.uk/search/?exps=shampoo"]` | **Main input.** Notino search / brand / category URLs, exactly as they appear in your browser. Each URL carries its own country shop, so prices and currency follow the market you link to. URLs from different countries can be mixed in one run. |
| `maxPagesPerSearchUrl` | integer | no | `5` | Result pages to walk per search URL. One page holds 24 products, so 5 ≈ 120 products. `0` = every page (max 500). |
| `sortOption` | integer | no | unset | Notino's sort index used while paginating. Leave empty for the default order. |
| `productUrls` | array | no | `[]` | Direct product page URLs. Product IDs are read automatically from the `/p-{id}` segment. |
| `productIds` | array | no | `[]` | Bare numeric IDs (e.g. `16316126`). Because a bare ID has no country, these resolve in UK prices. |
| `startUrls` | array | no | `[]` | Alias of `searchUrls`, kept for existing runs. Sitemap URLs are **not** supported — sitemap entries carry SEO slugs without the `/p-{id}` the API needs. |
| `includeReviews` | boolean | no | `true` | Fetch customer reviews into the separate `reviews` dataset. Reviews are billed as their own pay-per-event, so `false` gives a catalog-only run. |
| `maxReviewsPerProduct` | integer | no | `20` | Cap per product, `0` = none, maximum 500. Reviews are de-duplicated by ID while paging. |
| `maxItems` | integer | no | `100` | Cap on products per run (maximum 100,000). |
| `proxy` | object | no | `useApifyProxy: false` | Standard Apify proxy picker. Not needed for short runs; enable residential proxy for deep listing walks. |

**There is no country setting.** Each URL you paste identifies its own Notino shop and the Actor follows it, so prices, currency, product URLs and reviews all come from the country you linked to.

#### Supported country shops

Any of Notino's 27 shops, with or without the `www.` prefix:

`notino.co.uk`, `notino.de`, `notino.fr`, `notino.es`, `notino.it`, `notino.pl`, `notino.cz`, `notino.sk`, `notino.at`, `notino.nl`, `notino.be`, `notino.ch`, `notino.pt`, `notino.ie`, `notino.gr`, `notino.hu`, `notino.ro`, `notino.bg`, `notino.hr`, `notino.si`, `notino.ua`, `notino.se`, `notino.dk`, `notino.fi`, `notino.ee`, `notino.lv`, `notino.lt`

A URL from any other host is skipped with a warning naming the problem. Note that **`notino.com` is a marketing landing page** with no search and no product API, so it cannot be scraped — link a specific country shop instead.

***

### Output

Two datasets, selectable in the **Output** tab.

#### Products (default dataset)

| Field | Type | Description |
|---|---|---|
| `productId` | string | Notino product ID |
| `productCode` | string | Notino master product code (used to fetch reviews) |
| `productName` | string | Derived name — brand + variant + URL slug |
| `productUrl` | string | Canonical product page URL |
| `brand` | string | Brand name |
| `manufacturer` | string | Manufacturer |
| `countryDomain` | string | Shop the product was found on, e.g. `www.notino.de` |
| `categories` | array | Category labels, in the market's own language |
| `description` | string | Product description (HTML) |
| `rating` | number | Average review rating, 0–5 |
| `reviewCount` | number | Number of reviews **actually collected** for this product |
| `reviewsTruncated` | boolean | `true` when the product had more reviews than `maxReviewsPerProduct` allowed |
| `variants` | array | `{variantId, variantName, variantUrl, price, currency, color}` |

#### Customer reviews (`reviews` dataset)

One row per review, repeating the product context so the dataset is self-contained and joins cleanly on `productId` or `productCode`.

| Field | Type | Description |
|---|---|---|
| `reviewId` | number | Notino review ID |
| `productId` | string | Product the review belongs to |
| `productCode` | string | Notino master product code |
| `productName` | string | Product name, repeated for convenience |
| `productUrl` | string | Canonical product page URL |
| `brand` | string | Brand name |
| `countryDomain` | string | Shop the review was collected on |
| `title` | string | Review headline, or `null` |
| `text` | string | Review body, or `null` |
| `score` | number | Star score |
| `author` | string | Reviewer display name |

***

### Example input

```json
{
  "searchUrls": [
    "https://www.notino.co.uk/search/?exps=shampoo"
  ],
  "maxPagesPerSearchUrl": 5,
  "maxItems": 100,
  "includeReviews": true,
  "maxReviewsPerProduct": 50
}
```

Multi-market price comparison — one search term, three shops, three currencies:

```json
{
  "searchUrls": [
    "https://www.notino.de/search/?exps=shampoo",
    "https://www.notino.pl/search/?exps=shampoo",
    "https://www.notino.co.uk/search/?exps=shampoo"
  ],
  "maxPagesPerSearchUrl": 2,
  "includeReviews": false
}
```

Catalog-only price run (cheapest — no review events):

```json
{
  "searchUrls": ["https://www.notino.de/"],
  "includeReviews": false,
  "maxPagesPerSearchUrl": 10,
  "maxItems": 240
}
```

***

### Example output

Product row:

```json
{
  "productId": "16316126",
  "productCode": "SWRCRSW_KCOL13",
  "productName": "Schwarzkopf Creme Supreme Permanent Hair Dye",
  "productUrl": "https://www.notino.co.uk/schwarzkopf/creme-supreme-permanent-hair-dye/",
  "brand": "Schwarzkopf",
  "manufacturer": "Henkel Consumer Brands",
  "countryDomain": "www.notino.co.uk",
  "categories": ["Permanent hair colour"],
  "description": "<p>Deep black with lasting shine…</p>",
  "rating": 4.8,
  "reviewCount": 3,
  "reviewsTruncated": false,
  "variants": [
    {
      "variantId": "16316117",
      "variantName": "Creme Supreme",
      "variantUrl": "https://www.notino.co.uk/schwarzkopf/creme-supreme-permanent-hair-dye/p-16316117/",
      "price": 7.49,
      "currency": "GBP",
      "color": null
    }
  ]
}
```

Review row:

```json
{
  "reviewId": 3364088,
  "productId": "16316126",
  "productCode": "SWRCRSW_KCOL13",
  "productName": "Schwarzkopf Creme Supreme Permanent Hair Dye",
  "productUrl": "https://www.notino.co.uk/schwarzkopf/creme-supreme-permanent-hair-dye/",
  "brand": "Schwarzkopf",
  "countryDomain": "www.notino.co.uk",
  "title": "Gorgeous hair colour",
  "text": "This is a beautiful hair colour, rich and glossy and it lasted three weeks.",
  "score": 5,
  "author": "Sylvia"
}
```

***

### Monitor beauty prices and build a 27-market catalog on a schedule

Every Apify Actor is callable over HTTP, so the standard pattern is a recurring run over the same inputs:

- **Daily** — same search URL; diff `variants[].price` to catch price changes and MAP violations
- **Weekly** — a brand page; diff the variant list to catch assortment changes
- **Monthly** — add another country shop to `searchUrls` to grow market coverage
- **Wire into your stack** — Apify webhooks, Zapier, Make, Google Sheets and 100+ integrations fire on run completion; both datasets export as JSON, CSV, Excel, XML, HTML or RSS

Keep catalog runs and review runs on separate schedules: `includeReviews: false` is dramatically cheaper, and reviews are the second billed event.

***

### Related Actors

- [Douglas Scraper](https://apify.com/ahmed_jasarevic/douglas-scraper) (`ahmed_jasarevic/douglas-scraper`) — Europe's largest perfumery chain: products, prices, stock and categories for beauty price monitoring
- [Sephora Scraper](https://apify.com/ahmed_jasarevic/sephora-scraper) (`ahmed_jasarevic/sephora-scraper`) — US beauty retail catalog, prices and reviews
- [Lookfantastic Scraper](https://apify.com/ahmed_jasarevic/lookfantastic-scraper) (`ahmed_jasarevic/lookfantastic-scraper`) — premium beauty and hair care products across European markets
- [Perfume Scraper](https://apify.com/ahmed_jasarevic/perfume-scraper) (`ahmed_jasarevic/perfume-scraper`) — fragrance-specific catalog and price data
- [Idealo Scraper](https://apify.com/ahmed_jasarevic/idealo-scraper) (`ahmed_jasarevic/idealo-scraper`) — German price-comparison data, useful for cross-checking beauty prices against a wider market

***

### FAQ

#### Why use this Actor instead of Notino's website or an official API?

Notino does not publish a public developer API for its catalog. This Actor reads the same backend that Notino's own frontend uses, plus the server-rendered result pages — so you get the complete product, variant and review data as JSON, instead of scraping HTML fragments by hand. You also get pagination handled for you, which is where most manual Notino scrapers break.

#### What are the alternatives?

- **Notino's affiliate/partner program** — gives you promoted product feeds for a given market, not the full result set for an arbitrary search term, and not the review archive.
- **A Playwright-based scraper** — orders of magnitude more compute, and the data still has to be reconstructed from the page.
- **Douglas / Sephora scrapers** — different retailers; useful as market context, not a substitute for Notino's own assortment.

#### Why are reviews in a separate dataset?

So you can export, join and price them independently of the product catalog. It also means a catalog-only run (`includeReviews: false`) is charged at product rate only, and you never pay for reviews you did not ask for. Each review row repeats its product context, so the dataset is still self-contained.

#### Does it need a proxy?

Not for short runs. Product and review data come from Notino's backend API, which does not challenge requests, and a handful of listing pages work from a normal IP. For deep listing walks (10+ pages per search URL, many country shops in one run) enable the Apify residential proxy in the run input — no code change needed.

#### Why does `reviewCount` differ from the number shown on Notino?

The API does not expose an upstream review total, so `reviewCount` is what was actually fetched within `maxReviewsPerProduct`. When the cap truncated the archive, `reviewsTruncated` is `true`, so you know the number is a floor rather than the full count.

#### Why did one of my reviews only return 20?

Notino caps a review page at 20 and sorts by rating with no stable tie-break, so the same review can appear on two pages. The Actor pages with a fixed window of 20, de-duplicates by review ID, and stops on a short or fully-duplicate page — so a product with 60 reviews returns 60. If you still get exactly 20, raise `maxReviewsPerProduct`.

#### Are review dates available?

No. The API exposes only review text, score and author — there is no date field. Do not rely on a date column in your output schema.

#### Can I scrape a brand page instead of a search page?

Yes. A brand URL like `https://www.notino.co.uk/dior/` works in `searchUrls` and is treated as a listing.

***

### For AI Agents & LLM Apps

Callable via the Apify MCP server and the Apify API. Returns Notino beauty products in the default dataset and customer reviews in the `reviews` dataset.

**Minimal valid input** — one search URL, default limits:

```json
{ "searchUrls": ["https://www.notino.co.uk/search/?exps=shampoo"] }
```

**Cheapest useful run** — catalog and prices only, no review events:

```json
{
  "searchUrls": ["https://www.notino.de/search/?exps=shampoo"],
  "includeReviews": false,
  "maxPagesPerSearchUrl": 10
}
```

**Direct products** — skip discovery entirely:

```json
{ "productUrls": ["https://www.notino.co.uk/schwarzkopf/creme-supreme-permanent-hair-dye/p-16316126"] }
```

**Output fields** — products: `productId`, `productCode`, `productName`, `productUrl`, `brand`, `manufacturer`, `countryDomain`, `categories`, `description`, `rating`, `reviewCount`, `reviewsTruncated`, `variants` (each with `variantId`, `variantName`, `variantUrl`, `price`, `currency`, `color`). Reviews: `reviewId`, `productId`, `productCode`, `productName`, `productUrl`, `brand`, `countryDomain`, `title`, `text`, `score`, `author`.

**Behaviors an agent should know**

- **The URL carries the country.** There is no separate country field. Prices, currency and `countryDomain` follow whichever shop each URL points at, and URLs from different countries can be mixed in one run — do not try to set a market explicitly.
- **`notino.com` cannot be scraped.** It is a marketing landing page with no search and no product API. Always use a country shop such as `notino.de` or `notino.co.uk`; other hosts are skipped with a warning.
- **`productIds` without a country resolve in UK prices.** Prefer `productUrls` when the market matters.
- **Use `?exps=` for search terms.** The older `?search=` form no longer returns a result grid; the legacy `/search.asp?exps=` path is rewritten automatically. A search URL works in either `searchUrls` or `productUrls`.
- **Sitemap URLs are not supported** — they carry SEO slugs without the `/p-{id}` segment the API requires.
- **`includeReviews` defaults to `true`.** Turning it off removes the second billed event and is the right choice for price/catalog runs. `maxReviewsPerProduct: 0` also disables reviews.
- **One request per 10 product IDs**, and reviews page at 20 per request — size your expectations and your timeout accordingly. A 100-product run with 20 reviews each finishes in well under a minute on 256 MB.
- **`reviewCount` is what was fetched, not the upstream total.** Use `reviewsTruncated` to know whether the cap was hit.
- **No review dates exist in the output.** Do not build a time-series on review recency.

**Billing model** — pay per event: one `result` event per product ($0.0023–$0.0025) and, only when `includeReviews` is `true`, one `review` event per review collected ($0.0014–$0.0015). A run that hits the caller's spending limit stops immediately rather than continuing to work for free.

***

### Legal & Compliance Disclaimer

This Actor is an independent third-party tool. It is not affiliated with, endorsed by, sponsored by, or connected with Notino, Ashland Ventures s.r.o., or any Notino group company.

It reads **only publicly accessible pages and backend responses** on Notino's country shops. It does not log in, does not bypass authentication, does not solve CAPTCHAs, and does not use proxies by default.

Output includes **reviewer display names and review text**. That is personal data. You are responsible for your own lawful basis for processing it, for complying with Notino's Terms of Service, and for complying with applicable data-protection law including GDPR, UK GDPR and CCPA. Do not use reviewer data for unsolicited commercial outreach.

Product data scraped from a retailer may be subject to contractual or database-rights restrictions even when it is publicly viewable — check Notino's Terms of Service before large-scale collection, redistribution or resale.

This Actor is a data-collection tool; it does not provide legal advice and makes no claim that any particular use is permitted.

***

### SEO Keywords

notino scraper, notino api, notino data, cosmetics product data, beauty product database, perfume price tracker, beauty price monitoring, map compliance monitoring, notino country shops, skincare product data, ecommerce product data, product catalog scraping, brand catalog build, multi country pricing data, cosmetics reviews scraper, product review data, affiliate product feed, beauty market research, notino alternative, cosmetics aggregator data, product variant prices, daily price monitoring, europe ecommerce data

# Actor input Schema

## `searchUrls` (type: `array`):

Notino search, brand or category pages to scrape products from. Paste the URL exactly as it appears in your browser - e.g. https://www.notino.co.uk/search/?exps=shampoo for a keyword search, or https://www.notino.co.uk/dior/ for a brand. The country shop is taken from each URL, so prices and currency follow the market you link to, and URLs from different countries can be mixed in one run. All matching products are discovered and the result set is paginated automatically using 'maxPagesPerSearchUrl'. The whole flow works without a proxy for a handful of pages; enable Apify residential proxy for deep runs.

## `maxPagesPerSearchUrl` (type: `integer`):

How many result pages to walk for each search/brand/category URL (one page holds 24 products, so 5 pages is roughly 120 products). 0 = every page.

## `sortOption` (type: `integer`):

Optional. Notino's sort index used while paginating (part of the 'f={page}-{sort}' URL parameter). Leave empty to use the default.

## `productUrls` (type: `array`):

Optional. Notino product page URLs (e.g. https://www.notino.co.uk/schwarzkopf/creme-supreme-permanent-hair-dye/p-16316126). Product IDs are extracted automatically from the /p-{id} part of each URL.

## `productIds` (type: `array`):

Optional. Bare Notino product IDs (numeric, e.g. 16316126). Combined with IDs extracted from productUrls and discovered from searchUrls.

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

Optional. Alias of 'Search URLs' kept for existing runs. Sitemap URLs are NOT supported: sitemap entries carry SEO slugs without the /p-{id} that the API needs.

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

Fetch customer reviews (text, rating score, author) for each product. When enabled, reviews are written to a separate 'reviews' dataset - one row per review, each carrying the product it belongs to - instead of being nested inside the product rows. Reviews are billed as their own pay-per-event unit, so they are charged separately from products.

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

Maximum number of reviews to fetch per product (0 = none). The API serves reviews 20 at a time and Notino's ordering is not stable, so reviews are de-duplicated by ID while paging; the highest value is 500.

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

Maximum number of products to scrape in one run.

## `proxy` (type: `object`):

Select proxies to be used by your crawler.

## Actor input object example

```json
{
  "searchUrls": [
    "https://www.notino.co.uk/search/?exps=shampoo"
  ],
  "maxPagesPerSearchUrl": 1,
  "productUrls": [],
  "productIds": [],
  "startUrls": [],
  "includeReviews": false,
  "maxReviewsPerProduct": 20,
  "maxItems": 10,
  "proxy": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

## `results` (type: `string`):

No description

## `reviews` (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 = {
    "searchUrls": [
        "https://www.notino.co.uk/search/?exps=shampoo"
    ],
    "productUrls": [],
    "productIds": [],
    "startUrls": [],
    "proxy": {
        "useApifyProxy": false
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("ahmed_jasarevic/notino-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 = {
    "searchUrls": ["https://www.notino.co.uk/search/?exps=shampoo"],
    "productUrls": [],
    "productIds": [],
    "startUrls": [],
    "proxy": { "useApifyProxy": False },
}

# Run the Actor and wait for it to finish
run = client.actor("ahmed_jasarevic/notino-scraper").call(run_input=run_input)

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

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

```

## CLI example

```bash
echo '{
  "searchUrls": [
    "https://www.notino.co.uk/search/?exps=shampoo"
  ],
  "productUrls": [],
  "productIds": [],
  "startUrls": [],
  "proxy": {
    "useApifyProxy": false
  }
}' |
apify call ahmed_jasarevic/notino-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,ahmed_jasarevic/notino-scraper"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

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