REWE.de Scraper - Prices, Offers & Postal-Code Matching avatar

REWE.de Scraper - Prices, Offers & Postal-Code Matching

Pricing

from $1.00 / 1,000 product results

Go to Apify Store
REWE.de Scraper - Prices, Offers & Postal-Code Matching

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

Abot API

Maintained by Community

Actor stats

0

Bookmarked

12

Total users

2

Monthly active users

9 days ago

Last modified

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, category, search or listing link. Category and brand accept plain names.
  • 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

FieldExample
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/shop/p/sample-fresh-whole-milk-3-5-1l/677067"
hasVariantsfalse
freeShippingfalse
price / currency1.29 / "EUR"
originalPrice / discountAmount / discountPercent1.59 / 0.3 / 19 (all null off-special)
isOnSpecialtrue
pricePerUnit / grammage"1.29 EUR / l" / "1l"
availabletrue
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 / ingredientsonly 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

  1. Pick a mode: search (keyword and/or category, plus REWE's own brand and dietary/sourcing filters) or url (paste product or listing links).
  2. Set your postal code (PLZ) so prices, offers and the product assortment match the REWE market for that address.
  3. Fill in the fields for your mode, and turn on Fetch product detail if you also want description and ingredients.
  4. 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
}

URL mode shapes. Supported links: a product page (/p/<slug>/<id>), a category page (/shop/c/<slug>/), a search page (/suche/produkte?search=<term>), and listing links with search= or categorySlug=, optionally with page, objectsPerPage (1-100), brand, attribute and sorting (RELEVANCE_DESC, TOPSELLER_DESC, PRICE_ASC, PRICE_DESC, NAME_ASC). Any other link is skipped with a warning, and a link that yields no products is reported in the log. If you leave the URLs field untouched, URL mode scrapes one example of each of these shapes, so clear the list before running it with your own links.

Paste product or listing links, with detail enrichment on:

{
"mode": "url",
"urls": ["https://www.rewe.de/shop/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 ApifyClient
client = 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 as NEW. By default (with emitExpired off), later runs return only NEW and UPDATED products; UNCHANGED products are suppressed and not billed unless emitUnchanged is on. REAPPEARED and EXPIRED are a pair: EXPIRED tombstones are only created when emitExpired is 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 as REAPPEARED once it had previously been tombstoned that way and is then seen again, so if emitExpired has never been turned on for a given search, REAPPEARED will never appear for it either. State is isolated automatically per mode/postal code/search term/category/brand/attribute/price filters/URLs/detail setting, and, once set, per extra keywords, offers-only, available-only, market id and shopping-list product ids (postal code is included because it selects a different REWE market); set stateKey to name or deliberately share a monitoring campaign.

In Incremental mode, a product is UPDATED when its price, was-price, unit price, availability, name, brand, tags or category path change (named in changedFields). Image links and the scrapedAt timestamp never count as a change, nor do fields you list in ignoreFieldsForChanges; they stay in the output. EXPIRED is never produced from a partial scope: a pasted listing URL starting past page 1, or a walk stopped by Max products or Max pages. EXPIRED rows count against Max products.

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.

  1. Authorize a connector once under Apify, Settings, Integrations (Notion, Linear, Airtable, or Apify).
  2. Select it in the "Pipe results into your apps" input field. If the picker is empty, you have not authorized a connector yet.
  3. For Notion, also set notionParentPageUrl to 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

ParameterTypeDefaultDescription
modestringsearchsearch (keyword/category/filters) or url (paste product, category, search or listing links).
zipCodestring50667German postal code REWE uses to match your local market. Required. Scopes prices, offers and which products the market stocks.
searchTermstringnone (prefill: milch)Free-text keyword. Search mode only; leave empty to browse a category instead.
categorySlugstringnoneCategory name or REWE's own token, e.g. Milch or milch; a name matching nothing stops the run with suggestions. Search mode only; URL mode reads this from the pasted link.
urlsarrayone example of each supported shape (also the prefill)Product or listing URLs to scrape. URL mode only. Leaving the field untouched in URL mode scrapes these examples. A link's own brand= or attribute= filter is honoured and wins over the Filters section.
brandstringnoneExact 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 link's own brand= wins); a single pasted product link is not filtered by it.
attributestringnone (All products)ORGANIC, VEGAN, REGIONAL, NEW, CHILLED, FROZEN or HASLOYALTYBONUS, 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.
minPricenumbernoneMinimum 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.
maxPricenumbernoneMaximum 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.
fetchDetailsbooleanfalseAdds description and ingredient statement from the product detail page. Price, brand, category and images are already included without this.
sortBystringRELEVANCE_DESCRELEVANCE_DESC, TOPSELLER_DESC, PRICE_ASC, PRICE_DESC or NAME_ASC, sorted by REWE itself.
campaignsOnlybooleanfalseKeeps only products currently on offer. REWE has no server-side filter for this, so the run reads the normal result pages and drops the rest (bounded by Max pages and the empty-page guard).
inStockOnlybooleanfalseKeeps only products orderable at your market. REWE has no server-side filter for this, so the run reads the normal result pages and drops the rest (bounded by Max pages and the empty-page guard).
marketIdstringnoneExact REWE market id; overrides the postal code.
searchTermsarraynoneExtra keywords searched one after another, in addition to the Search keyword.
productIdsarraynoneShopping list: price exact product ids; rows get quantity and lineTotal (price x quantity).
quantitiesarraynoneQuantity for each id in productIds, in the same order.
compactbooleanfalseCore fields only. Description and ingredients are not part of the compact set, so with Fetch product detail on they are dropped and the detail-enrichment event is not charged for those rows.
excludeEmptyFieldsbooleanfalseDrop empty fields from each row.
descriptionMaxLengthinteger0Truncate the description (Fetch product detail) to this length; 0 = no truncation.
maxPagesintegernone (built-in ceiling of 500 pages)Cap on result pages per search/URL entry. Leave empty for the built-in ceiling of 500 pages per entry; the run also stops at Max products and the guards described above.
maxItemsinteger20Hard cap on total products returned across every search/URL entry. 0 = unlimited (still bounded by Max pages). Values above 1,000,000 are clamped to 1,000,000.
resumeFromRunIdstringnoneID of a previous run or dataset of this actor. Already-collected products are skipped, so this run returns only the remaining delta.
incrementalModebooleanfalseRecurring monitoring of the same search. See "Resume and recurring updates" above for exactly what is returned by default.
stateKeystringnoneName for an incremental-mode monitoring campaign. Leave empty to derive one automatically from mode/postal code/search/filter settings.
emitUnchangedbooleanfalseIncremental mode only. Also return (and bill) products unchanged since the last run.
emitExpiredbooleanfalseIncremental mode only. Also return (and bill) products no longer found, once a run fully scans the tracked search.
ignoreFieldsForChangesarraynoneIncremental mode only. Field names whose changes never make a product UPDATED. Image links and scrapedAt are always ignored.
proxyobjectautomatic poolConnection settings. The default uses the automatic proxy pool; residential access is used as a backup when your plan includes it.
mcpConnectorsarraynoneOptional MCP connectors to export results into (Notion, Linear, Airtable, Apify).
notionParentPageUrlstringnoneNotion connector only: page under which item pages are created.
maxNotifyListingsinteger50Cap 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/shop/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.

Output views

The dataset has four views: Products (overview), Product details (description and ingredients, with Fetch product detail), Changes (incremental) (changeType, changedFields, first and last seen) and Shopping list (quantity and lineTotal when productIds is used). The run also stores a summary under the OUTPUT key.

Plan Requirement

The default connection is the automatic Apify proxy pool, measured to serve REWE's product listings (the JSON catalog that search, category and listing links read), so no residential plan is needed for a normal run. If that connection is refused for your account, the run tries Germany residential access where your plan includes it, then a backup connection. Then the log shows:

The selected connection is unavailable to this run. Apify free plans do not include residential proxies. Continuing on a backup connection; some pages may still be unavailable.

and, once the backup serves pages: "Served over the backup connection (the default connection was unavailable)." If nothing can be read, the run fails with an explicit message instead of an empty dataset: "The proxy connection was refused for this account, so no page could be read" (a paid plan or your own proxy URLs are needed), "No results: residential proxies are unavailable on this run ... and the backup connection could not load the requested REWE pages", or "Could not load any results page (the requests failed) ... This is a connection problem, not an empty search." (only when result pages were actually requested; a run with no keyword/category or no recognised link ends with a plain input message instead) You can also supply your own proxy URLs. See https://apify.com/pricing.

Product detail pages (fetchDetails) are read from REWE's product page. Not every product has a description, and some have no ingredient statement. If product pages stop loading during a run, the run logs one warning and skips detail enrichment for the remaining products.

FAQ

How much does it cost?

You pay a small fixed amount per run start, plus a charge per product returned (dataset item), plus an optional detail-enrichment surcharge only for products where Fetch product detail is on and the product's page delivered a description or an ingredient statement for a product that reached the dataset. Products where REWE's own page has neither are not charged. The detail-enrichment event is charged one unit per product, immediately after that product is written to the dataset, so an interrupted run is only billed for products already delivered. A row whose delivered output carries no description or ingredients (for example with Compact output on) is not charged the event. The Pricing tab shows current rates. Use Max products to cap the cost of any run.

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...
🥦 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...
🥦 Coles AU Scraper
Scrape Coles.com.au grocery products and customer reviews. Search by keyword, browse...
🥦 ResQ Club Scraper
Scrape ResQ Club surplus food offers in Finland, Sweden and Estonia: name, price, current...

👉 Browse all abotapi scrapers

💬 Support

  • 🐞 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 contact@abotapi.com.
  • ⭐ Enjoying it? A quick review on the actor page helps other users find it.