REWE APIshop.rewe.de ↗
Search REWE's online grocery catalog by product name and German postal code. Returns prices, GTINs, discount status, grammage, and pagination for any PLZ.
What is the REWE API?
The REWE shop API exposes 1 endpoint — search_products — that queries REWE's online grocery catalog and returns up to 9 fields per product including price in EUR, GTIN/EAN, discount status, and grammage. Prices are resolved to the nearest REWE market for a given 5-digit German postal code, so results reflect actual local availability rather than a national average.
curl -X GET 'https://api.parse.bot/scraper/1ccc94cf-cbaf-4412-b95f-f4ac4a0dc490/search_products?page=1&query=Milch&per_page=5&postal_code=51063' \ -H 'X-API-Key: $PARSE_API_KEY'
Typed, relational, agent-ready
A generated client with real types, enums, and the links between objects — the structure a flat JSON response can't carry. Autocompletes in your editor and reads cleanly to coding agents.
- Fully typed · autocompletes
- Objects link to objects
- Typed errors & pagination
Typed Python client. Set up the SDK in your uv project, then pull this API’s typed client:
uv add parse-sdk uv run parse init uv run parse add --marketplace shop-rewe-de-api
uv run parse add --marketplace pulls a pinned snapshot of this canonical API — it won’t change underneath you. To customize it, subscribe and swap to your own copy.
"""Walkthrough: REWE Online Shop API — search grocery products by postal code."""
from parse_apis.shop_rewe_de_api import Rewe, MarketNotFound
client = Rewe()
# Search for milk products near Köln (51063), capped at 5 results.
for product in client.products.search(query="Milch", postal_code="51063", limit=5):
print(product.name, product.price_eur, product.grammage, product.is_discounted)
# Drill into the first result for a different search.
item = client.products.search(query="Bio Joghurt", postal_code="10115", limit=1).first()
if item:
print(item.product_id, item.gtin, item.name, item.price_eur)
print(item.product_url, item.image_url)
# Handle the case where a postal code has no REWE market.
try:
result = client.products.search(query="Brot", postal_code="00000", limit=1).first()
except MarketNotFound as exc:
print(f"No market for postal code: {exc.postal_code}")
print("exercised: products.search / MarketNotFound error handling")
Search REWE online grocery products by name within a specific German postal code area. Prices are specific to the nearest market serving the given postal code. Results are paginated and include product details such as GTIN/EAN, current price in EUR, discount status, grammage, and image URLs.
| Param | Type | Description |
|---|---|---|
| page | integer | Page number for pagination. |
| queryrequired | string | Product search term (e.g. 'Milch', 'Bio Joghurt', 'Nutella'). |
| per_page | integer | Number of products per page. Maximum observed: 40. |
| postal_coderequired | string | 5-digit German postal code (PLZ). Determines which market's prices and availability are returned. |
{
"type": "object",
"fields": {
"page": "integer",
"per_page": "integer",
"products": "array of product objects with product_id, gtin, name, price_eur, is_discounted, discount_valid_to, grammage, image_url, product_url, market_id, postal_code",
"total_pages": "integer",
"total_results": "integer"
},
"sample": {
"data": {
"page": 1,
"per_page": 5,
"products": [
{
"gtin": "4045317058067",
"name": "Bärenmarke Die Alpenfrische Vollmilch 1l",
"grammage": "1l",
"image_url": "https://img.rewe-static.de/1252410/25380943_digital-image.png",
"market_id": "240574",
"price_eur": 1.79,
"product_id": "1252410",
"postal_code": "51063",
"product_url": "https://www.rewe.de/p/baerenmarke-die-alpenfrische-vollmilch-1l/1252410",
"is_discounted": false,
"discount_valid_to": null
}
],
"total_pages": 70,
"total_results": 346
},
"status": "success"
}
}About the REWE API
What the API Returns
The search_products endpoint accepts a query string (e.g. 'Milch', 'Bio Joghurt', 'Nutella') and a postal_code to return a paginated list of matching grocery products from REWE's online catalog. Each product object includes product_id, gtin (the EAN barcode), name, price_eur, is_discounted, discount_valid_to, grammage, image_url, and product_url. The gtin field is useful for cross-referencing products with nutritional databases or other retail sources.
Postal Code Pricing
The postal_code parameter is required and drives which market's inventory and pricing are returned. A search for the same product with two different postal codes can yield different price_eur values or availability. This makes the API suitable for geographic price comparison across German regions. The postal_code must be a valid 5-digit German PLZ (Postleitzahl).
Pagination
Results are paginated. The response includes page, per_page, total_pages, and total_results fields so you can iterate through large result sets. The per_page parameter accepts up to 40 products per page. For queries that match many products, walking page from 1 through total_pages gives complete coverage of the result set.
The REWE API is a managed, monitored endpoint for shop.rewe.de — not a raw scraper you maintain. Every endpoint is automatically health-checked on a schedule, and when shop.rewe.de changes and a check fails, the API is automatically queued for repair and re-verified. It is built to keep working as the site underneath it changes.
This isn't an official shop.rewe.de API — it's an independent, maintained REST wrapper over public data. Where the source has no official API (or only a limited one), Parse gives you a stable contract over a source that never promised one, and keeps it current. Need a new endpoint or field? You can revise it yourself in plain English and the agent rebuilds it against the live site in minutes — contributing the change back to the shared API is free.
Will this API break when the source site changes?+
Is this an official API from the source site?+
Can I fix or extend this API myself if I need a new endpoint or field?+
What happens if I call an endpoint that has an issue?+
- Build a grocery price tracker that monitors
price_eurchanges for specific GTINs across multiple postal codes over time. - Compare REWE shelf prices for a shopping basket across different German cities by varying the
postal_codeparameter. - Identify currently discounted products by filtering results where
is_discountedis true and noting thediscount_valid_todate. - Populate a recipe cost estimator by searching for ingredients and summing their
price_eurvalues for a given PLZ. - Cross-reference REWE product data with nutritional or sustainability databases using the
gtinEAN field. - Build a regional price index for a category (e.g. dairy) by querying a broad term and collecting
price_euracross several postal codes.
| Tier | Price | Credits/month | Rate limit |
|---|---|---|---|
| Free | $0/mo | 100 | 5 req/min |
| Hobby | $30/mo | 1,000 | 20 req/min |
| Developer | $100/mo | 5,000 | 100 req/min |
One credit = one API call regardless of which marketplace API you call. Exceeding the rate limit returns a 429 response. Authenticate with the X-API-Key header.
Does REWE have an official public developer API?+
What does the search_products endpoint return for a discounted product?+
is_discounted is set to true and discount_valid_to carries the expiry date of the promotion. The price_eur field reflects the current (discounted) price rather than the original price, so you cannot retrieve the pre-discount price from this endpoint.Does the API cover product reviews, nutritional information, or ingredient lists?+
Can I retrieve products for a specific store ID rather than a postal code?+
postal_code only; there is no parameter to target a store by its internal ID. If multiple REWE markets serve the same PLZ, the nearest one is used. You can fork this API on Parse and revise it to add store-level selection if you need finer geographic control.Is there a limit on how many results I can retrieve per query?+
per_page parameter supports a maximum of 40 products per page. To retrieve more results, increment the page parameter up to the value of total_pages returned in the first response. total_results tells you the full match count for the query.