# Kruidvat Scraper — Belgium & Netherlands Products & Prices (`studio-amba/kruidvat-scraper`) Actor

Scrape product listings, prices, ratings, and availability from Kruidvat Belgium (kruidvat.be) and Netherlands (kruidvat.nl). No login required.

- **URL**: https://apify.com/studio-amba/kruidvat-scraper.md
- **Developed by:** [Studio Amba](https://apify.com/studio-amba) (community)
- **Categories:** E-commerce
- **Features:** Limited permissions
- **Stats:** 1 total users, 0 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.00 / 1,000 result scrapeds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

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

## Kruidvat Scraper -- Belgium & Netherlands Products, Prices & Deals

Scrape product data from Kruidvat.be (Belgium) and Kruidvat.nl (Netherlands) -- the Benelux's largest drugstore chain with over 1,200 locations. Get structured data on beauty products, personal care, baby items, health supplements, and household essentials at everyday low prices.

### How to scrape Kruidvat data

Kruidvat Scraper supports both the Belgian and Dutch Kruidvat stores. Pick your country, enter a search query or category URL, and the scraper handles the rest. No login or cookies required.

#### What is Kruidvat?

Kruidvat is the dominant drugstore brand in Belgium and the Netherlands, owned by AS Watson Group. They stock thousands of products across beauty, personal care, health, baby, and household categories -- from EUR 1.99 shampoo to high-end skincare lines. Their aggressive promotions and "1+1 gratis" deals make price tracking especially valuable.

Who uses this scraper:

- **Price comparison platforms** -- Kruidvat sets the benchmark for drugstore pricing in the Benelux. Track their prices to power comparison features across beauty, health, and personal care.
- **Brand managers & manufacturers** -- Monitor how your products are priced and positioned at the biggest Benelux drugstore chain. Detect unauthorized discounting or track promotional cycles.
- **E-commerce competitors** -- If you run a pharmacy, beauty store, or health shop in Belgium or the Netherlands, Kruidvat is your pricing floor. Know when they run promotions before your customers do.
- **Market researchers** -- Analyze the Benelux drugstore market: category sizes, price distributions, brand representation, and seasonal patterns.
- **Deal tracking & couponing** -- Kruidvat's frequent promotions (1+1, 2e halve prijs, 25% korting) create opportunities for deal-focused content and apps.

#### Choose your country

Use the `country` input to switch between Belgium and the Netherlands:

```json
{
    "country": "BE",
    "searchQuery": "shampoo",
    "maxResults": 100
}
```

```json
{
    "country": "NL",
    "searchQuery": "shampoo",
    "maxResults": 100
}
```

#### Search by keyword

The fastest way to find specific products:

```json
{
    "country": "NL",
    "searchQuery": "zonnebrand",
    "maxResults": 50
}
```

#### Browse a category

Scrape an entire product category. Grab category URLs from kruidvat.be or kruidvat.nl navigation:

```json
{
    "country": "BE",
    "categoryUrl": "https://www.kruidvat.be/nl/verzorging/haarverzorging/shampoo",
    "maxResults": 200
}
```

```json
{
    "country": "NL",
    "categoryUrl": "https://www.kruidvat.nl/verzorging/haarverzorging/shampoo",
    "maxResults": 200
}
```

If a `categoryUrl` is provided, it takes priority over the `searchQuery`.

**Tip:** Kruidvat's category tree is deep. Target leaf categories (like "Shampoo > Droog haar") for focused scraping, or parent categories (like "Haar") for broader coverage.

### What data does Kruidvat Scraper extract?

| Field | Type | Description |
|-------|------|-------------|
| `name` | String | Full product title |
| `brand` | String | Brand name (Nivea, L'Oreal, Kruidvat eigen merk, Pampers, etc.) |
| `price` | Number | Current selling price in EUR |
| `currency` | String | Always "EUR" |
| `originalPrice` | Number | Price before promotions |
| `ean` | String | 13-digit EAN barcode |
| `sku` | String | Kruidvat product number |
| `inStock` | Boolean | Online stock status |
| `rating` | Number | Average customer rating (0-5) |
| `reviewCount` | Number | Number of customer reviews |
| `imageUrl` | String | Primary product image |
| `imageUrls` | Array | All product images |
| `description` | String | Product details |
| `category` | String | Deepest category in breadcrumb |
| `categories` | Array | Full category breadcrumb path |

### Output

A realistic Kruidvat product record:

```json
{
    "name": "Andrélon Shampoo Levendig Lang",
    "brand": "Andrélon",
    "price": 3.49,
    "currency": "EUR",
    "url": "https://www.kruidvat.nl/andrelon-shampoo-levendig-lang/p/4305728",
    "scrapedAt": "2026-05-19T09:15:00.000Z",
    "originalPrice": 4.99,
    "ean": "8710447321942",
    "sku": "4305728",
    "inStock": true,
    "rating": 4.3,
    "reviewCount": 87,
    "imageUrl": "https://static.kruidvat.nl/medias/product/4305728-front.jpg",
    "imageUrls": [
        "https://static.kruidvat.nl/medias/product/4305728-front.jpg",
        "https://static.kruidvat.nl/medias/product/4305728-back.jpg"
    ],
    "description": "Andrélon Shampoo Levendig Lang maakt je haar zacht en glanzend. Speciaal ontwikkeld voor lang haar dat snel dof en pluizig wordt.",
    "category": "Shampoo",
    "categories": ["Haar", "Shampoo"]
}
```

### How much does it cost?

| Scenario | Estimated cost |
|----------|---------------|
| 100 products (search) | ~$0.02 |
| 500 products (category) | ~$0.08 |
| 2,000 products (multiple categories) | ~$0.30 |
| Large catalog crawl | ~$0.50+ |

Kruidvat Scraper fetches server-rendered pages over plain HTTP through an unblocking proxy layer and reads the embedded product data directly. No browser is launched, and each request returns a full listing page of products, keeping the cost per result low.

Note: a run's usage cost only settles after the run reports SUCCEEDED — the final amount can differ slightly from the live estimate shown while the run is in progress.

### Can I integrate?

Connect Kruidvat data to your tools:

- **Google Sheets** -- track Benelux drugstore prices in a spreadsheet
- **Webhooks** -- trigger alerts when promotions start or prices drop
- **Zapier / Make** -- build automated workflows around price changes
- **Slack** -- daily notifications on Kruidvat deals in specific categories
- **Amazon S3 / Google Cloud Storage** -- archive weekly pricing snapshots
- **PostgreSQL / MySQL** -- feed data into your analytics database

### Can I use it as an API?

#### Python

```python
from apify_client import ApifyClient

client = ApifyClient("YOUR_API_TOKEN")

run = client.actor("studio-amba/kruidvat-scraper").call(run_input={
    "country": "NL",
    "searchQuery": "zonnebrand",
    "maxResults": 50,
})

for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    price_info = f"EUR {item['price']}"
    if item.get('originalPrice'):
        price_info += f" (was EUR {item['originalPrice']})"
    print(f"{item['brand']} - {item['name']} -- {price_info}")
```

#### JavaScript

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

const client = new ApifyClient({ token: 'YOUR_API_TOKEN' });

const run = await client.actor('studio-amba/kruidvat-scraper').call({
    country: 'NL',
    searchQuery: 'zonnebrand',
    maxResults: 50,
});

const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach(item => {
    const sale = item.originalPrice ? ` (was EUR ${item.originalPrice})` : '';
    console.log(`${item.brand} - ${item.name} -- EUR ${item.price}${sale}`);
});
```

### Input parameters

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `country` | String | `"BE"` | Which Kruidvat site to scrape: `"BE"` (kruidvat.be) or `"NL"` (kruidvat.nl) |
| `categoryUrl` | String | | A Kruidvat category page URL to scrape |
| `searchQuery` | String | `"shampoo"` | Search for products by keyword |
| `maxResults` | Integer | `100` | Maximum number of products to return |
| `proxyConfiguration` | Object | | Legacy field, accepted for compatibility (fetches go through a built-in unblocking layer) |
| `brightDataApiKey` | String | | Optional Bright Data API key override; the actor ships with its own |

### FAQ

**Does this scrape Kruidvat Belgium or Netherlands?**
Both. Use the `country` input to select `"BE"` for kruidvat.be or `"NL"` for kruidvat.nl. The scraper automatically adjusts URLs and language headers.

**Can I track promotions like "1+1 gratis"?**
The scraper captures `originalPrice` when a product is on promotion. The specific promotion type (1+1, 2e halve prijs, etc.) is reflected in the price difference but not as a separate field.

**How do I find the right category URL?**
Browse kruidvat.be or kruidvat.nl, navigate to the category you want, and copy the URL from your browser's address bar (for example `https://www.kruidvat.nl/verzorging/haarverzorging/shampoo`).

**What language is the data in?**
Product data comes in Dutch. Belgian results use the kruidvat.be catalog, Dutch results use kruidvat.nl.

**How often do Kruidvat prices change?**
Kruidvat runs weekly promotions (folder deals). Scraping weekly on Monday or Tuesday captures the new promotion cycle. Daily scraping catches flash deals.

**Are Kruidvat's own-brand products included?**
Yes. Kruidvat eigen merk products appear in results like any other brand.

### Limitations

- Product data is extracted from HTML. If Kruidvat changes their page structure, some fields may temporarily return empty.
- Kruidvat's in-store promotions and member-only deals may differ from what appears online.
- Stock status reflects online availability, not individual store inventory.
- Very large category scrapes may take longer due to pagination and per-product detail page visits.

### Other retail and beauty scrapers

Build comprehensive Benelux and European retail intelligence:

- [ICI PARIS XL Scraper](https://apify.com/studio-amba/iciparisxl-scraper) -- Belgian beauty and perfume (premium segment)
- [Rituals Scraper](https://apify.com/studio-amba/rituals-scraper) -- Luxury cosmetics and home fragrance
- [Action Scraper](https://apify.com/studio-amba/action-scraper) -- Pan-European discount retailer
- [Mytheresa Scraper](https://apify.com/studio-amba/mytheresa-scraper) -- Luxury fashion from 200+ designers
- [AS Adventure Scraper](https://apify.com/studio-amba/asadventure-scraper) -- Outdoor and adventure gear
- [Bergfreunde Scraper](https://apify.com/studio-amba/bergfreunde-scraper) -- Climbing and hiking equipment
- [Intersport Scraper](https://apify.com/studio-amba/intersport-scraper) -- European sports retail
- [Helly Hansen Scraper](https://apify.com/studio-amba/hellyhansen-scraper) -- Outdoor and sailing apparel

### Your feedback

Found an issue or want a new feature? Let us know through the Apify Store actor page. We fix bugs quickly and actively maintain this scraper.

# Actor input Schema

## `country` (type: `string`):

Which Kruidvat site to scrape. Belgium (kruidvat.be) or Netherlands (kruidvat.nl).

## `categoryUrl` (type: `string`):

A Kruidvat category page URL to scrape. Example: https://www.kruidvat.be/nl/verzorging/haarverzorging/shampoo or https://www.kruidvat.nl/verzorging/haarverzorging/shampoo

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

Search for products by keyword. Used if no categoryUrl is provided.

## `maxResults` (type: `integer`):

Maximum number of products to return.

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

Accepted for compatibility but not used for the actual page fetches, which go through the Bright Data Web Unlocker (the only transport that clears Kruidvat's anti-bot wall).

## `brightDataApiKey` (type: `string`):

Bright Data API key for the Web Unlocker zone. Optional — falls back to the BRIGHT_DATA_API_KEY environment variable configured on the actor.

## Actor input object example

```json
{
  "country": "NL",
  "categoryUrl": "",
  "searchQuery": "shampoo",
  "maxResults": 5,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "NL"
  }
}
```

# Actor output Schema

## `results` (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 = {
    "country": "NL",
    "categoryUrl": "",
    "searchQuery": "shampoo",
    "maxResults": 5,
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ],
        "apifyProxyCountry": "NL"
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("studio-amba/kruidvat-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 = {
    "country": "NL",
    "categoryUrl": "",
    "searchQuery": "shampoo",
    "maxResults": 5,
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
        "apifyProxyCountry": "NL",
    },
}

# Run the Actor and wait for it to finish
run = client.actor("studio-amba/kruidvat-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 '{
  "country": "NL",
  "categoryUrl": "",
  "searchQuery": "shampoo",
  "maxResults": 5,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "NL"
  }
}' |
apify call studio-amba/kruidvat-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,studio-amba/kruidvat-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/JTyGSJUjQFmY9Ou9W/builds/itVdpcExrBTLqf5uF/openapi.json
