# Kaufland Scraper - Products, Prices, EAN & Images, 7 Countries (`s-r/kaufland-scraper`) Actor

Kaufland scraper for product prices, EANs and images in seven supported marketplaces. Enter product ids or URLs, then export JSON, CSV or Excel for price monitoring, catalogue checks and cross-border comparison.

- **URL**: https://apify.com/s-r/kaufland-scraper.md
- **Developed by:** [SR](https://apify.com/s-r) (community)
- **Categories:** E-commerce, Automation
- **Stats:** 2 total users, 2 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.10 / 1,000 product rows

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

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

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

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

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

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

# README

## Kaufland Scraper: Products, Prices and EANs Across 7 Countries

The **Kaufland scraper** turns product ids or URLs into rows of prices, EANs
and images for price monitoring, catalogue checks and comparison across seven
supported Kaufland marketplaces. Choose a country, paste your products and
export the results from Apify as JSON, CSV or Excel. No Kaufland seller account
or seller API credentials are required. You can also start and schedule runs
through the Apify API using your Apify account credentials.

Each distinct valid product id produces one dataset row. Product ids and full
product URLs can be mixed in the same input list, and duplicates are removed.
Every row identifies its marketplace and distinguishes a product that was read
from a missing product or a lookup that could not be completed.

### What the Kaufland scraper returns

Read the product title, numeric price, original price text, currency, EAN and
main image URL from a public product page. Use `ean` to match a Kaufland
product to your own catalogue, `price` for calculations and `price_text` to
preserve the local display format. Identifiers stay strings so leading zeros
in barcodes survive exports and imports.

The supported markets are Germany (`de`), Austria (`at`), the Netherlands
(`nl`), Italy (`it`), Poland (`pl`), Czechia (`cz`) and Slovakia (`sk`). Each
run reads one selected market. Product availability and content can differ
by country, so use the EAN to confirm that rows from different markets refer
to the same item before comparing their prices.

### Input: product ids, URLs and countries

| Field | Type in the Apify form | Required | Default | Purpose |
|---|---|---|---|---|
| `products` | Array of strings | Yes | No default; form prefill is `["478632371"]` | Product ids or full Kaufland product URLs; duplicates are removed |
| `country` | String | No | `de` | Select `de`, `at`, `nl`, `it`, `pl`, `cz` or `sk` |
| `concurrency` | Integer, 1–8 | No | `3` | Number of parallel product lookups |

`products` must contain at least one valid product. The prefilled id is a
starting point for the form, not an automatically supplied input default.
Replace it with the products you want to monitor. The scraper also preserves
legacy handling of a plain string of ids or URLs separated by commas,
whitespace or newlines; the Apify form uses the list shown above.

Set `country` to the marketplace you intend to read, even when your list
contains complete URLs. The product number is extracted from the URL and
looked up in that selected country. A German link in a Dutch run therefore
requests that id on `kaufland.nl`; it does not change the run to Germany.

The following input was used for the captured output example below. It mixes
bare ids with a full product URL and explicitly sets `concurrency` to 8.
For routine monitoring, start with the default of 3 and adjust only if needed.

```json
{
  "products": [
    "442862724",
    "https://www.kaufland.nl/product/546547025/",
    "478632371"
  ],
  "country": "nl",
  "concurrency": 8
}
```

To begin a run, open the Input tab, choose your country, enter your list and
click Start. Review the Dataset tab after the run, then download the format
needed by your spreadsheet or application. Save that input as an Apify task
and add a schedule when you want the same catalogue checked regularly.

### Output: field names, types and a real example

This is the first dataset row from a real lookup on 9 October 2026. It is
captured using the input above. The price is a snapshot from that lookup,
so a later run can return a different
amount or different availability.

```json
{
  "product_id": "442862724",
  "country": "nl",
  "site": "kaufland.nl",
  "url": "https://www.kaufland.nl/product/442862724/",
  "title": "LEGO Botanica Collectie – Boeket Wilde Bloemen 10280",
  "ean": "5702017416663",
  "price": 52.3,
  "price_text": "52,30",
  "currency": "EUR",
  "image": "https://media.cdn.kaufland.de/product-images/original/c4339de95a950921248728f08364f1ff.jpg",
  "found": true,
  "blocked": false,
  "fetched_at": "2026-10-09T19:23:06.104731Z",
  "country_code": "NL"
}
```

All twelve existing fields retain their names and JSON types. The additional
`country_code` and `fetched_at` fields help combine records across countries
and repeated runs.

| Field | JSON type | Meaning |
|---|---|---|
| `product_id` | string | Kaufland product id extracted from the input |
| `country` | string | Selected market in lowercase, such as `nl` |
| `site` | string | Marketplace domain, such as `kaufland.nl` |
| `url` | string | Product URL in the selected market |
| `title` | string or null | Product title when available |
| `ean` | string or null | EAN or GTIN shown on the page |
| `price` | number or null | Listed price as a number |
| `price_text` | string or null | Original displayed price text |
| `currency` | string | Currency code; normally EUR, PLN or CZK according to market |
| `image` | string or null | Main product image URL |
| `found` | boolean | Whether the product page was read |
| `blocked` | boolean | Whether the lookup could not be completed because access failed |
| `country_code` | string | Selected market in uppercase ISO format, such as `NL` |
| `fetched_at` | string | UTC lookup timestamp in ISO 8601 format |

A row with `found: false` and `blocked: false` means the marketplace returned
a missing product. A row with `found: false` and `blocked: true` means the
lookup was refused or could not be completed; it does not establish that the
product is unavailable. In either case, `title`, `ean`, `price`, `price_text`
and `image` are null. Even a found product can lack an extracted field, so
check for null before joining barcodes or comparing prices.

Run records also include `summary` with `itemCount`, `foundCount`,
`blockedCount` and `errorCount`. When there are errors, the `errors` record
contains readable messages and codes such as `blocked`, `all_blocked` or
`bad_input`. These help distinguish a retry from a correction to the input.
A missing product or access failure can finish as a successful run; inspect
the rows and counts to determine what was actually delivered.

### Use cases for Kaufland product data

**Monitoring Kaufland prices.** Schedule repeated lookups for a known set of
products, then compare numeric `price` values across timestamps. Keep the
`currency` alongside each value and exclude rows without a readable price.
A blocked lookup should trigger another attempt, rather than a conclusion
that a competitor removed its product.

**Catalogue enrichment and verification.** Match the returned `ean` to your
own catalogue to add Kaufland links and main image URLs. Check `found` and
`blocked` separately when deciding whether a listing needs investigation.
Keep the original product id and market so a result remains traceable.

**Cross-border comparison.** Run separate tasks for the supported countries
and join the resulting Kaufland products by EAN. Compare prices in the same
currency, or convert currencies in your analysis. Product ids alone are not
proof that listings in different countries describe the same item.

**Building an id-to-EAN map.** A Kaufland product id identifies a marketplace
listing, while the barcode lets you connect that listing to other retailers.
Collect both and retain the country to avoid mixing country-specific records.

### How this Kaufland scraper compares

| Option | Input and scope | When it fits |
|---|---|---|
| This Kaufland scraper | Product ids or URLs, seven selectable markets, one row per product | Price monitoring and EAN-based catalogue checks |
| Official Kaufland Seller API | Authenticated seller integration; product lookup, inventory and sales operations | Product discovery or management alongside your seller account |
| Kaufland Product Detail Scraper by e-commerce | Product URLs on kaufland.de; detailed attributes, ratings and images | Enriching German product pages with fields beyond this actor's output |
| Kaufland Fast Product Scraper by e-commerce | Search, category and product pages on kaufland.de | Discovering products from German search or category listings |
| Manual spreadsheet collection | Copy information from individual product pages | A small, occasional check |

The [official Kaufland API documentation](https://sellerapi.kaufland.com/?page=rest-api)
describes product search as well as seller operations, and requires signed
requests with seller account keys. This actor reads public product pages
without those seller credentials. Choose according to your input and the
fields you need.

The Store also offers [Kaufland Product Detail Scraper](https://apify.com/e-commerce/kaufland-product-detail-scraper)
and [Kaufland Fast Product Scraper](https://apify.com/e-commerce/kaufland-fast-product-scraper).
They advertise richer German-market extraction and discovery respectively.
Compare their country coverage, output fields and Pricing tabs with your
requirements. Some alternatives bill both a run start and a product result;
this actor has one `product` event and no actor start event.

### Pricing

The price is **$0.0014 per found product on Apify's Free plan** and
**$0.0011 per found product on paid Apify plans**. Only delivered rows with
`found: true` are charged as the `product` event. A found page is chargeable
even if an individual field, such as its title or EAN, is null.

Missing products, blocked lookups and empty results incur no product charge.
There is no separate actor start event or actor rental. A successful retry is
a new product lookup and costs the normal product price; a blocked or missing
retry remains free. See the Pricing tab for the current plan-specific rate.

Free-plan Apify users receive at most the first 10 dataset rows per run,
including any missing or blocked rows. Paid plans remove this actor's ten-row
limit. The free-plan row limit and the price per found product are separate:
receiving a row does not make it chargeable unless `found` is true.

### Limits and interpretation

Supply known product ids or URLs. This actor does not accept keyword searches,
category pages or sitemaps as product discovery inputs. It returns the main
image and listed price, without a seller-by-seller offer list, star ratings,
review counts or brand fields. The listed price is not a guarantee of the
checkout total for a particular seller, shipping address or purchase quantity.

Keep concurrency within 1–8 and begin at 3. If a run repeatedly reports blocked
lookups, retry later with fewer products or a lower concurrency. Invalid values
that leave no valid product ids produce an empty result with an input message.
Do not treat null prices or blocked rows as zero-priced products.

### FAQ

#### Can I search by keyword instead of by id?

This actor takes product ids and URLs. Use a catalogue mapping, a product link
you already have or a separate discovery tool to build your input list.
Search and category extraction require an actor that supports those inputs.

#### Where do I find a product id?

It is the number after `/product/` in a Kaufland product URL. In the captured
example, `https://www.kaufland.nl/product/546547025/` identifies `546547025`.
You can paste the full URL instead of extracting the number yourself.

#### Can I mix countries in one run?

A run reads the market selected by `country`. Create a separate task or run
for each country and keep `country` or `country_code` when combining exports.
Changing the URL's domain in the input does not override the selected market.

#### Is there a Kaufland price scraper I can run on a schedule?

Yes. Save the product list and country as an Apify task and schedule it.
Compare `price` between runs using `fetched_at`, with currency and missing
values handled explicitly. Each found lookup is charged at the ordinary rate.

#### Why did a run return `blocked: true`?

The lookup could not be completed. The product may still exist. Inspect the
`errors` record and retry later, preferably with a smaller list or lower
concurrency. A blocked row is not charged.

#### How do I scrape Kaufland without losing missing-product information?

Retain all rows, including those with `found: false`. Separate confirmed misses
from blocked lookups using `blocked`, and keep null values intact when exporting.
This preserves the difference between an unavailable listing and an incomplete
check, which matters for price alerts and catalogue monitoring.

#### Does this work for Kaufland's supermarket sites?

It reads marketplace product pages in the seven supported countries listed
above. Supermarket leaflets and local store offers are outside its input and
output scope.

#### Is there a Kaufland product scraper that covers more than Germany?

Yes. Select Germany, Austria, the Netherlands, Italy, Poland, Czechia or
Slovakia with `country`. Check availability separately for each market and
use the barcode to match products across countries.

#### Should I use the Kaufland API instead of a scraper?

Use the Seller API when you have seller credentials and need its product,
inventory or sales operations. Use this actor for the documented public-page
fields through Apify. It needs an Apify account, but no Kaufland seller account.

# Actor input Schema

## `products` (type: `array`):

Kaufland product ids or full product URLs. Both forms work, so you can paste links straight from the site. Duplicates are removed.

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

Which Kaufland marketplace to read. A product id is per country: an id listed in Germany is not necessarily listed in Poland.

## `concurrency` (type: `integer`):

Parallel lookups. Kept low on purpose: Kaufland refuses an address that asks too much too quickly, and a refused lookup returns no data.

## Actor input object example

```json
{
  "products": [
    "442862724",
    "https://www.kaufland.de/product/478632371/"
  ],
  "country": "de",
  "concurrency": 3
}
```

# Actor output Schema

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

One row per product id looked up.

## `output` (type: `string`):

Counts plus whether a proxy was configured.

## `errors` (type: `string`):

Blocked lookups and input problems.

# 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 = {
    "products": [
        "478632371"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("s-r/kaufland-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 = { "products": ["478632371"] }

# Run the Actor and wait for it to finish
run = client.actor("s-r/kaufland-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 '{
  "products": [
    "478632371"
  ]
}' |
apify call s-r/kaufland-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,s-r/kaufland-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/peTG9a55o2iKzWWpd/builds/hwWt2d7okumCa040V/openapi.json
