# Lidl US Scraper: Store Prices, myLidl Coupons & Weekly Deals (`moggedhq/lidl-us-scraper`) Actor

Get Lidl US store prices in the USA for milk, coffee and bread: regular prices, weekly deals with dates, public Lidl Plus prices, unit price, brand, size and category. Search or supply product links by ZIP or store. About $0.003 per product. No login.

- **URL**: https://apify.com/moggedhq/lidl-us-scraper.md
- **Developed by:** [mogged](https://apify.com/moggedhq) (community)
- **Categories:** E-commerce, Automation
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.40 / 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.
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

## Lidl US Scraper: Store Prices, myLidl Coupons & Weekly Deals

For retail price analysts, brands and comparison services that need Lidl US (USA) prices at specific stores. Collect regular advertised prices, public Lidl Plus member offers, promotion dates, unit prices, package sizes and product identity in the same product/store format used by the US retail family.

About **$0.003 per product at one store**. A 20-product basket costs about **$0.06** and 1,000 observations cost about **$3**, plus the minimum $0.00005 start charge. Bronze, Silver and Gold prices are lower. Search for milk, coffee or bread, choose ZIP codes or exact stores, then export the results. No login is required.

### What you get

One row is one product at one store. A product at two stores creates two observations. Overlapping searches, repeated IDs and duplicate URLs at the same store are delivered and charged once per run.

| Information | Fields |
| --- | --- |
| Product identity | `productId`, `sku`, `gtin`, `title`, `brand` |
| Store selection | `storeId`, `storeName`, `location`, `storeAddress` |
| Regular shopper price | `price`, `regularPrice`, `onSale`, `size` |
| Public deals | `promoText`, `promoType`, `promoStart`, `promoEnd`, `offers` |
| Lidl Plus offers | `memberPrice`, `memberProgram`, member unit price and offer conditions |
| Unit comparison | `unitPrice`, `unitOfMeasure`, original unit-price text |
| Product context | `category`, `department`, product URL and image URL |
| Optional details | Description, published GTINs, image gallery and public store availability |
| Observation evidence | `scrapedAt`, `offerRegion`, `regionPriceId`, `sourceUrl` |

The current program is **Lidl Plus**, also searched as myLidl. Public member offers stay separate from ordinary shopper prices.

On 4 November 2026, chocolate milk `11249194` was **$1.98** at store `1001`, North Chesterfield, and **$1.49** at `1009`, Greenville. Corresponding unit rates were $0.03 and $0.02 per fl.oz.

### Who uses it

Price analysts monitor comparable baskets; brands compare shelf prices and promotions; comparison sites show selected-store prices. Discover products through keywords or categories, then monitor exact product IDs. Preserve identifiers as text in spreadsheets.

### Start in three steps

1. Enter a few search terms, category/product links or product IDs.
2. Choose US ZIP codes or exact Lidl store IDs and set your total product limit.
3. Run the Actor, inspect SUMMARY for selected stores and coverage, then export JSON, CSV or Excel.

The prefill searches milk near `23235`, capped at 20 products. A 4 November 2026 cloud test delivered 20 unique rows, 20 charges and no source failures in 10.4 seconds. Retries, store count and optional details affect runtime.

### Inputs

| Input | How to use it |
| --- | --- |
| `searchTerms` | Array of plain search terms, for example `["milk", "coffee"]`. |
| `startUrls` | Public Lidl US category, search, campaign, weekly-ad or product links. |
| `productIds` | Numeric ID after `p` in a product URL, for example `11249194`. |
| `locations` | US ZIP codes, for example `["23235", "27858"]`. ZIP+4 is accepted. |
| `storeIds` | Exact store IDs, such as `["1001", "1009"]`, or public object numbers such as `US01001`. |
| `maxItemsPerSearch` | Maximum new rows for each source at each store; default 20, up to 1,000. |
| `maxItems` | Total product/store rows across the run; default 20, up to 10,000. |
| `dealsOnly` | Keep regular-price reductions and current public Lidl Plus offers. |
| `includeDetails` | Add product-page metadata and a public store-availability check, without another product fee. |
| `proxyConfiguration` | Default datacenter routing with US residential retries; custom proxies are supported. |

Exact store IDs take precedence. Empty selections use website default region `1001`. ZIPs select the nearest open store using a public centroid and the store directory. SUMMARY records the selection; a distant ZIP can select a distant store.

Example:

```json
{
  "searchTerms": ["milk", "coffee"],
  "locations": ["23235", "27858"],
  "maxItemsPerSearch": 20,
  "maxItems": 80
}
```

This collects at most 80 observations, about $0.24 at base pricing. Limits are ceilings; the retailer may return fewer matching products.

A category example:

```json
{
  "startUrls": ["https://www.lidl.com/h/cheese-dairy-eggs/h10095761"],
  "storeIds": ["1001"],
  "maxItemsPerSearch": 100,
  "maxItems": 100
}
```

A repeatable basket with store availability and product details:

```json
{
  "productIds": ["11249194", "11240789", "11237181"],
  "storeIds": ["1001", "1009"],
  "includeDetails": true,
  "maxItems": 6
}
```

To collect current public deals, supply the weekly-ad URL `https://www.lidl.com/c/offers-leaflets/s10092873` or set `dealsOnly: true` with your search terms. A search URL with an empty `q`, such as `https://www.lidl.com/q/search?q=`, scans the published catalog. The Actor paginates while new products remain and the requested limits allow more.

### Output fields

The family fields appear first in each product row, following a plain-English `verdict`.

| Field | Meaning |
| --- | --- |
| `retailer`, `country`, `currency` | `Lidl US`, `US`, and `USD`. |
| `storeId`, `storeName`, `location` | Verified store identity and requested ZIP, if any. |
| `productId` | Product identifier from the page URL and public catalog. |
| `sku` | On-page item number when supplied; it differs from productId. |
| `gtin` | Published checksum-valid UPC or GTIN, preserved as text. |
| `title`, `brand`, `size` | Supplied product title, brand and package-size label. |
| `price` | Current nonmember advertised price for the chosen store region. |
| `regularPrice` | Supplied previous/strikethrough price, or current ordinary price when no reduction is shown. |
| `onSale` | Whether the ordinary price is below its supplied comparison price. |
| `promoText`, `promoType` | Displayed promotion text and `sale` or `member` classification. |
| `promoStart`, `promoEnd` | Source timestamps for the applicable current offer. |
| `memberPrice`, `memberProgram` | Separate current Lidl Plus price and program name. |
| `unitPrice`, `unitOfMeasure` | Ordinary shopper unit rate and its label, such as `fl.oz.` or `lb.`. |
| `inStock`, `stockLevel` | Optional public store availability and supplied quantity. Quantity remains null when absent. |
| `rating`, `reviewCount` | Aggregate values when supplied. |
| `category` | Source taxonomy path or product category. |
| `url`, `imageUrl`, `scrapedAt` | Canonical product page, image and UTC observation timestamp. |

Additional fields include member unit rates, original unit-price text, `offers`, `futureMemberOffers`, `isDeal`, `weeklyAd` and price-validity timestamps. Future offers never lower today's price.

`offerRegion` and `regionPriceId` identify the selected price record. Store metadata retains address, timezone, distance in kilometres and requested ZIPs. Details add `stockStatus` and `stockCheckedAt`.

`surpriseItem`, `onSaleDate`, `department`, `brandType` and `sellByWeight` require source evidence. A unit rate per pound alone does not prove variable-weight selling.

### Real output example

North Chesterfield, 4 November 2026:

```json
{
  "recordType": "PRODUCT",
  "retailer": "Lidl US",
  "country": "US",
  "currency": "USD",
  "storeId": "1001",
  "storeName": "Mall Dr, North Chesterfield",
  "productId": "11249194",
  "sku": "7010519",
  "gtin": null,
  "title": "chocolate milk, 1% lowfat",
  "size": "64 fl.oz.",
  "price": 1.98,
  "regularPrice": 1.98,
  "memberPrice": null,
  "unitPrice": 0.03,
  "unitOfMeasure": "fl.oz.",
  "offerRegion": "1001",
  "regionPriceId": "1"
}
```

The overview view combines product, prices, promotion, unit rate and store. The deals view emphasizes offer fields. The `DEALS` JSON output contains only delivered products with a current deal; a large deal export is split into named parts.

Every run writes `SUMMARY` with delivered products, selected stores, deals found, duplicates excluded, source outcomes, free failures and spending-limit status. A parseable invalid selection produces a free `NOTE` row and summary. Check `freeFailures` before accepting a scheduled snapshot as complete.

### Prices and spending limits

| Product/store observations | Base | Bronze | Silver | Gold |
| --- | --- | --- | --- | --- |
| 20 | $0.06 | $0.057 | $0.054 | $0.048 |
| 100 | $0.30 | $0.285 | $0.27 | $0.24 |
| 1,000 | $3 | $2.85 | $2.70 | $2.40 |

Add the minimum $0.00005 start charge. Base price is $0.003 for one distinct product at one store. Bronze is $0.00285, Silver $0.0027 and Gold $0.0024. Product details have no additional product fee. Notes, summaries, empty results, failed requests, retries and duplicates have no Product charge. There is no extra default dataset-row fee.

Set Apify's maximum total charge to control larger jobs. The Actor checks billing capacity before saving another product, stops cleanly when the limit is reached and records that stop in SUMMARY. Saved products survive reboots without another delivery or charge.

### Monitor prices every day

Save a task with stable product and store IDs. In Apify Console, create a schedule, choose that task and set the desired time and timezone. Connect its completed-run webhook to your database, spreadsheet or workflow. Each scheduled run collects a new snapshot.

Join snapshots on `retailer + storeId + productId`, retaining `scrapedAt`. Keep member prices and unit rates separate, compare package sizes and preserve nulls. Store snapshots to build history. Make, Zapier, n8n and Google Sheets can read the dataset and SUMMARY. Keep source failures as gaps rather than substituting old prices.

### API and automation

Start a run with your own Apify token, then retrieve its completed dataset and SUMMARY:

```bash
curl -X POST \
  'https://api.apify.com/v2/acts/moggedhq~lidl-us-scraper/runs' \
  -H 'Authorization: Bearer YOUR_APIFY_TOKEN' \
  -H 'Content-Type: application/json' \
  -d '{"searchTerms":["milk"],"locations":["23235"],"maxItems":20}'
```

```python
from apify_client import ApifyClient
client = ApifyClient("YOUR_APIFY_TOKEN")
run = client.actor("moggedhq/lidl-us-scraper").call(
    run_input={"productIds": ["11249194"], "storeIds": ["1001", "1009"], "maxItems": 2}
)
rows = list(client.dataset(run["defaultDatasetId"]).iterate_items())
```

```javascript
import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('moggedhq/lidl-us-scraper').call({
  searchTerms: ['coffee'], storeIds: ['1001'], maxItems: 20
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
```

### Use with AI agents (MCP)

Connect to `https://mcp.apify.com`. Request Lidl US prices, public Lidl Plus offers, dates and unit rates by ZIP or store. Supply terms/IDs and a cap. Ask the agent to inspect SUMMARY and preserve nulls and membership conditions. Enable includeDetails for store availability.

### Limits

The public catalog is not a physical shelf audit. Lidl warns advertised prices and availability can differ in store. A missing region never receives a default-region price.

Personalized/clipped coupons, rewards, receipts and account data are outside coverage. Membership, activation and checkout conditions may apply. Weekly-ad mode selects catalog deals and public offers, without transcribing image-only flyer panels.

GTINs, ratings, brand type, variable-weight flags and explicit Surprises labels are often absent; missing fields remain null. Checked milk pages published no barcodes. Non-food products are not automatically classified as Surprises.

Stock is null by default. With details enabled, retailer indicators can be available, unavailable or unknown, without an audited unit count. Missing optional stock or metadata does not replace a verified price.

Search follows retailer relevance and may return related matches. Publication windows can change. Source timezones are retained; ordinary price-validity timestamps are distinct from sale dates.

Outages and site changes can cause incomplete output. Requests are sequential and paced, with fresh-session retries. Endpoint discovery is cached for seven days; address/region metadata for one day, with a verified directory less than seven days old available on refresh failure. Each row exposes metadata cache flags and observation time. Prices and stock are fetched for the current run. No login, account cookies or CAPTCHA solving.

### FAQ

**Which product number should I supply?** Use the numeric value after `p` in the product URL. The separate on-page item number is returned as `sku`.

**Can I choose an exact store?** Yes. `storeIds` makes a monitored basket repeatable. ZIP codes choose the nearest open store using the available centroid and directory.

**Does price include the Lidl Plus discount?** The ordinary shopper price stays in `price`; the public member offer stays in `memberPrice` with its eligibility and dates.

**Why do two stores have different prices?** The retailer publishes regional price variants. Each row retains the selected store's offer region and price-record ID.

**Can I get only deals?** Use `dealsOnly` or a supported weekly-ad link. The `DEALS` output also isolates delivered deal rows.

**Are duplicates charged?** Overlapping inputs at one store are charged once per run. Another store or scheduled snapshot is another observation.

**What happens with invalid input?** Parseable invalid selections produce a free note and summary. Apify may reject schema-invalid input before a run starts; neither path adds a Product charge.

**Can I combine US grocery Actors?** Yes. Common product, store, price, promotion and unit-price fields support one downstream table.

# Actor input Schema

## `searchTerms` (type: `array`):

Keywords searched in the Lidl US catalog at each chosen store. Empty search URLs scan the published catalog.

## `startUrls` (type: `array`):

Public lidl.com category, campaign, weekly-ad, search or product URLs. Weekly-ad links select current catalog deals; image-only flyer panels are outside coverage.

## `productIds` (type: `array`):

Numeric product number after p in a Lidl US product URL, for example 11249194. The on-page item number is a different identifier.

## `locations` (type: `array`):

Select the nearest open Lidl using the US ZIP centroid and live store directory. Leave empty for the website default region. Exact store IDs take precedence.

## `storeIds` (type: `array`):

Exact numeric store IDs, such as 1001, or public object numbers such as US01001. One row is one product at one store.

## `maxItemsPerSearch` (type: `integer`):

Maximum new product rows for one source at one store. A product supplied by overlapping sources is delivered once.

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

Maximum product/store observations for the whole run. Notes and failed requests have no product charge.

## `dealsOnly` (type: `boolean`):

Keep public regular-price reductions and current Lidl Plus member offers. Member eligibility and dates stay separate.

## `includeDetails` (type: `boolean`):

Read additional product pages for descriptions, GTINs when published, images and store-specific public availability. No extra product fee.

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

Default datacenter proxy first; US residential only after repeated refusal. Custom Apify proxy or custom proxy URLs are supported.

## Actor input object example

```json
{
  "searchTerms": [
    "milk"
  ],
  "locations": [
    "23235"
  ],
  "maxItemsPerSearch": 20,
  "maxItems": 20,
  "dealsOnly": false,
  "includeDetails": false,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `products` (type: `string`):

No description

## `dealsView` (type: `string`):

No description

## `dealsOnly` (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 = {
    "searchTerms": [
        "milk"
    ],
    "locations": [
        "23235"
    ],
    "maxItemsPerSearch": 20,
    "maxItems": 20,
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("moggedhq/lidl-us-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 = {
    "searchTerms": ["milk"],
    "locations": ["23235"],
    "maxItemsPerSearch": 20,
    "maxItems": 20,
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("moggedhq/lidl-us-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 '{
  "searchTerms": [
    "milk"
  ],
  "locations": [
    "23235"
  ],
  "maxItemsPerSearch": 20,
  "maxItems": 20,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call moggedhq/lidl-us-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,moggedhq/lidl-us-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/ZGN9nB5Jfo2wvbnCL/builds/nHX35CjaQxTdIKYWL/openapi.json
