Skip to main content
Piloterr
Back to blog
July 2, 2026

€17.99 in France, €29.99 in Germany: monitoring prices by country

You monitor prices for a retailer operating across a dozen countries? On Lidl, the same ERP reference can sell for €17.99 in France, €29.99 in Germany, and 119 PLN in Poland on the same day, with or without a promo, sometimes with no listing at all.

For pricing and data teams, the challenge is not just collecting those numbers: it is comparing distinct regional offers without mixing currencies, asynchronous promos, and assortment gaps. Piloterr surfaces each Lidl shop as displayed to the local customer, via the Lidl API, across 27 markets.

This article explains how to structure a multiregional price monitoring pipeline, why price gaps exist (and are not data bugs), and how to observe them in practice with API calls and a Python script.

One product, many commercial offers

In economic theory, price discrimination means charging each segment according to its willingness to pay. Online, geographic segmentation is trivial: lidl.fr and lidl.de are distinct commercial contexts even when they share the same brand.

In practice, each national shop calibrates price based on:

  • Local competition (Castorama in France, OBI in Germany, etc.)
  • Perceived brand positioning in that market
  • The subsidiary's promo calendar
  • Purchasing power and local price anchors

The result: same product identity, different economic offer. This is not an anomaly to fix in your pipeline. It is the data to capture.

What moves price from one country to another

Local costs and constraints

Two regions can sell the same SKU while facing different cost structures:

FactorImpact
VAT and tax rulesTax-inclusive display, variable rates
Customs and importEspecially outside single-market blocs
Logistics and last mileCarrier contracts, labor
Compliance (packaging, labeling)Local compliance costs
Fraud and payment methodsMarket-specific risk and fees

The displayed price embeds these constraints. Comparing France and Poland without FX conversion or local context says little about actual commercial strategy.

Promotions are not synchronized

Promo mechanics (strikethrough prices, "−44%" badges, "mega deal" labels) are decided country by country. A product on sale in France can be at full price in Germany on the same day. That is not an API inconsistency: promo calendars are decentralized.

For analysis, two consequences:

  • Spot price and reference price must be stored separately.
  • discount_percentage is a derived field: it may be absent when no local promo is running.

Assortment is never 100% identical

Some ERP references are pan-European. Others are listed only where demand, regulation, or logistics allow. Titles, slugs, and product pages also vary by locale.

A missing listing is itself a signal: product not distributed, temporary stockout, or catalog delisting. Do not confuse it with a request error.

Multiregional shops expose the native currency of their jurisdiction. On some markets (Bulgaria, for example), a secondary currency may appear alongside the primary one.

In analytics, always store (price, currency, region, timestamp). Convert offline when you need comparability. The API should not normalize everything to EUR: the displayed price is the commercial and legal offer as the customer sees it.

The right mental model for your data

Think in regional offers, not a single price:

Plain text
Global product identity (ERP / SKU)

   ┌────┼────┐
   ▼    ▼    ▼
Offer  Offer  Offer
 FR     DE     PL
€17.99 €29.99 119 PLN
 promo   —      —

Each (erp_id, region) pair is a distinct offer. Your record key should look like:

(erp_id, region, observed_at) → { price, currency, old_price, in_stock, url, locale }

That model avoids misleading comparisons and dashboards that mix apples and oranges.

Case study: one PARKSIDE drill across 8 countries

Take ERP reference 100397447, the PARKSIDE PSBM 750 B3 percussion drill. Same product, observed across several Lidl shops in June 2026:

RegionPriceCurrencyOld priceReading
France17.99EUR31.99Active promo (~−44%)
Spain19.99EURNo strikethrough at observation time
Slovakia19.99EUR29.99Promo
Belgium (FR/NL)24.99EUR34.99Same price on both BE locales
Poland119.00PLN≈ €27 at typical FX
Germany29.99EUR~67% higher nominal EUR than FR
Netherlands29.99EURAligned with Germany
Czechia999.90CZK≈ €40 at typical FX

Not listed at test time: UK, Italy, Portugal, Hungary, Romania. Same ERP, partial assortment.

Four lessons from a single product page:

  1. The euro does not guarantee uniformity: €17.99 vs €29.99 inside the eurozone.
  2. Promos are asynchronous: FR, SK, and BE discounted; DE and NL at full price.
  3. Currencies require conversion for any serious comparison.
  4. Catalog coverage varies: a "European" product is not necessarily everywhere.

What the API returns (France vs Germany)

In France, the shop shows a promotion:

JSON
{
  "product_id": "100397447",
  "title": "PARKSIDE® Perceuse à percussion PSBM 750 B3, 10 Nm, 750 W",
  "price": 17.99,
  "old_price": 31.99,
  "discount_percentage": 43.0,
  "currency": "EUR",
  "locale": "fr-fr",
  "in_stock": true
}

In Germany, same reference, different title, different price, no promo:

JSON
{
  "product_id": "100397447",
  "title": "PARKSIDE® Schlagbohrmaschine »PSBM 750 B3«",
  "price": 29.99,
  "currency": "EUR",
  "locale": "de-de",
  "in_stock": true
}

The API does not try to harmonize. It surfaces what each shop displays. The spread you see in the responses is the same spread a customer would see when switching national sites.

Piloterr API examples

Two endpoints cover the use case: product for a precise regional offer, search to discover references in a national catalog. The query parameter accepts an ERP reference, a full Lidl URL, or a keyword; region targets the shop when no URL is provided.

curl: same ERP, two regions

Replace YOUR-API-KEY with your key from the Piloterr dashboard.

France (promo active at observation time):

Bash
curl -G "https://api.piloterr.com/v2/lidl/product" \
  -H "x-api-key: YOUR-API-KEY" \
  --data-urlencode "query=100397447" \
  --data-urlencode "region=fr"

Germany (same reference, different price):

Bash
curl -G "https://api.piloterr.com/v2/lidl/product" \
  -H "x-api-key: YOUR-API-KEY" \
  --data-urlencode "query=100397447" \
  --data-urlencode "region=de"

You can also pass a national URL: the region is inferred from the domain and the region parameter is ignored.

Bash
curl -G "https://api.piloterr.com/v2/lidl/product" \
  -H "x-api-key: YOUR-API-KEY" \
  --data-urlencode "query=https://www.lidl.pl/p/parkside-wiertarka-udarowa-750-w-psbm-750-b3/p100397447"

Search to find ERP references in a given market:

Bash
curl -G "https://api.piloterr.com/v2/lidl/search" \
  -H "x-api-key: YOUR-API-KEY" \
  --data-urlencode "query=drill" \
  --data-urlencode "region=de"

Python: compare one reference across regions

This script queries several shops for the same ERP reference and prints a comparative snapshot. Missing listings are treated as null offers, not fatal errors.

Python
import requests
from datetime import datetime, timezone

PILOTERR_API_KEY = "YOUR-API-KEY"
ERP_ID = "100397447"
REGIONS = ["fr", "de", "pl", "es", "nl", "cs"]

def fetch_lidl_offer(erp_id: str, region: str) -> dict | None:
    response = requests.get(
        "https://api.piloterr.com/v2/lidl/product",
        headers={"x-api-key": PILOTERR_API_KEY},
        params={"query": erp_id, "region": region},
        timeout=30,
    )
    if response.status_code == 404:
        return None
    response.raise_for_status()
    return response.json()

def main():
    observed_at = datetime.now(timezone.utc).isoformat()
    print(f"ERP {ERP_ID} — observed at {observed_at}\n")

    for region in REGIONS:
        try:
            offer = fetch_lidl_offer(ERP_ID, region)
        except requests.HTTPError as exc:
            print(f"{region.upper():<4}  error  {exc}")
            continue

        if offer is None:
            print(f"{region.upper():<4}  —      not listed")
            continue

        price = offer.get("price")
        currency = offer.get("currency", "?")
        old_price = offer.get("old_price")
        promo = f" (was {old_price})" if old_price else ""
        stock = "in stock" if offer.get("in_stock") else "out of stock"

        print(f"{region.upper():<4}  {price} {currency}{promo}  {stock}")

if __name__ == "__main__":
    main()

Sample output (June 2026):

Plain text
ERP 100397447 — observed at 2026-06-15T09:00:00+00:00

FR    17.99 EUR (was 31.99)  in stock
DE    29.99 EUR  in stock
PL    119.0 PLN  in stock
ES    19.99 EUR  in stock
NL    29.99 EUR  in stock
CS    999.9 CZK  in stock

For cross-currency comparison, convert offline with your FX rates for the day. The API returns the price as displayed on the local shop, which is the right granularity for compliant monitoring and promo archiving.

Full docs: Lidl Search and Lidl scraper.

What this means for price monitoring

If you monitor multiregional prices (Lidl or elsewhere), a few simple principles apply:

Do

  • Fix a global product key (ERP, GTIN, manufacturer SKU) to join offers.
  • Query each region explicitly: region=fr, region=de, etc.
  • Keep timestamp, currency, and locale on every snapshot.
  • Treat missing listings as null offers, not errors.
  • Separate spot price, reference price, and availability.

Avoid

  • Comparing 119 PLN and €17.99 without FX conversion.
  • Using a single region as "the Lidl price".
  • Expecting identical promo flags across countries.
  • Confusing product absence with a technical failure.

For Lidl specifically, Piloterr covers 27 national shops (fr, de, pl, gb, ch, cs, be, etc.).

Edge cases that surprise teams in production

PhenomenonInterpretation
price: null on some Austrian listingsProduct visible, but no online price in the payload
Dual currency (e.g. Bulgaria)Primary currency follows shop display rules
Product missing on lidl.co.ukAssortment gap, not API failure
Different titles and slugs FR/DESame ERP, localized merchandising
Inconsistent old_price on some categoriesValidate semantics per product category

These cases do not overturn the general principle: each region is an autonomous offer.

In summary

Cross-country price gaps in e-commerce are structural and intentional. They come from market segmentation, local costs, currencies, decentralized promos, and assortment choices.

Lidl is a clear illustration: one ERP reference, eight different regional offers on the same tool. With Piloterr, you access each one as presented to the local customer, ready to feed a price monitoring pipeline or competitive positioning analysis.

For more on promotional price compliance in Europe, see our article on the Omnibus directive.

Prices and availability mentioned reflect observations from June 2026. They change with promotions and repricing.

More to read

Guides and news about web scraping, proxies, and data extraction.

Scraping

Migrating from NetNut: what to do after the network takedown

Google took action against the NetNut/Popa proxy network alongside the FBI and Lumen. How to rethink your scraping stack without managing proxies yourself.

Josselin Liebe
Josselin Liebe
Read
Scraping

Best Leboncoin Scraper 2026

Piloterr vs Apify vs lobstr.io for Leboncoin scraping in 2026. Pricing, endpoints, and product data verified from official sources on June 29, 2026 — including the legal gap between public and authenticated scraping.

Josselin Liebe
Josselin Liebe
Read
Scraping

How to Scrape Company Salary Data with Python

Learn to scrape Comparably salary data with Python and Piloterr. Complete tutorial with code, Angular handling, and structured JSON extraction.

Josselin Liebe
Josselin Liebe
Read

Ready to get started?

Your web scraping API is one click away. Start with +500 credits, no infrastructure to set up, no proxies to manage, and no credit card required.

  • +500 credits
  • No credit card required
  • All endpoints included