# PLUS Scraper (`sleepmodesystems/plus`) Actor

PLUS supermarket product API alternative: all ~17,300 plus.nl products with prices, unit prices, deals with dates, EAN barcodes on every product and, on request, Nutri-Score and vegan labels, in about 3 minutes, no proxy. Every run checks its count against PLUS's own total.

- **URL**: https://apify.com/sleepmodesystems/plus.md
- **Developed by:** [Sleep Mode Systems](https://apify.com/sleepmodesystems) (community)
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.50 / 1,000 products

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

PLUS Scraper extracts products from PLUS supermarket (https://www.plus.nl): prices, unit prices, deals (aanbiedingen) with their dates, **an EAN barcode on every product**, organic flag, categories and stock status, and on request Nutri-Score, vegan, vegetarian and deposit labels. It is the only PLUS actor that reads the full catalog, and every run checks itself: it compares the products it read with PLUS's own total and reports the result as `coverage`, which was 1 (17,326 of 17,326) in the last full run.

**Price: $1.50 per 1,000 products, plus $1.00 per 1,000 for product details. A full run reads all 17,326 products in about 3 minutes on Apify, with no proxy.**

### What does the PLUS Scraper extract?

| Data            | Fields                                                                    | Filled in last full run                                                                     |
| --------------- | ------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------- |
| Identity        | `externalId`, `name`, `brand`, `ean`, `gtins`                             | 100%: every product has its barcode                                                         |
| Size            | `sizeText`, `packCount`, `quantity`, `unit`                               | 99.5%                                                                                       |
| Price           | `price`, `currency`, `unitPrice`, `unitPriceUnit`                         | 100% price, 99.5% unit price                                                                |
| Deals           | `promoPrice`, `promoText`, `promoType`, `promoStart`, `promoEnd`          | 1,587 products on a deal (9.2%), all with dates                                             |
| Product facts   | `organic`, `badges`, `storeOnly`                                          | 100% organic flag (1,030 organic), 240 store-only                                           |
| With details    | `nutriScore`, `vegan`, `vegetarian`, `deposit`, quality logos in `badges` | with `withDetails`: Nutri-Score 28.5% (4,931), vegan 2,875, vegetarian 4,517, deposit 1,048 |
| Category        | `categoryPath`, `category`                                                | 100%                                                                                        |
| Links and stock | `url`, `imageUrl`, `inStock`                                              | 100% url and stock flag, 99.4% image                                                        |

Last full run: 2026-11-04, 17,326 products, 1,524 requests, all HTTP 200.

### Who uses the PLUS Scraper?

- **Price comparison sites** load the full catalog and match it to Albert Heijn, Jumbo and Dirk on `ean`, which every PLUS product has.
- **Deal and folder apps** read this week's PLUS aanbiedingen with `promoStart`, `promoEnd` and the deal text.
- **Brand and category managers** follow their own and competing products' price and deals at PLUS per week.
- **Retail and market analysts** track PLUS's prices, its own brand (3,710 PLUS products) and deal share across 31 top-level categories.
- **Nutrition and food apps** use `nutriScore`, `vegan`, `vegetarian` and `organic` with `withDetails`.
- **Developers** who need a PLUS supermarket product API without maintaining one call this actor from JavaScript, Python or REST.

### How much does the PLUS Scraper cost?

Pay per event. You pay for products written to the dataset, for product details when you ask for them (from the details file or read live, the same price), and a tiny start fee. Platform usage is included.

| Event                           | Price                                  |
| ------------------------------- | -------------------------------------- |
| Product written to dataset      | $0.0015                                |
| Product details (`withDetails`) | $0.001 per product                     |
| Actor start                     | $0.00005 per run at the default 512 MB |

#### PLUS Scraper cost examples

| Scenario                                       | Products | Cost    |
| ---------------------------------------------- | -------- | ------- |
| Small test, `maxItems: 100`                    | 100      | $0.15   |
| Keyword search, `keywords: ["halfvolle melk"]` | 57       | $0.09   |
| Same search with `withDetails`                 | 57       | $0.14   |
| This week's deals, `onlyBonus: true`           | 1,587    | $2.38   |
| Full catalog                                   | 17,326   | $25.99  |
| Full catalog with details                      | 17,326   | $43.32  |
| Full catalog every week, 4 runs a month        | 69,304   | $103.96 |

Product counts are from runs on 2026-11-04. Set `maxItems` to cap any run. Set the run's maximum charge in Apify to cap spend; the actor stops cleanly when it is reached and reports how many products it got.

### How do you configure the PLUS Scraper?

| Field          | Type             | Default | Meaning                                                                                                            |
| -------------- | ---------------- | ------- | ------------------------------------------------------------------------------------------------------------------ |
| `keywords`     | array of strings | empty   | Search for these words instead of reading the full catalog.                                                        |
| `eans`         | array of strings | empty   | Look up these barcodes instead of reading the full catalog.                                                        |
| `onlyBonus`    | boolean          | `false` | Keep only products on a deal, in any mode.                                                                         |
| `withDetails`  | boolean          | `false` | Add each product's details: Nutri-Score, vegan, vegetarian, deposit, quality logos, from the actor's details file. |
| `freshDetails` | boolean          | `false` | With `withDetails`: read every product's details live from PLUS, with in-store availability.                       |
| `maxItems`     | integer          | 100000  | Stop after this many products. The default covers the full catalog.                                                |
| `minItems`     | integer          | 1       | Fail the run if fewer products were found.                                                                         |

With `keywords` and `eans` empty, the actor reads the full catalog.

### How do you scrape the full PLUS supermarket catalog with the PLUS Scraper?

Use it for a complete list of PLUS products with prices and barcodes. Leave the input empty. The actor reads PLUS's whole product list, compares the count with PLUS's own total, and reads the list once more if it came up short.

```json
{}
```

### How do you get the PLUS aanbiedingen of this week with the PLUS Scraper?

`onlyBonus` keeps products on a deal and works with every mode. Free-delivery offers do not count. On the full catalog it reads all products and stores those on a deal: 1,587 in the last run, 1,287 of them running Wednesday 4 to Tuesday 10 November.

```json
{
    "onlyBonus": true
}
```

### How do you search PLUS by keyword with the PLUS Scraper?

Use it when you need a product group. One PLUS search runs per keyword, with all result pages: `halfvolle melk` returned 57 products.

```json
{
    "keywords": ["halfvolle melk", "pindakaas"]
}
```

### How do you look up PLUS products by EAN barcode with the PLUS Scraper?

PLUS's own search does not find barcodes. The actor knows the barcode of every PLUS product from a file it carries, finds the products, and reads the list for their current price and deal: about 3 minutes on Apify, however many barcodes. Leading zeros are optional. A barcode the file does not know is looked for among products new since; one not found is not on sale, and has `expected: 0` in the run summary.

```json
{
    "eans": ["8413498121102", "8718182066272"]
}
```

### How do you get Nutri-Score and vegan labels with the PLUS Scraper?

Set `withDetails`. Every product then carries its details: Nutri-Score, organic, vegan and vegetarian logos, deposit (statiegeld) and quality marks such as Beter Leven or MSC. PLUS gives details only one product at a time, so the actor ships with a details file read in one full run (`detailsDate`, 2026-11-05 for the current file: 17,345 of 17,345 products) and reads live only the products the file does not know. A full run with details then takes about 2 minutes (125 seconds and 1,562 requests locally, 32 products read live), instead of about 28 minutes. On a search of 916 products, the details from the file and read live were identical for every product.

Set `freshDetails` as well to read every product's details from PLUS now, including in-store availability: one request per product, a few seconds on a search, about 28 minutes on the full catalog.

```json
{
    "keywords": ["yoghurt"],
    "withDetails": true
}
```

### Which fields does the PLUS Scraper output?

Source: **PLUS** = PLUS's value unchanged. **Derived** = computed by this actor. **Fixed** = same in every item. **File** = the barcode file the actor carries. **Input** = from your input. Missing values are `null`, never an empty string.

| Field               | Source  | Meaning                                                                                                  |
| ------------------- | ------- | -------------------------------------------------------------------------------------------------------- |
| `chain`             | Fixed   | Always `plus`.                                                                                           |
| `store`             | Fixed   | Always `null`: plus.nl's prices with no store chosen.                                                    |
| `externalId`        | PLUS    | PLUS product id, such as `454439`.                                                                       |
| `ean`               | File    | Barcode, mostly EAN-13.                                                                                  |
| `gtins`             | Derived | The barcode in a list, for the same field on other chains.                                               |
| `name`              | PLUS    | Product name.                                                                                            |
| `brand`             | PLUS    | Brand.                                                                                                   |
| `sizeText`          | PLUS    | Size as PLUS writes it, such as `Per 750 ml` or `Per 30 st`.                                             |
| `packCount`         | Derived | Units in a multipack; 1 when not a multipack.                                                            |
| `quantity`          | Derived | Size of one unit: `Per 750 ml` gives 750.                                                                |
| `unit`              | Derived | Unit of `quantity`: `g`, `kg`, `ml`, `cl`, `l`, `stuk` or `m`.                                           |
| `price`             | PLUS    | Regular price in EUR.                                                                                    |
| `currency`          | Fixed   | Always `EUR`.                                                                                            |
| `unitPrice`         | Derived | Regular price per kg, litre, piece or metre, equal to PLUS's own on 99.6% of products.                   |
| `unitPriceUnit`     | Derived | Unit of `unitPrice`: `kg`, `l`, `stuk` or `m`.                                                           |
| `promoPrice`        | PLUS    | Deal price in EUR, rounded to the cent, when lower than `price`.                                         |
| `promoText`         | PLUS    | The deal as shown, such as `30 % KORTING`, `1+1 GRATIS` or `2 VOOR 2.99`.                                |
| `promoType`         | PLUS    | PLUS's second label, such as `OP=OP`.                                                                    |
| `promoLabels`       | Fixed   | Always `null` on PLUS; kept for the same field on other chains.                                          |
| `promoStart`        | PLUS    | First day of the deal, `YYYY-MM-DD`.                                                                     |
| `promoEnd`          | PLUS    | Last day of the deal, `YYYY-MM-DD`.                                                                      |
| `organic`           | Derived | `true` when in PLUS's organic filter, named organic, or with an organic logo in the details.             |
| `nutriScore`        | PLUS    | Nutri-Score `A` to `E`, with `withDetails`.                                                              |
| `badges`            | PLUS    | PLUS's logos, such as `Laagblijver`; with `withDetails` also `VEGAN`, `Beter Leven 1 Ster`, `MSC Label`. |
| `vegan`             | Derived | Vegan logo (with `withDetails`) or vegan in the name.                                                    |
| `vegetarian`        | Derived | Vegetarian logo (with `withDetails`), vegan, or vegetarisch in the name.                                 |
| `deposit`           | PLUS    | Deposit (statiegeld) logo, with `withDetails`; otherwise `null`.                                         |
| `storeOnly`         | PLUS    | `true` when sold in PLUS shops only, not online.                                                         |
| `categoryPath`      | PLUS    | Category path, such as `Zuivel, eieren, boter/Melk/Houdbare melk`.                                       |
| `categoryIds`       | Fixed   | Always `null`: PLUS gives no category ids.                                                               |
| `category`          | PLUS    | Top-level category.                                                                                      |
| `url`               | Derived | Product page on plus.nl.                                                                                 |
| `imageUrl`          | PLUS    | Product image.                                                                                           |
| `inStock`           | PLUS    | `true` when the product can be ordered online.                                                           |
| `availabilityLabel` | Fixed   | Always `null` on PLUS.                                                                                   |
| `detailsRead`       | Derived | `true` when the product's details are in the item, from the details file or read live (`withDetails`).   |
| `detailsDate`       | Derived | Date the details were read: the details file's date, or the run's date when read live.                   |
| `searchTerm`        | Input   | The keyword or barcode that found the product; `null` in full-catalog mode.                              |
| `scrapedAt`         | Fixed   | Time the product was read, ISO 8601.                                                                     |

#### PLUS Scraper output example

With `withDetails`:

```json
{
    "chain": "plus",
    "store": null,
    "externalId": "762827",
    "ean": "8718989755867",
    "gtins": ["8718989755867"],
    "name": "PLUS Cashewnoten Extra Groot  (ongz)",
    "brand": "PLUS",
    "sizeText": "Per 170 g",
    "packCount": 1,
    "quantity": 170,
    "unit": "g",
    "price": 3.99,
    "currency": "EUR",
    "unitPrice": 23.47,
    "unitPriceUnit": "kg",
    "promoPrice": null,
    "promoText": "2E HALVE PRIJS",
    "promoType": null,
    "promoLabels": null,
    "promoStart": "2026-11-04",
    "promoEnd": "2026-11-10",
    "organic": false,
    "nutriScore": "B",
    "badges": ["Nutri-Score B", "VEGAN", "VEGETARIAN"],
    "vegan": true,
    "vegetarian": true,
    "deposit": false,
    "storeOnly": false,
    "categoryPath": "Borrel, chips, noten, snacks/Noten/Ongezouten noten gebrand",
    "categoryIds": null,
    "category": "Borrel, chips, noten, snacks",
    "url": "https://www.plus.nl/product/plus-cashewnoten-extra-groot-ongz-bakje-170-g-762827",
    "imageUrl": "https://images.ctfassets.net/s0lodsnpsezb/762827_M/fcb08d2fc462caa7c915b4b55baf1bce/762827.png",
    "inStock": true,
    "availabilityLabel": null,
    "detailsRead": true,
    "detailsDate": "2026-11-04",
    "searchTerm": null,
    "scrapedAt": "2026-11-04T19:35:29.450Z"
}
```

### How does the PLUS Scraper report on its run?

Every run saves a `SUMMARY` record in its key-value store. From the last full run:

```json
{
    "mode": "catalog",
    "itemsPushed": 17326,
    "distinctIds": 17326,
    "productsRead": 17326,
    "expectedTotal": 17326,
    "coverage": 1,
    "organicCount": 930,
    "barcodesFromFile": 17326,
    "barcodesFetched": 0,
    "barcodesMissing": 0,
    "detailsRead": 0,
    "detailsFromFile": 0,
    "detailsFileDate": null,
    "stoppedAtChargeLimit": false,
    "blocked": false,
    "concurrencyReduced": false,
    "versionsRefreshed": 0,
    "durationSec": 129,
    "requests": 1524,
    "secondPassRequests": 0,
    "statusCodes": { "200": 1524 },
    "errors": [],
    "retries": [],
    "searches": []
}
```

| Field                                | Meaning                                                                                                     |
| ------------------------------------ | ----------------------------------------------------------------------------------------------------------- |
| `itemsPushed`, `distinctIds`         | Products stored. Only products Apify accepted count.                                                        |
| `productsRead`                       | Distinct products read from PLUS, including those left out by `onlyBonus`, `maxItems` or your charge limit. |
| `expectedTotal`, `coverage`          | PLUS's own product count, and `productsRead / expectedTotal`. `null` in search mode.                        |
| `organicCount`                       | Products in PLUS's organic filter.                                                                          |
| `barcodesFromFile`                   | Barcodes taken from the file the actor carries.                                                             |
| `barcodesFetched`                    | Barcodes read from PLUS in this run, for products new since the file was written.                           |
| `barcodesMissing`                    | Products without a barcode.                                                                                 |
| `detailsRead`                        | Products whose details were read live in this run.                                                          |
| `detailsFromFile`, `detailsFileDate` | Products whose details came from the actor's details file, and the file's date.                             |
| `searches`                           | In search mode, PLUS's count and the collected count per keyword or barcode.                                |
| `stoppedAtChargeLimit`               | `true` when the run stopped at your maximum charge.                                                         |
| `blocked`                            | `true` when PLUS refused twice in a row (HTTP 403); the run then fails with the products it already had.    |
| `concurrencyReduced`                 | `true` when PLUS answered 403 or 429; the actor then sends fewer requests at a time.                        |
| `versionsRefreshed`                  | Times the actor re-read PLUS's site version, because PLUS released during the run.                          |
| `statusCodes`, `retries`, `errors`   | Every HTTP status received, every retry with its reason, and requests that failed after 3 retries.          |

A full-catalog run is suspect when `coverage` is below 1 while `stoppedAtChargeLimit` is `false`, when `barcodesMissing` is above 0, when `blocked` or `concurrencyReduced` is `true`, or when `statusCodes` holds anything other than 200. Set `minItems` to make a bad run fail outright.

### How does the PLUS Scraper compare to other PLUS scrapers?

|                                         | PLUS Scraper         | studio-amba/plus-nl-scraper            | harvestedge/dutch-supermarkets-all-11 |
| --------------------------------------- | -------------------- | -------------------------------------- | ------------------------------------- |
| Price per 1,000                         | $1.50, details $1.00 | from $1.20 on top plans, $2.00 on free | $5.00                                 |
| Full catalog                            | yes, default         | no, one keyword per run                | no, keyword search                    |
| EAN barcode                             | yes, every product   | yes, can be empty                      | no                                    |
| Barcode lookup                          | yes, `eans`          | no                                     | no                                    |
| Deal dates                              | yes                  | no                                     | no                                    |
| Nutri-Score, vegan, deposit             | yes, `withDetails`   | no                                     | no                                    |
| Organic flag                            | yes                  | no                                     | no                                    |
| Completeness check against PLUS's count | yes, every run       | no                                     | no                                    |
| Proxy                                   | none needed          | NL residential by default              | not stated                            |

Figures read from each actor's public page on 2026-11-04.

### Things to know about PLUS data from the PLUS Scraper

- **PLUS's list holds no barcodes, and its search does not find them.** Only each product's details do, one product per request. So the actor carries a barcode file: 17,425 products, which covered all 17,326 products listed on 4 November. A product new since then gets its barcode from its details during the run.
- **Barcodes can change.** In the run of 4 November, 7 of 17,326 products had a new barcode since the file was written on 31 October (Oatly Haver cuisine bio, four Derlon products). With `withDetails` the barcode read in the run wins; the file is updated with each release of the actor.
- **Webshop prices are advice prices.** PLUS says the price at the till can differ, because of local price differences.
- **PLUS's deal week runs Wednesday to Tuesday.** In the run of Wednesday 4 November, 1,287 of 1,587 deals ran 4 to 10 November.
- **Multi-buy deals usually have no deal price.** `2 VOOR 2.99` or `1+1 GRATIS` leave the single price unchanged; the deal is in `promoText`.
- **Some deals carry no label.** 611 deals have dates and often a deal price, but no text from PLUS, such as Royal Club Lemon soda at 2.00 instead of 4.69.
- **Deal prices are rounded to the cent.** PLUS sometimes sends unrounded ones, such as 1.183.
- **Free-delivery offers are left out.** PLUS marks them, and they appear in no deal field and not with `onlyBonus`.
- **`unitPrice` matches PLUS's own.** Computed from the regular price and size, it equalled PLUS's unit price on 12,292 of 12,345 products compared and was within 2 cents on the rest. Small packs have real but high unit prices, such as €1,081.67 per litre for 6 ml of eye drops.
- **Vegan and vegetarian come from PLUS's logos and the product name.** 12 products named vegan and 17 named vegetarian, such as `Hands off Vegan Seriously Dark` and `Vegetarische Slager` products, have no logo at PLUS; a vegan product is vegetarian too, though 1,168 lack PLUS's vegetarian logo. Without `withDetails`, only the name counts, and the fields are otherwise `null`.
- **Organic is PLUS's organic filter plus names.** 930 products are in the filter; 100 more are named bio, biologisch or organic. With `withDetails`, PLUS's `EU Organic Farming` logo counts too.
- **Prices are those with no store chosen.** A chosen store shows its own range (10,795 products in store 747), with the same prices in the sample checked.
- **Details come from a file, dated.** With `withDetails`, logos come from the details file the actor ships with (`detailsDate`), and products the file does not know are read live. In-store availability is not kept in the file: `inStock` then comes from the product list, as without details. `freshDetails` reads every detail live, with availability.
- **PLUS gives no category ids**, so `categoryIds` is `null`. Seasonal categories such as `Kerst` and `Sinterklaas` appear in their season.

### Is it legal to use the PLUS Scraper?

This actor reads publicly available data only. PLUS product data contains no personal data. It sends a limited number of requests at a time, respects plus.nl's robots.txt, and does not bypass any login or paywall. You are responsible for how you use the data, including any terms that apply to you. See Apify's [guide to web scraping legality](https://blog.apify.com/is-web-scraping-legal/).

### Frequently asked questions about the PLUS Scraper

#### Can I get PLUS products as CSV or Excel?

Yes. Every run's dataset downloads as CSV, Excel, JSON or XML from Apify, or through the API.

#### How often should I run it?

PLUS's deals change every Wednesday. Run the full catalog once a week on Wednesday for that week's prices and aanbiedingen.

#### Does it need proxies?

No. Requests go straight to PLUS: the last full run got HTTP 200 on all 1,524. If PLUS answers 403 or 429, the actor sends fewer requests at a time; after a 403 it also pauses 60 seconds and tries once more, and a second 403 ends the run with `blocked: true`.

#### Can I schedule it and send results somewhere?

Yes. Use Apify Schedules, and a webhook or integration to send each run's dataset to your database, Google Sheets, Slack or Notion.

#### Does it work with the Apify API and SDK?

Yes. Any Apify client (JavaScript, Python, REST) can start the actor and read the dataset.

#### Is there an official PLUS supermarket API?

No public one. PLUS's webshop runs on actions that are not documented for outside use. This actor reads them for you and returns a stable set of fields, so you do not maintain the integration.

#### Does every PLUS product have a barcode?

Yes, in the last full run all 17,326. PLUS's list has none, so the actor carries a barcode file and reads the details of products new since it was written.

#### Can I get vegan PLUS products?

Yes. Run with `withDetails` and filter on `vegan: true`. PLUS marks vegan products with a logo in their details, not in the list.

#### Can I compare PLUS prices with Albert Heijn, Jumbo and Dirk?

Yes. The Albert Heijn, Jumbo and Dirk scrapers by Sleep Mode Systems output the same fields. Match on `ean` (Albert Heijn writes it with a leading zero, so compare without leading zeros) and compare `unitPrice`.

#### Does it give prices per PLUS store?

No. It gives plus.nl's prices with no store chosen. PLUS says shop prices can differ locally.

#### Does it show next week's PLUS aanbiedingen?

No. PLUS lists a deal once it runs; next week's deals were not published on its site on the Wednesday checked.

### Other scrapers by Sleep Mode Systems

| Actor                                                                   | What it extracts                                                       | Price per 1,000 |              |
| ----------------------------------------------------------------------- | ---------------------------------------------------------------------- | --------------- | ------------ |
| PLUS Scraper                                                            | PLUS products: prices, deals with dates, EAN, Nutri-Score, vegan       | $1.50           | you are here |
| [Albert Heijn Scraper](https://apify.com/sleepmodesystems/albert-heijn) | Albert Heijn products: prices, Bonus deals, EAN, Nutri-Score           | $1.00           |              |
| [Jumbo Scraper](https://apify.com/sleepmodesystems/jumbo)               | Jumbo products: prices, deals with dates, EAN, organic, shelf life     | $1.50           |              |
| [Dirk Scraper](https://apify.com/sleepmodesystems/dirk)                 | Dirk products: prices, next week's deals, EAN, Nutri-Score             | $2.00           |              |
| [DekaMarkt Scraper](https://apify.com/sleepmodesystems/dekamarkt)       | DekaMarkt products: prices, next week's deals, EAN, organic            | $2.00           |              |
| [Hoogvliet Scraper](https://apify.com/sleepmodesystems/hoogvliet)       | Hoogvliet products: prices, next week's deals, EAN, ingredients, vegan | $2.00           |              |
| [Vomar Scraper](https://apify.com/sleepmodesystems/vomar)               | Vomar products: prices, every EAN barcode, BIO, categories             | $1.00           |              |
| [Poiesz Scraper](https://apify.com/sleepmodesystems/poiesz)             | Poiesz products: prices, deals with dates, EAN, deposit, ingredients   | $1.50           |              |
| [Ekoplaza Scraper](https://apify.com/sleepmodesystems/ekoplaza)         | Ekoplaza products: prices, next week's deals, EAN, allergens, Ekoscope | $2.00           |              |
| [Aldi NL Scraper](https://apify.com/sleepmodesystems/aldi)              | Aldi products: prices, next week's deals, special buys, seals          | $1.00           |              |

All of them share the same output fields, so you can combine their datasets directly. The Aldi NL Scraper adds `articleNumber`, `description`, `specialBuy`, `vegan`, `vegetarian`, `ageRestriction` and `priceDate`, and has no barcodes; the Ekoplaza Scraper adds `articleNumber`, `vegan`, `vegetarian`, `ekoscope`, `origin`, `shelfLifeDays`, `ageRestriction`, `soldByWeight`, `detailsDate`, `description`, `ingredients`, `allergens`, `mayContain`, `freeFrom`, `nutrition` and `priceDate`; the Poiesz Scraper adds `promoDescription`, `deposit`, `depositAmount`, `ageRestriction`, `alcoholPercentage`, `purchaseLimit`, `soldByWeight`, `detailsRead`, `detailsDate`, `ingredients`, `allergens`, `mayContain`, `freeFrom`, `nutrition` and `storage`; the Vomar Scraper adds `soldByWeight`, and fills `gtins` with every barcode Vomar lists; the Hoogvliet Scraper adds `promoDescription`, `vegan`, `vegetarian`, `shelfLifeDays`, `ageRestriction`, `soldByWeight`, `ingredients`, `nutrition`, `storage`, `origin`, `alcoholPercentage` and `priceDate`; the DekaMarkt and Dirk Scrapers add `soldByWeight` and `priceDate`; PLUS adds `vegan`, `vegetarian`, `deposit`, `storeOnly`, `detailsRead` and `detailsDate`; Jumbo adds `promotions` and `shelfLifeDays`. Category ids are text on Jumbo, Dirk, DekaMarkt, Hoogvliet, Vomar, Poiesz, Ekoplaza and Aldi, numbers on Albert Heijn, and not given by PLUS.

### Support for the PLUS Scraper

Questions, a missing field, or a custom pipeline on top of this data: write to Imad at imad@sleepmodesystems.com. Bugs go in the Issues tab of this actor.

# Actor input Schema

## `keywords` (type: `array`):

Search PLUS for these words instead of reading the full catalog. One search per keyword, all result pages. Leave empty for the full catalog.

## `eans` (type: `array`):

Look up these barcodes instead of reading the full catalog. Leading zeros are optional. Reads the full list to find their prices, about 3 minutes. Leave empty for the full catalog.

## `onlyBonus` (type: `boolean`):

Keep only products on a deal (aanbieding), in any mode. Free-delivery offers do not count.

## `withDetails` (type: `boolean`):

Add each product's details: Nutri-Score, organic, vegan and vegetarian logos, deposit and quality marks. They come from the details file shipped with the actor, read in one full run (date in detailsDate); products the file does not know, such as new ones, are read live.

## `freshDetails` (type: `boolean`):

With withDetails: ignore the details file and read every product's details from PLUS now, including in-store availability. One extra request per product: about 25 minutes more on the full catalog, a few seconds on a search.

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

Stop after this many distinct products. The full PLUS catalog is about 17,300 products.

## `minItems` (type: `integer`):

Fail the run if fewer products were found.

## Actor input object example

```json
{
  "keywords": [],
  "eans": [],
  "onlyBonus": false,
  "withDetails": false,
  "freshDetails": false,
  "maxItems": 100000,
  "minItems": 1
}
```

# Actor output Schema

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

No description

## `summary` (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 = {};

// Run the Actor and wait for it to finish
const run = await client.actor("sleepmodesystems/plus").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 = {}

# Run the Actor and wait for it to finish
run = client.actor("sleepmodesystems/plus").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 '{}' |
apify call sleepmodesystems/plus --silent --output-dataset

```

## MCP server setup

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

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/sVAeflNFyhC0HbGPm/builds/W4P0h7YI4IEgP4hVr/openapi.json
