# Lidl API scraper — Lidl's web shops in 8 European countries and the in-store weekly offers of 30: search, category browse, offers and the full product record with EAN, variants, Lidl Plus member price and delivery, in local currency. No account, no browser.

> Search one Lidl country by keyword (or EAN): product id, title, brand, image, the public price with the struck-through price and whether that is the recommended retail price or Lidl's previous price, discount, unit price, Lidl Plus member price kept separate, rating and review count, web-shop availability and in-store offer dates. Filter by brand, price, rating and availability; sort by price, rating, newest, bestselling or discount.
> ReefAPI engine `lidl` · 4 endpoints · clean JSON, no scraping or browsers to manage.

## How to call
- **Endpoint:** `POST https://api.reefapi.com/lidl/v1/<action>` with a JSON body.
- **Auth:** header `x-api-key: <YOUR_REEFAPI_KEY>` — create one free (1,000 credits, no card): https://reefapi.com/signup
- **Response (every call):** `{ ok: boolean, data: ..., meta: { record_count, credits, ... }, error: { code, message } }` — branch on `ok`. Failed calls are free except verified SHEIN NOT_FOUND on product/detail and price (4 credits).
- **One key + one shared credit pool** across every ReefAPI API. Per-call credits are listed on each endpoint below.
- **Use it from an AI agent (MCP):** connect `https://api.reefapi.com/mcp` (remote streamable-http, `Authorization: Bearer <key>`) and your assistant can call these actions directly.

## Endpoints

### POST /lidl/v1/search — 1 credit
Search one Lidl country by keyword (or EAN): product id, title, brand, image, the public price with the struck-through price and whether that is the recommended retail price or Lidl's previous price, discount, unit price, Lidl Plus member price kept separate, rating and review count, web-shop availability and in-store offer dates. Filter by brand, price, rating and availability; sort by price, rating, newest, bestselling or discount.

**Parameters:**
- `query` (string, required) — What to look for, in the country's language. An EAN barcode also works.
- `country` (enum, optional, default "de") — Lidl country site. de, fr, pl, nl, be, es, cz and sk have a web shop; the other countries list only their current and upcoming in-store offers. Prices come back in that country's currency. [one of: de, fr, pl, nl, be, es, cz, sk, it, at, hu, ro, bg, hr, si, ch, dk, se, fi, ie, gb, pt, lt, lv, ee, gr, cy, rs, mt, lu]
- `language` (enum, optional) — Only for Belgium (nl, fr) and Switzerland (de, fr, it). Every other country has one language and ignores nothing — a language it does not offer is rejected. [one of: nl, fr, de, it]
- `page` (integer, optional, default 1) — Result page, 1-based. A page past the end returns an empty list.
- `limit` (integer, optional, default 36) — Products per page, 1-100 (Lidl's own page is 36).
- `sort` (enum, optional, default "relevance") — Order of results. Only orderings Lidl offers are accepted. [one of: relevance, price_asc, price_desc, newest, rating, bestselling, discount]
- `brand` (array, optional) — One brand or a list (any of them), spelt as Lidl shows it on rows (`brand`).
- `price_min` (number, optional) — Lowest price, in the country's currency.
- `price_max` (number, optional) — Highest price, in the country's currency.
- `min_rating` (number, optional) — Only products rated at least this (1-5).
- `availability` (enum, optional) — Restrict to web-shop stock or to in-store offers. [one of: online, in_store]
- `max_rotations` (integer, optional, default 3) — Advanced: how many times to retry a difficult request (1-5).

**Returns:** results[]{product_id, title, brand, url, image, images[], currency, price (public shelf price — null when Lidl publishes only a member price), price_before_discount, price_before_discount_type (recommended_retail_price|previous_price), discount_percent, discount_label, multi_buy, unit_price, unit_price_text, packaging, price_valid_from, price_valid_until, member_price (Lidl Plus app price — never the public price), member_price_before_discount, member_program, member_price_label, member_discount_label, member_unit_price_text, regional_prices[]{region_id, price, price_before_discount, valid_until}, rating, review_count, rating_scale (5), available_online, availability (available_online|coming_soon_online|in_store_only|unavailable_online), availability_text, in_store, store_offers[]{label, type, valid_from, valid_until}, product_type, has_variants, category, deal_of_the_day, age_restricted}, count, total_results, offset, sort_applied, corrected_query, keyword_matches_on_page, fallback_results_dropped, country, language, currency, web_shop, query, redirect{url, product_id}

**Example request body:**
```json
{
  "query": "kaffeemaschine",
  "country": "de"
}
```

### POST /lidl/v1/category/products — 1 credit
Browse one Lidl category by its id or URL: the same product rows, filters, sorts and paging as search.

**Parameters:**
- `category` (string, required) — A Lidl category id from a category URL (…/h/kaffee-espressomaschinen/h10006306 → h10006306, …/c/kueche-haushalt/s10067764 → s10067764). The full URL is accepted.
- `country` (enum, optional, default "de") — Lidl country site. de, fr, pl, nl, be, es, cz and sk have a web shop; the other countries list only their current and upcoming in-store offers. Prices come back in that country's currency. [one of: de, fr, pl, nl, be, es, cz, sk, it, at, hu, ro, bg, hr, si, ch, dk, se, fi, ie, gb, pt, lt, lv, ee, gr, cy, rs, mt, lu]
- `language` (enum, optional) — Only for Belgium (nl, fr) and Switzerland (de, fr, it). Every other country has one language and ignores nothing — a language it does not offer is rejected. [one of: nl, fr, de, it]
- `page` (integer, optional, default 1) — Result page, 1-based. A page past the end returns an empty list.
- `limit` (integer, optional, default 36) — Products per page, 1-100 (Lidl's own page is 36).
- `sort` (enum, optional, default "relevance") — Order of results. Only orderings Lidl offers are accepted. [one of: relevance, price_asc, price_desc, newest, rating, bestselling, discount]
- `brand` (array, optional) — One brand or a list (any of them), spelt as Lidl shows it on rows (`brand`).
- `price_min` (number, optional) — Lowest price, in the country's currency.
- `price_max` (number, optional) — Highest price, in the country's currency.
- `min_rating` (number, optional) — Only products rated at least this (1-5).
- `availability` (enum, optional) — Restrict to web-shop stock or to in-store offers. [one of: online, in_store]
- `max_rotations` (integer, optional, default 3) — Advanced: how many times to retry a difficult request (1-5).

**Returns:** results[]{product_id, title, brand, url, image, images[], currency, price (public shelf price — null when Lidl publishes only a member price), price_before_discount, price_before_discount_type (recommended_retail_price|previous_price), discount_percent, discount_label, multi_buy, unit_price, unit_price_text, packaging, price_valid_from, price_valid_until, member_price (Lidl Plus app price — never the public price), member_price_before_discount, member_program, member_price_label, member_discount_label, member_unit_price_text, regional_prices[]{region_id, price, price_before_discount, valid_until}, rating, review_count, rating_scale (5), available_online, availability (available_online|coming_soon_online|in_store_only|unavailable_online), availability_text, in_store, store_offers[]{label, type, valid_from, valid_until}, product_type, has_variants, category, deal_of_the_day, age_restricted}, count, total_results, offset, sort_applied, corrected_query, keyword_matches_on_page, fallback_results_dropped, country, language, currency, web_shop, category

### POST /lidl/v1/deals — 1 credit
Lidl's in-store offers for one country — the weekly leaflet products, current and upcoming — with each offer's valid-from and valid-until dates, the offer price, struck price, unit price and any Lidl Plus member price. Works in all 30 countries, including those without a web shop.

**Parameters:**
- `country` (enum, optional, default "de") — Lidl country site. de, fr, pl, nl, be, es, cz and sk have a web shop; the other countries list only their current and upcoming in-store offers. Prices come back in that country's currency. [one of: de, fr, pl, nl, be, es, cz, sk, it, at, hu, ro, bg, hr, si, ch, dk, se, fi, ie, gb, pt, lt, lv, ee, gr, cy, rs, mt, lu]
- `language` (enum, optional) — Only for Belgium (nl, fr) and Switzerland (de, fr, it). Every other country has one language and ignores nothing — a language it does not offer is rejected. [one of: nl, fr, de, it]
- `query` (string, optional) — Optional keyword to narrow the offers.
- `page` (integer, optional, default 1) — Result page, 1-based. A page past the end returns an empty list.
- `limit` (integer, optional, default 36) — Products per page, 1-100 (Lidl's own page is 36).
- `sort` (enum, optional, default "relevance") — Order of results. Only orderings Lidl offers are accepted. [one of: relevance, price_asc, price_desc, newest, rating, bestselling, discount]
- `brand` (array, optional) — One brand or a list (any of them), spelt as Lidl shows it on rows (`brand`).
- `price_min` (number, optional) — Lowest price, in the country's currency.
- `price_max` (number, optional) — Highest price, in the country's currency.
- `max_rotations` (integer, optional, default 3) — Advanced: how many times to retry a difficult request (1-5).

**Returns:** results[]{product_id, title, brand, url, image, images[], currency, price (public shelf price — null when Lidl publishes only a member price), price_before_discount, price_before_discount_type (recommended_retail_price|previous_price), discount_percent, discount_label, multi_buy, unit_price, unit_price_text, packaging, price_valid_from, price_valid_until, member_price (Lidl Plus app price — never the public price), member_price_before_discount, member_program, member_price_label, member_discount_label, member_unit_price_text, regional_prices[]{region_id, price, price_before_discount, valid_until}, rating, review_count, rating_scale (5), available_online, availability (available_online|coming_soon_online|in_store_only|unavailable_online), availability_text, in_store, store_offers[]{label, type, valid_from, valid_until}, product_type, has_variants, category, deal_of_the_day, age_restricted}, count, total_results, offset, sort_applied, corrected_query, keyword_matches_on_page, fallback_results_dropped, country, language, currency, web_shop

**Example request body:**
```json
{
  "country": "it"
}
```

### POST /lidl/v1/product/detail — 1 credit
The full Lidl product record by id or URL: title, brand, gallery, EAN/GTIN, public price with struck price and its type, unit price, Lidl Plus member price, rating with review count and recommendation counts, web-shop availability, in-store offer dates, delivery time and charge, maximum order quantity, description, bullet points, specification table, breadcrumb, size and colour variants each with price, stock state and EAN, manuals, and the other Lidl countries that sell it.

**Parameters:**
- `product_id` (string, required) — Lidl product id — the digits after /p in a product URL (…/p100348984 → 100348984). A variant id or a full product URL is accepted; a URL also sets the country.
- `country` (enum, optional, default "de") — Lidl country site. de, fr, pl, nl, be, es, cz and sk have a web shop; the other countries list only their current and upcoming in-store offers. Prices come back in that country's currency. [one of: de, fr, pl, nl, be, es, cz, sk, it, at, hu, ro, bg, hr, si, ch, dk, se, fi, ie, gb, pt, lt, lv, ee, gr, cy, rs, mt, lu]
- `language` (enum, optional) — Only for Belgium (nl, fr) and Switzerland (de, fr, it). Every other country has one language and ignores nothing — a language it does not offer is rejected. [one of: nl, fr, de, it]
- `max_rotations` (integer, optional, default 3) — Advanced: how many times to retry a difficult request (1-5).

**Returns:** product{product_id, requested_variant_id, title, brand, url, images[], currency, price, price_before_discount, price_before_discount_type, discount_percent, discount_label, multi_buy, unit_price, unit_price_text, packaging, price_valid_from, price_valid_until, member_price, member_price_before_discount, member_program, member_price_label, member_discount_label, member_unit_price_text, regional_prices[], rating, review_count, rating_scale, recommended_yes, recommended_no, available_online, availability, availability_text, in_store, store_offers[], sold_online, sold_in_store, max_order_quantity, gtin (a valid GS1 barcode; null when Lidl publishes none), gtins[], in_store_codes[] (Lidl's internal 2-prefix store codes, not barcodes), description, feature_bullets[], long_description, specifications[]{name, value}, breadcrumbs[], category, product_type, variants[]{variant_id, attributes{size, colour, …}, title, price, price_before_discount, price_before_discount_type, available_online, availability, ean, url}, delivery{text, days, by_freight_forwarder, home_delivery_charge, free_delivery, returns}, manuals[]{name, url}, age_restricted, alcoholic, other_countries[]{country, language, url}, country, language, web_shop}

**Example request body:**
```json
{
  "product_id": "100348984",
  "country": "de"
}
```

## More
- Try it live, no code: https://reefapi.com/playground?engine=lidl
- Human docs page: https://reefapi.com/docs/lidl
- Overview page: https://reefapi.com/lidl-api
- Every ReefAPI API in one file (for your AI): https://reefapi.com/llms-full.txt
