# bol.com Products, Offers & Reviews Scraper (`automation-lab/bol-com-scraper`) Actor

Extract bol.com products, offers, prices, availability, ratings, and reviews for Netherlands and Belgium marketplace monitoring.

- **URL**: https://apify.com/automation-lab/bol-com-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 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

## bol.com Products, Offers & Reviews Scraper

Extract public bol.com product records for price, availability, seller, offer, rating, and review monitoring across the Netherlands and Belgium marketplaces.

Use the Actor as a bol data source for one-time catalog research or scheduled marketplace comparisons. It accepts product searches and public product URLs, then writes one normalized product record per result to the default dataset.

### What does this bol.com scraper do?

The Actor opens bol.com through a location-matched Netherlands or Belgium residential browser session. It reads server-rendered search cards and enriches products from public structured data on each product page.

A result can include:

- stable bol.com product ID and EAN;
- product and selected variant title;
- current price, advice/list price, and currency;
- stock availability and current seller;
- brand, description, color, material, and images;
- aggregate rating and total review count;
- public product or variant offers exposed by bol.com;
- up to six public review samples;
- search query, marketplace, rank, source URL, and extraction time.

No login, buyer account, checkout, order, or private customer data is accessed.

### Who is this Actor for?

- **Marketplace analysts** comparing assortment, prices, and stock between bol.com NL and BE.
- **Brands and manufacturers** checking how products and variants appear in search.
- **Retail operators** creating scheduled product-price and availability snapshots.
- **Review researchers** combining aggregate ratings with the public review samples exposed on product pages.
- **Data engineers** sending structured bol products to a spreadsheet, warehouse, BI tool, webhook, or API workflow.

### Why use it for marketplace monitoring?

Direct requests to bol.com are commonly challenged. This Actor manages a sticky, country-matched residential browser session and rotates the complete session after an explicit block. It also blocks images, fonts, video, and other unnecessary binary resources to limit transfer and runtime.

The output uses stable field names for repeat runs. That makes it practical to compare `price`, `availability`, `seller`, `rating`, and `reviewCount` over time outside the Actor.

### How to get started

1. Open the Actor input page.
2. Enter one or more `queries`, add bol.com `startUrls`, or use both.
3. Select the `NL` or `BE` marketplace for query searches.
4. Keep `includeDetails` enabled when you need EAN, descriptions, offers, and review samples.
5. Set `maxItems` to the maximum unique products you want.
6. Run the Actor and open the **Products** dataset view.
7. Export JSON, CSV, Excel, XML, or RSS, or connect the dataset through the Apify API.

A small first run is recommended before increasing the limit.

### Input parameters

| Field | Type | Default | Purpose |
| --- | --- | --- | --- |
| `queries` | string array | `['laptop']` | Searches products on the selected marketplace. |
| `startUrls` | URL array | empty | Public bol.com product or search URLs. |
| `marketplace` | `NL` or `BE` | `NL` | Selects the query URL and matching proxy country. A URL's own `/nl/` or `/be/` path takes precedence. |
| `maxItems` | integer, 1–500 | `20` | Maximum unique product records across all inputs. |
| `includeDetails` | boolean | `true` | Visits each product page for EAN, description, structured offers, ratings, and reviews. |
| `maxReviews` | integer, 0–6 | `6` | Maximum public review samples kept per product. |

Provide at least one non-empty query or bol.com URL. Other domains are rejected before browsing.

### Search products in the Netherlands

```json
{
  "queries": ["laptop"],
  "marketplace": "NL",
  "maxItems": 5,
  "includeDetails": true,
  "maxReviews": 3
}
```

This route returns ranked search products and enriches each accepted item from its product page.

### Extract one bol.com product URL

```json
{
  "queries": [],
  "startUrls": [
    {
      "url": "https://www.bol.com/nl/nl/p/lenovo-ideapad-slim-3-16arp10-laptop-16-inch-ryzen-7-16gb-1tb/9300000251047023/"
    }
  ],
  "marketplace": "NL",
  "maxItems": 1,
  "includeDetails": true,
  "maxReviews": 6
}
```

Direct URL mode is useful when another system already stores bol.com product IDs or URLs.

### Output fields

Every default-dataset row is a product object. Arrays remain in the same row so common exports and integrations need no dataset joins.

| Field | Meaning |
| --- | --- |
| `productId`, `ean` | bol.com product ID and EAN when available. |
| `title`, `brand`, `description` | Product identity and public description. |
| `url`, `marketplace`, `query`, `rank` | Source and discovery context. |
| `price`, `listPrice`, `currency` | Current and advice prices. |
| `availability`, `seller` | Current stock signal and merchant. |
| `rating`, `reviewCount` | Aggregate public review metrics. |
| `imageUrl`, `images`, `color`, `material` | Catalog attributes exposed by the page. |
| `offers` | Public product/variant offer objects exposed in structured data. |
| `reviews` | Up to `maxReviews` public review samples. |
| `scrapedAt` | UTC extraction timestamp. |

Source fields can be `null` when bol.com does not expose them for a product.

### Output example

A current local product-page run returned the following shape:

```json
{
  "productId": "9300000251047023",
  "ean": "0199274041410",
  "title": "Lenovo IdeaPad Slim 3 16ARP10 - Laptop - 16 inch - Ryzen 7 - 16GB/1TB",
  "brand": "Lenovo",
  "url": "https://www.bol.com/nl/nl/p/lenovo-ideapad-slim-3-16arp10-laptop-16-inch-ryzen-7-16gb-1tb/9300000251047023/",
  "marketplace": "NL",
  "query": null,
  "rank": null,
  "price": 669,
  "listPrice": null,
  "currency": "EUR",
  "availability": "InStock",
  "seller": "bol",
  "rating": 4.8,
  "reviewCount": 21,
  "offers": [
    {
      "productId": "9300000251047023",
      "price": 669,
      "currency": "EUR",
      "availability": "InStock",
      "condition": "NewCondition",
      "seller": "bol"
    }
  ],
  "reviews": [
    {
      "title": "Complete, vlotte laptop",
      "rating": 5,
      "publishedAt": "2024-10-30"
    }
  ],
  "scrapedAt": "2026-07-30T00:00:00.000Z"
}
```

Values can change between runs because bol.com is a live marketplace.

### How much does it cost to scrape bol.com products?

The Actor uses pay-per-event pricing:

- a one-time **Actor start** event currently costs **$0.00525** per run;
- each unique **Product scraped** event uses tiered pricing; the current BRONZE price is **$0.020225 per product**;
- details, offer arrays, and review samples have no separate event charge.

At the current BRONZE rates, 1 product costs about **$0.0255**, 10 products about **$0.2075**, and 100 products about **$2.0278**. Higher subscription tiers receive the lower item prices shown by Apify before a run starts. Platform usage and proxy economics are incorporated into the Actor pricing workflow; always use the current Console estimate as the authoritative rate.

### Schedule price and offer monitoring

Apify schedules can run the same Task hourly, daily, or weekly. Keep a stable input and compare records by `productId` between datasets.

A typical workflow is:

1. Create a Task with known URLs or a focused query.
2. Schedule it at an interval suitable for the business decision.
3. Send the completed-run dataset to a warehouse or automation platform.
4. Compare `price`, `availability`, `seller`, `rating`, and `reviewCount` with the prior snapshot.
5. Alert only on meaningful changes in the downstream system.

The Actor returns snapshots; it does not itself store price history or send alerts.

### Use the Apify API

Replace `APIFY_TOKEN` with a token that can run the Actor.

#### cURL

```bash
curl -X POST \
  "https://api.apify.com/v2/acts/automation-lab~bol-com-scraper/runs?token=APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"queries":["laptop"],"marketplace":"NL","maxItems":5,"includeDetails":true}'
```

#### JavaScript

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

const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('automation-lab/bol-com-scraper').call({
  queries: ['laptop'],
  marketplace: 'NL',
  maxItems: 5,
  includeDetails: true,
  maxReviews: 3,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items);
```

#### Python

```python
from apify_client import ApifyClient

client = ApifyClient(token="APIFY_TOKEN")
run = client.actor("automation-lab/bol-com-scraper").call(run_input={
    "queries": ["koffiezetapparaat"],
    "marketplace": "BE",
    "maxItems": 5,
    "includeDetails": True,
    "maxReviews": 2,
})
items = client.dataset(run["defaultDatasetId"]).list_items().items
print(items)
```

### Connect through MCP

Add the Actor to Claude Code:

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

**Claude Desktop setup**, **Cursor setup**, and **VS Code setup** can use the same remote MCP server configuration:

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

Example prompts:

- “Search bol.com NL for five laptops and compare price, rating, and stock.”
- “Extract this bol.com product URL and summarize its offer and public review samples.”
- “Run the Belgium coffee-machine Task and return a table sorted by rating.”

### Integrations and exports

The default dataset works with Apify webhooks, Google Sheets, Make, Zapier, Airbyte, Keboola, and custom API consumers. Export it as JSON for nested `offers` and `reviews`; CSV and Excel serialize nested arrays and may require downstream expansion.

Use `productId` as the primary comparison key. EAN can be missing or can differ between product variants, so it should not be the only deduplication key.

### Limits and failure behavior

- bol.com can change its anti-bot behavior, markup, or structured data without notice.
- The Actor uses Netherlands or Belgium residential traffic and does not expose an unmeasured datacenter fallback.
- A blocked session is rotated up to three times. Exhaustion fails the run instead of returning a misleading empty success.
- Public product structured data exposes up to six review samples, not necessarily every review.
- `offers` contains offers that bol.com exposes in product structured data. It is not a guarantee of every seller visible through every interactive account or checkout surface.
- Search ranking, sponsored placement, prices, seller, availability, and review totals can change at any time.
- Search pagination stops when no new stable product IDs are found or the requested limit is reached.
- The maximum input limit is 500 products per run; use focused Tasks for repeat monitoring.

### Responsible use and legality

This Actor processes public product and review information. Use it only for lawful purposes and follow bol.com's terms, applicable database rights, copyright rules, and data-protection law.

Reviews can contain public display names and user-written text. Collect only what your use case needs, secure exported datasets, and do not use review data to identify, profile, harass, or contact individuals. The Actor intentionally excludes accounts, orders, checkout, buyer profiles, and personal contact enrichment.

### Troubleshooting

**The run failed after residential session rotations.**

Retry later with a smaller focused input. Persistent failures usually indicate a changed challenge or page shape; inspect the run log before scheduling another paid run.

**A field is null.**

The source did not expose that field for the selected product or search card. Enable `includeDetails` for EAN, full descriptions, structured offers, and review samples.

**I received fewer products than `maxItems`.**

`maxItems` is a ceiling, not a promised count. Results can be deduplicated, a source can be exhausted, or a search can return fewer unique products.

**Why are there only six reviews?**

The current public product structured data exposes a bounded sample. `reviewCount` still reports the aggregate total when available.

### Related Automation Lab Actors

- [Amazon Product Scraper](https://apify.com/automation-lab/amazon-scraper) for product, offer, rating, and marketplace research on Amazon.
- [eBay Product Scraper](https://apify.com/automation-lab/ebay-scraper) for active eBay listings, seller details, auctions, and Buy It Now data.

Choose a source-specific Actor when the monitored catalog is on that marketplace; keep datasets separate and normalize them downstream when comparing multiple sources.

### FAQ

**Does this Actor require my bol.com account?**\
No. It accesses public product and search surfaces without login.

**Can it search both the Netherlands and Belgium?**\
Yes. Set `marketplace` to `NL` or `BE`. Direct URLs follow their own marketplace path.

**Does it download product images?**\
No. It returns public image URLs while blocking image binaries during extraction.

**Does it track changes automatically?**\
It produces current snapshots. Use an Apify Task schedule and compare datasets in your preferred storage or automation tool.

**Are offer and review arrays separately charged?**\
No. They are included in the single Product scraped event when `includeDetails` is enabled.

# Actor input Schema

## `queries` (type: `array`):

Product searches to run on bol.com, such as laptop, koffiezetapparaat, or LEGO Technic.

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

Optional bol.com product or search URLs. Product URLs are extracted directly; search URLs return their product results.

## `marketplace` (type: `string`):

Marketplace and residential proxy country used for query searches.

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

Maximum number of unique product records saved across all queries and URLs.

## `includeDetails` (type: `boolean`):

Open each product page to add EAN, description, seller offers exposed by bol.com, aggregate ratings, and up to six public review samples.

## `maxReviews` (type: `integer`):

Maximum public review samples saved per product. bol.com product structured data exposes up to six.

## Actor input object example

```json
{
  "queries": [
    "laptop"
  ],
  "startUrls": [],
  "marketplace": "NL",
  "maxItems": 20,
  "includeDetails": true,
  "maxReviews": 6
}
```

# Actor output Schema

## `dataset` (type: `string`):

Default dataset containing all scraped product records.

# 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 = {
    "queries": [
        "laptop"
    ],
    "startUrls": [],
    "marketplace": "NL",
    "maxItems": 20,
    "includeDetails": true,
    "maxReviews": 6
};

// Run the Actor and wait for it to finish
const run = await client.actor("automation-lab/bol-com-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 = {
    "queries": ["laptop"],
    "startUrls": [],
    "marketplace": "NL",
    "maxItems": 20,
    "includeDetails": True,
    "maxReviews": 6,
}

# Run the Actor and wait for it to finish
run = client.actor("automation-lab/bol-com-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 '{
  "queries": [
    "laptop"
  ],
  "startUrls": [],
  "marketplace": "NL",
  "maxItems": 20,
  "includeDetails": true,
  "maxReviews": 6
}' |
apify call automation-lab/bol-com-scraper --silent --output-dataset

```

## MCP server setup

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

```

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/acts/xn82Z4Lt2lPwHp9rq/builds/09zTQgfxho4FVcwPu/openapi.json
