REWE.de Scraper - Prices, Offers & Postal-Code Matching
Pricing
from $1.00 / 1,000 product results
REWE.de Scraper - Prices, Offers & Postal-Code Matching
Scrape REWE Germany (rewe.de) grocery products: current price, was-price and discount when genuinely on offer, brand, category, price per unit, images and tags. Prices match a real postal code you choose. Search keywords or paste product/listing links.
Pricing
from $1.00 / 1,000 product results
Rating
0.0
(0)
Developer
Abot API
Maintained by CommunityActor stats
0
Bookmarked
11
Total users
3
Monthly active users
14 days ago
Last modified
Categories
Share
REWE Scraper: German Grocery Prices, Offers and Product Details by Postal Code
REWE Scraper pulls product data from REWE Germany's own grocery catalog (rewe.de), matched to the real market for a German postal code you choose, the same way the site itself scopes prices, offers and assortment to your address. Search by keyword and/or REWE's own category, brand and dietary/sourcing filters, or paste product and listing links directly. Was-price and discount are only ever reported when REWE's own data genuinely carries a reduced price, never guessed. Export to JSON, CSV or Excel, or pull results straight into your app through the API.
Why This Scraper?
- Postal-code matched pricing and assortment. A German postal code (PLZ) resolves your local REWE market before anything else runs. It changes which products even show up, not just their prices, the same way the site itself works.
- Was-price and discount, gated on the site's own signal. When a product genuinely carries a reduced price, the original price plus the discount amount and percentage are captured. A full-price product simply carries
originalPrice: null, nothing is fabricated. - Real site filters. Brand and REWE's own dietary/sourcing quick filter (Bio, Vegan, Regional, New, Gekühlt, Tiefgefroren) apply in search mode and to a pasted listing link, because a pasted listing link is rebuilt through the same filters, not just replayed; category applies in search mode only, since a pasted link already carries its own category.
- Two ways in. Keyword and/or category search, or paste any product or listing link.
- Optional detail enrichment. Turn on Fetch product detail to add the description and ingredient statement from the product page, on top of the price, brand, category and images already included by default.
- Optional export to your apps. Send results into Notion, Linear, Airtable or any Apify MCP connector alongside the dataset.
- Resume and recurring updates. Continue one interrupted crawl with a run or dataset id, or turn on Incremental mode to track the same search over time and get only what changed.
Use Cases
- Grocery price monitoring: track price and promotion changes for specific products or categories in one or more postal-code markets over time.
- Competitive and market intelligence: compare REWE's assortment, pricing and current offers against other supermarkets for a given region.
- Market research and analytics: build a structured dataset of product names, brands, categories and pricing for a German market.
- Brand and MAP monitoring: brands and agencies checking how their products are listed and priced on REWE in specific markets.
- Grocery comparison and content sites: aggregate real product details and current specials into a comparison tool or feed.
Data You Get
| Field | Example |
|---|---|
productId | "677067" |
name | "Sample Fresh Whole Milk 3.5% 1l" |
brand | "Sample Dairy" |
category / categoryPath | "Frischmilch" / ["Kühlregal", "Milchprodukte", "Frischmilch"] |
categoryId | "175" |
tags | ["Gekühlt", "Regional"] |
url | "https://www.rewe.de/p/sample-fresh-whole-milk-3-5-1l/677067" |
hasVariants | false |
freeShipping | false |
price / currency | 1.29 / "EUR" |
originalPrice / discountAmount / discountPercent | 1.59 / 0.3 / 19 (all null off-special) |
isOnSpecial | true |
pricePerUnit / grammage | "1.29 EUR / l" / "1l" |
available | true |
offerValidTo | "2026-10-05T23:59:59Z" (on-special only) |
merchant | "REWE" |
gtin | "4008400205746" |
image / images | "https://img.rewe-static.de/sample/digital-image.png" / [...] |
description / ingredients | only when Fetch product detail is on |
Sample shape: values above are illustrative placeholders, not from a live product.
When Incremental mode is on, every returned record also carries changeType, changedFields, firstSeenAt and lastSeenAt. See "Resume and recurring updates" below for exactly what those mean.
How to Use
- Pick a mode:
search(keyword and/or category, plus REWE's own brand and dietary/sourcing filters) orurl(paste product or listing links). - Set your postal code (PLZ) so prices, offers and the product assortment match the REWE market for that address.
- Fill in the fields for your mode, and turn on Fetch product detail if you also want description and ingredients.
- Set Max products and Max pages to control run size and cost, then click Start.
Keyword search, first page:
{"mode": "search","searchTerm": "milch","zipCode": "50667","maxItems": 20}
Category browse, filtered to a brand and a dietary tag:
{"mode": "search","categorySlug": "milch","brand": "Alpro","attribute": "VEGAN","zipCode": "50667","maxItems": 50,"maxPages": 5}
Paste product or listing links, with detail enrichment on:
{"mode": "url","urls": ["https://www.rewe.de/p/weihenstephan-h-milch-3-5-1l/677067"],"zipCode": "50667","fetchDetails": true}
Recurring search, tracked with Incremental mode:
{"mode": "search","searchTerm": "milch","zipCode": "50667","incrementalMode": true,"stateKey": "cologne-milk-watch"}
Run it from your code
Python:
from apify_client import ApifyClientclient = ApifyClient("<YOUR_APIFY_TOKEN>")run = client.actor("abotapi/rewe-de-scraper").call(run_input={"mode": "search","searchTerm": "milch","zipCode": "50667","maxItems": 20,})for product in client.dataset(run["defaultDatasetId"]).iterate_items():print(product["name"], product["price"], product["currency"])
JavaScript:
import { ApifyClient } from 'apify-client';const client = new ApifyClient({ token: '<YOUR_APIFY_TOKEN>' });const run = await client.actor('abotapi/rewe-de-scraper').call({mode: 'search',searchTerm: 'milch',zipCode: '50667',maxItems: 20,});const { items } = await client.dataset(run.defaultDatasetId).listItems();
Or connect it to Make, Zapier, n8n, Google Sheets or webhooks from the Integrations tab.
How price filtering is bounded
REWE offers no price filter of its own, so minPrice/maxPrice narrow what this actor returns to you, after a page has already been fetched, rather than what REWE hands back. To stop a very selective band from paging through an entire category or search looking for survivors, a search stops after 5 consecutive result pages that contained new (not-yet-seen) products but none of them matched the price band. A stop like this is reported in the run log, and it means the search was not read to the end: more matches may exist further down. Narrow the search or category, or widen the price band, to see more. Pages with nothing new on them at all, for example when resuming a run whose early pages are already collected, never count toward this limit.
Resume and recurring updates
- Resume (
resumeFromRunId) continues one specific interrupted crawl: paste a run id or dataset id and this run skips products already collected there, returning only the remaining new products. - Incremental mode (
incrementalMode) is for running the same search again and again (daily, weekly) and getting only the changes. The actor remembers the previous run of the same search by itself, so you never paste a run id. The first run returns everything asNEW. By default (withemitExpiredoff), later runs return onlyNEWandUPDATEDproducts;UNCHANGEDproducts are suppressed and not billed unlessemitUnchangedis on.REAPPEAREDandEXPIREDare a pair:EXPIREDtombstones are only created whenemitExpiredis on for a run that fully scans the tracked search (not capped by Max products/Max pages, not stopped early by a connection problem, and never on a Resume run). A product only classifies asREAPPEAREDonce it had previously been tombstoned that way and is then seen again, so ifemitExpiredhas never been turned on for a given search,REAPPEAREDwill never appear for it either. State is isolated automatically per mode/postal code/search term/category/brand/attribute/price filters/URLs/detail setting (postal code is included because it selects a different REWE market); setstateKeyto name or deliberately share a monitoring campaign.
In Incremental mode, if Fetch product detail is on and a detail-page fetch fails on a later run, the previously fetched description/ingredients are carried forward from state rather than dropped, so a transient fetch failure never looks like real content disappearing, and never re-bills the detail-enrichment surcharge for it.
Send results into your apps (MCP connectors)
Optionally pipe the scraped results into the apps you already use, via Model Context Protocol (MCP) connectors. This is an extra delivery step after the scrape: the Apify dataset is never changed.
What gets written to the connector: a condensed, human-readable summary of each product, not the full JSON. Each item becomes one entry with a title and its key fields flattened to plain text. The complete record always stays in the Apify dataset.
- Authorize a connector once under Apify, Settings, Integrations (Notion, Linear, Airtable, or Apify).
- Select it in the "Pipe results into your apps" input field. If the picker is empty, you have not authorized a connector yet.
- For Notion, also set
notionParentPageUrlto the page where items should be created.
The connection is mediated by Apify's MCP proxy, so this actor never sees your third-party credentials. Leave the field empty to skip.
Input Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
mode | string | search | search (keyword/category/filters) or url (paste product or listing links). |
zipCode | string | 50667 | German postal code REWE uses to match your local market. Required. Scopes prices, offers and which products the market stocks. |
searchTerm | string | none (prefill: milch) | Free-text keyword. Search mode only; leave empty to browse a category instead. |
categorySlug | string | none | REWE's own category token, e.g. milch. Search mode only; URL mode reads this from the pasted link. |
urls | array | none (prefill: one sample product URL) | Product or listing URLs to scrape. URL mode only. |
brand | string | none | Exact brand name to keep, matched as REWE's own brand filter shows it. Applies in search mode and to pasted listing links in URL mode; a single pasted product link is not filtered by it. |
attribute | string | none (All products) | ORGANIC, VEGAN, REGIONAL, NEW, CHILLED, or FROZEN, REWE's own single-select dietary/sourcing quick filter. Applies in search mode and to pasted listing links in URL mode; a single pasted product link is not filtered by it. |
minPrice | number | none | Minimum EUR price to keep. REWE offers no price filter of its own, so this narrows the actor's own results; see "How price filtering is bounded" above. Applies in both search mode and URL mode. |
maxPrice | number | none | Maximum EUR price to keep. REWE offers no price filter of its own, so this narrows the actor's own results; see "How price filtering is bounded" above. Applies in both search mode and URL mode. |
fetchDetails | boolean | false | Adds description and ingredient statement from the product detail page. Price, brand, category and images are already included without this. |
maxPages | integer | none (no page limit) | Cap on result pages per search/URL entry. Leave empty for no page limit; the run still stops at Max products and the guards described above. |
maxItems | integer | 20 | Hard cap on total products returned across every search/URL entry. 0 = unlimited (still bounded by Max pages). |
resumeFromRunId | string | none | ID of a previous run or dataset of this actor. Already-collected products are skipped, so this run returns only the remaining delta. |
incrementalMode | boolean | false | Recurring monitoring of the same search. See "Resume and recurring updates" above for exactly what is returned by default. |
stateKey | string | none | Name for an incremental-mode monitoring campaign. Leave empty to derive one automatically from mode/postal code/search/filter settings. |
emitUnchanged | boolean | false | Incremental mode only. Also return (and bill) products unchanged since the last run. |
emitExpired | boolean | false | Incremental mode only. Also return (and bill) products no longer found, once a run fully scans the tracked search. |
proxy | object | residential, country DE | Connection settings. The default already selects a residential connection in Germany. |
mcpConnectors | array | none | Optional MCP connectors to export results into (Notion, Linear, Airtable, Apify). |
notionParentPageUrl | string | none | Notion connector only: page under which item pages are created. |
maxNotifyListings | integer | 50 | Cap on items exported to each connector per run. Does not affect the dataset. |
Output Example
{"productId": "677067","name": "Sample Fresh Whole Milk 3.5% 1l","brand": "Sample Dairy","tags": ["Gekühlt", "Regional"],"url": "https://www.rewe.de/p/sample-fresh-whole-milk-3-5-1l/677067","hasVariants": false,"freeShipping": false,"categoryId": "175","category": "Frischmilch","categoryPath": ["Kühlregal", "Milchprodukte", "Frischmilch"],"image": "https://img.rewe-static.de/sample/digital-image.png","images": ["https://img.rewe-static.de/sample/digital-image.png"],"price": 1.29,"currency": "EUR","originalPrice": 1.59,"discountAmount": 0.3,"discountPercent": 19,"isOnSpecial": true,"pricePerUnit": "1.29 EUR / l","grammage": "1l","available": true,"offerValidTo": "2026-10-05T23:59:59Z","merchant": "REWE","gtin": "4008400205746"}
Sample shape: values above are illustrative placeholders, not from a live product.
Plan Requirement
This site needs a residential connection for a reliable run; a datacenter connection is likely to fail most requests. The default proxy configuration already selects a residential connection in Germany, so most runs need no changes. For large or frequent runs, confirm your plan includes residential proxy access.
FAQ
How much does it cost?
You pay per product returned, plus an optional detail-enrichment surcharge only for products where Fetch product detail is on and the detail page was actually fetched for a product that reached the dataset. The Pricing tab shows current rates. Use Max products to cap the cost of any run.
Is it legal to scrape REWE?
This actor collects only publicly available product and pricing data. You are responsible for how you use it: follow REWE's terms and the laws that apply to you, and get legal advice if you plan commercial redistribution. Product names, prices and descriptions are generally facts, but images and brand names may be subject to third-party rights.
Can I get only new or changed products on a schedule?
Yes. Schedule the actor from the Schedules tab and turn on Incremental mode. By default a scheduled run then returns only NEW and UPDATED products; unchanged ones are suppressed and not billed. EXPIRED rows appear only on a run that has emitExpired on and fully scans the search; REAPPEARED only appears on a later run, after such a run has already marked a product expired; see "Resume and recurring updates" above.
Why did my run return fewer products than I expected?
Two independent reasons: Max products or Max pages capped the run intentionally, or a tight price band ran into the 5-consecutive-barren-page rule described above (REWE has no price filter of its own, so this actor's own narrowing can stop early rather than paging the whole catalog). Either way, more matches may exist; raise the caps or widen the price band to see more.
Why did my run fail instead of returning an empty dataset?
The most common cause is a postal code with no matching REWE market: the site's own postal-code service is checked up front, before anything is scraped or billed, and the run stops with a clear message rather than returning a dataset full of null prices. A genuinely empty search (no products match your keyword, category or filters) still succeeds, it just returns nothing to charge for.
Can I use it with AI agents or MCP?
Yes. Call it from any Apify integration or MCP client, and use the connector field to push results into Notion, Linear or Airtable.
🔗 Want more grocery data?
Pair this actor with these related scrapers from the same team:
| 🥦 Kaufland.de Scraper Scrape Kaufland.de, Germany's hypermarket and online marketplace: keyword/category/brand... | 🚗 mobile.de From $0.8/1K. Scrape mobile.de vehicle listings with 30+ structured fields including... |
| 🥦 Mercadona Scraper Scrape Mercadona products by delivery-area postal code. Search by keyword or category, or... | 🥦 Auchan France Scraper Scrape Auchan.fr products: grocery, drinks, household and general merchandise. Real price... |
| 🥦 E.Leclerc Scraper Scrape E.Leclerc France (e.leclerc) grocery and retail products. Search by keyword or... | 🥦 Instacart Scraper Scrape Instacart grocery catalogs with per-store prices. Run keywords across several... |
💬 Support & custom scrapers
- 🐞 Found a bug or a missing field? Open a ticket on the Issues tab. We usually reply within hours.
- 🛠️ Need another site, extra fields or a private build? Email abotapi@proton.me or message Telegram @abotapi.
- ⭐ Enjoying it? A quick review on the actor page helps other users find it.