# Bol.com Keyword & Niche Research (`matte_wingback/bol-niche-scout`) Actor

Find winnable niches on bol.com. Expands your seed keywords into real bol.com search suggestions and scores every keyword on demand vs. competition: result count, review velocity, review moat, sponsored density, share sold by bol itself, and price band.

- **URL**: https://apify.com/matte\_wingback/bol-niche-scout.md
- **Developed by:** [Rob](https://apify.com/matte_wingback) (community)
- **Categories:** E-commerce, SEO tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per usage

This Actor is paid per platform usage. The Actor is free to use, and you only pay for the Apify platform usage, which gets cheaper the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-usage

## 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 Keyword & Niche Research (bol-niche-scout)

**Identify winnable niches on bol.com before committing to a product.** Provide a few
seed keywords; the actor expands them into real bol.com search suggestions and scores
every keyword on demand versus competition — comparable to established keyword tools
for Etsy, applied to the largest marketplace of the Netherlands and Belgium. One run
produces one decision document.

Built for bol sellers (print-on-demand, private label, dropshipping) who need to decide
*which* product or keyword to pursue.

### What you get

One row per keyword, keyword column first, no arrays, no half-empty cells. Illustrative
example:

| keyword | opportunity\_score | result\_count | review\_velocity\_30d | review\_moat\_median\_top10 | bol\_self\_pct | sponsored\_density\_pct | price\_median |
|---|---|---|---|---|---|---|---|
| yogamat extra dik | 71 | 1 842 | 18 | 24 | 0 | 20 | 29.95 |
| bureau organizer bamboe | 63 | 957 | 9 | 41 | 0 | 10 | 24.99 |
| yogamat | 38 | 28 410 | 6 | 312 | 40 | 30 | 27.95 |

Use the **Opportunities** dataset view for the ranked shortlist, or **All columns
(ordered)** for the full export in a fixed, keyword-first column order (the raw CSV
export sorts columns alphabetically; the views preserve the intended order).

#### All output columns

- `keyword` — the search term (seeds plus expanded suggestions)
- `opportunity_score` (0–100) — higher means more demand signal and less competition
- `demand_score`, `competition_score` — the two components of the formula (see below)
- `result_count` — total number of products bol returns for this search
- `review_velocity_30d` — estimated reviews in the last 30 days across the analyzed
  top-N products (proxy for sales velocity)
- `review_velocity_source` — `exact` (newest-reviews API), `estimate` (dates from the
  reviews embedded in the product page; a lower bound) or `none`
- `review_moat_median_top10` — median review count of the top-10 results: how
  entrenched the incumbents are
- `bol_self_pct` — share of the top-10 sold by bol itself; competing directly with bol
  is rarely viable, so this weighs heavily
- `sponsored_density_pct` — share of the top-10 that is a sponsored listing
- `price_min` / `price_median` / `price_max` — price band of the analyzed top-N
- `avg_rating_top_n`, `fast_delivery_pct` — quality and delivery pressure in the top-N
- `suggest_rank` — position at which this keyword appeared in its parent's autocomplete
  (1 = top suggestion; 0 for your own seeds)
- `depth`, `parent_keyword` — position in the expansion tree
- `top1_title`, `top1_url`, `serp_url` — direct links for manual verification
- `domain`, `language`, `analyzed_top_n` — run parameters for reproducibility

### Input

```json
{
    "seeds": ["yogamat", "bureau organizer"],
    "domain": "NL",
    "language": "nl",
    "depth": 2,
    "maxKeywords": 40,
    "analyzeTopN": 5,
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": ["RESIDENTIAL"],
        "apifyProxyCountry": "NL"
    }
}
```

- `domain` (**required**): `NL` (bol.com Nederland) or `BE` (bol.com België)
- `language`: `nl` (default) or `fr`; French is only available for BE
- `depth`: number of suggestion levels to expand (seeds are depth 0)
- `maxKeywords`: hard cap on the number of analyzed keywords, seeds included
- `analyzeTopN`: products per keyword that receive review-velocity analysis

### How keyword expansion stays relevant

Bol's autocomplete pads short queries with popular but unrelated terms. The actor
counters this with two mechanisms, both enabled by default:

- **Strict suggestion filter** (`strictSuggestions`): bol's response reports how many
  characters of the query were actually matched; suggestions that do not match the full
  keyword (and do not contain it) are discarded.
- **A–Z prefix probing** (`prefixProbes`): every seed is additionally queried as
  "seed a" through "seed z" — a proven technique from Etsy keyword tools. This is the
  main source of long-tail variants such as "yogamat extra dik" or "yogamat antislip".

A small number of substring near-matches may remain (a seed like "mat" also surfaces
"matras"); their own SERP metrics make them easy to dismiss.

### How the opportunity score works

The formula is deliberately simple and fully documented:

```
demand_score      (0–50) = suggest points (0–20) + review-velocity points (0–30)
competition_score (0–50) = review moat (0–15) + result count (0–15)
                           + sold-by-bol (0–10) + sponsored density (0–10)
opportunity_score        = clamp(50 + demand_score − competition_score, 0, 100)
```

| Component | Weight | Calculation |
|---|---|---|
| Autocomplete presence | 0–20 | `20 − 2 × (suggest_rank − 1)`, minimum 2. Seeds score a neutral 10. |
| Review velocity | 0–30 | 1 point per review per 30 days, summed over the top-N products, capped at 30. |
| Review moat | 0–15 | `log10(median reviews top-10 + 1) × 5`; a median of 1 000 reviews reaches the cap. |
| Result count | 0–15 | `log10(result_count + 1) × 2.5`; one million results reaches the cap. |
| Sold by bol | 0–10 | Proportional to the share of the top-10 sold by bol itself. |
| Sponsored density | 0–10 | Proportional to the sponsored share of the top-10. |

As a rule of thumb: scores above 60 indicate real demand with beatable competition,
around 50 is neutral or unknown, and below 40 the ranking is entrenched, ad-saturated,
or dominated by bol itself.

### Proxy configuration

bol.com's bot protection blocks common datacenter IP ranges, so the actor defaults to
**Apify Proxy RESIDENTIAL with country NL** (suitable for both the NL and BE shop).
Measured cost: a 40-keyword run transfers roughly 25 MB of residential data, about
**$0.20 per run** (≈ $0.005–0.007 per keyword) with negligible compute. Datacenter
proxies are not supported in practice.

### Use as an AI-agent tool (MCP)

The actor works as a tool for AI agents through the [Apify MCP server](https://mcp.apify.com):
connect an MCP-capable client (Claude, Claude Code, Cursor, custom agents) to

```
https://mcp.apify.com?tools=<username>/bol-niche-scout
```

authenticating with your Apify account (OAuth) or an API token. The agent then calls the
actor with the same input as above and reads the scored keywords from the resulting
dataset. For Claude Code:

```bash
claude mcp add --transport http apify "https://mcp.apify.com?tools=<username>/bol-niche-scout"
```

**Recommended agent inputs** — agents prefer short calls, so trade breadth for speed:
`depth: 1`, `maxKeywords: 15`, `analyzeTopN: 3` finishes in roughly 1–2 minutes and is
usually enough to answer "is this niche worth a closer look?". A follow-up full run
(`depth: 2`, `maxKeywords: 40`, `analyzeTopN: 5`) can then deepen the shortlist.

### Reliability: built-in self-test

Running the actor with `{ "selfTest": true }` analyzes one fixed keyword and fails with
a non-zero exit code and a clear error message if any part of bol.com's page structure
has changed. Recommended setup: an Apify schedule that runs the self-test daily with a
failure notification, so breakage is detected before users encounter it.

### Fair use & disclaimer

- Not affiliated with bol.com. "bol" and "bol.com" are trademarks of bol.com b.v.
- Only publicly visible data is used: search suggestions, search result pages and
  product pages. No login, no buyer accounts, and no personal data of reviewers — only
  review counts and dates.
- The actor operates at a deliberate, human-like pace and caches within the run (no
  page is fetched twice). Keep `maxKeywords` reasonable.
- Review velocity is a proxy for sales velocity, not a sales report. Only a small share
  of buyers leaves a review; interpret it as a relative signal between keywords.

***

## Bol.com keyword research & niche-onderzoek (Nederlands)

**De eerste keyword- en niche-researchtool voor bol.com.** Voor wie zoekt op *bol.com
keyword research*, *bol niche vinden* of *welk product verkopen op bol*: deze actor
beantwoordt die vraag met actuele bol-data in plaats van onderbuikgevoel. Een
vergelijkbaar hulpmiddel zoals eRank voor Etsy bestond tot nu toe niet voor bol.com.

### Wat doet de tool?

1. **Zoeksuggesties uitbreiden** — de opgegeven seed-keywords worden recursief
   uitgebreid via de autocomplete van bol.com, aangevuld met A–Z-prefix-probing voor
   long-tail-varianten. Wat bol suggereert, wordt daadwerkelijk gezocht: dat vormt het
   vraagsignaal.
2. **Concurrentie meten per keyword** — aantal zoekresultaten, mediaan aantal reviews
   in de top-10 (de toetredingsdrempel), het aandeel topposities dat bol zelf bezet
   (direct concurreren met bol is zelden haalbaar en weegt daarom zwaar mee),
   advertentiedruk en de prijsband.
3. **Verkoopsnelheid schatten** — review-velocity: het aantal nieuwe reviews van de
   topproducten in de afgelopen 30 dagen, als indicator voor omzetsnelheid.
4. **Opportunity-score (0–100)** — hoge vraag, lage toetredingsdrempel, beperkte
   aanwezigheid van bol zelf en weinig advertenties leveren een hoge score op. De
   volledige weging staat hierboven gedocumenteerd.

### Voor wie?

Bol-sellers (print-on-demand, private label, dropshipping) die onderbouwd willen
beslissen welk product of keyword zij gaan voeren. Eén run levert een gesorteerd
overzicht: welke niches bieden ruimte, welke zijn verzadigd.

### Voorbeeld

De seeds `["yogamat", "bureau organizer"]` op bol.com (NL) leveren binnen enkele
minuten 40 gescoorde keywords op, gesorteerd op kans. Bovenaan verschijnen long-tail-
keywords zoals "yogamat extra dik" of "bureau organizer bamboe" met aantoonbare vraag
en een lage toetredingsdrempel; onderaan de verzadigde hoofdkeywords.

### Disclaimer

Niet geaffilieerd met bol.com. De tool gebruikt uitsluitend publieke data
(zoeksuggesties, zoekresultaten, productpagina's), zonder login en zonder
persoonsgegevens van reviewers — alleen aantallen en datums. De tool werkt in een
beheerst, menselijk tempo.

# Actor input Schema

## `seeds` (type: `array`):

Starting keywords to expand via bol.com autocomplete, e.g. "yogamat" or "bureau organizer".

## `domain` (type: `string`):

Which bol shop to analyze. Results, prices and suggestions differ per country.

## `language` (type: `string`):

Search language. French is only available for bol.com (België).

## `depth` (type: `integer`):

How many suggestion levels to expand. Depth 1 = suggestions for your seeds; depth 2 = also suggestions for those suggestions.

## `maxKeywords` (type: `integer`):

Hard cap on the number of keywords analyzed (seeds included).

## `analyzeTopN` (type: `integer`):

How many top-ranking products per keyword get review-velocity analysis (more = better signal, slower run).

## `strictSuggestions` (type: `boolean`):

Only keep autocomplete suggestions that actually match your keyword. Bol pads short queries with popular but unrelated terms ("mok" → "mobiele airco"); this filters those out.

## `prefixProbes` (type: `boolean`):

Also query "seed a" … "seed z" per seed to surface long-tail suggestions (like the well-known Etsy keyword tools). Highly recommended for short seeds.

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

Use Apify Proxy RESIDENTIAL with country NL — bol.com blocks datacenter IP ranges. Costs ~$0.25 in proxy data per 40-keyword run.

## `selfTest` (type: `boolean`):

Internal health check: analyzes one fixed keyword and fails loudly if bol.com's page structure changed. Not shown in the form; pass it via the API or a schedule input.

## Actor input object example

```json
{
  "seeds": [
    "yogamat",
    "bureau organizer"
  ],
  "domain": "NL",
  "language": "nl",
  "depth": 2,
  "maxKeywords": 15,
  "analyzeTopN": 3,
  "strictSuggestions": true,
  "prefixProbes": true,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "NL"
  },
  "selfTest": false
}
```

# Actor output Schema

## `opportunities` (type: `string`):

The ranked shortlist: keyword, scores and the core demand/competition signals.

## `allColumns` (type: `string`):

Every output column in a fixed, keyword-first order.

## `costSummary` (type: `string`):

Requests and cost bookkeeping for this run (key-value store record COST\_SUMMARY).

# 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 = {
    "seeds": [
        "yogamat",
        "bureau organizer"
    ],
    "domain": "NL",
    "maxKeywords": 15,
    "analyzeTopN": 3,
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ],
        "apifyProxyCountry": "NL"
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("matte_wingback/bol-niche-scout").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 = {
    "seeds": [
        "yogamat",
        "bureau organizer",
    ],
    "domain": "NL",
    "maxKeywords": 15,
    "analyzeTopN": 3,
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
        "apifyProxyCountry": "NL",
    },
}

# Run the Actor and wait for it to finish
run = client.actor("matte_wingback/bol-niche-scout").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 '{
  "seeds": [
    "yogamat",
    "bureau organizer"
  ],
  "domain": "NL",
  "maxKeywords": 15,
  "analyzeTopN": 3,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "NL"
  }
}' |
apify call matte_wingback/bol-niche-scout --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,matte_wingback/bol-niche-scout"
        }
    }
}

```

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/Pa7LBRXMMAOt9nwuy/builds/HG8RuMgYiFiDFyn66/openapi.json
