Discover/Penny API
live

Penny APIPenny.de ↗

Access Penny.de weekly promotional offers and store locations via two endpoints. Filter by selling region, category, and week. Returns prices, discounts, and store geodata.

Endpoint health
verified 4h ago
list_weekly_offers
search_markets
2/2 passing latest checkself-healing
Endpoints
2
Updated
5h ago

What is the Penny API?

The Penny.de API exposes 2 endpoints covering Germany's PENNY supermarket chain: current and upcoming weekly promotional offers (Angebote) with shelf prices, UVP comparisons, discount percentages, and app-exclusive pricing — plus a store directory endpoint (search_markets) that finds PENNY locations by postal code or city and returns the selling region codes needed to pull region-specific offers.

This call costs10 credits / call— charged only on success
Try it
Which offer week to read.
Offer category slug as emitted in categories[*].category (one shape: top-angebote). Omitted = all categories of the week.
Selling region code of a store, from search_markets.markets[*].selling_region. Omitted = nationwide offers only.
→ api.parse.bot/scraper/fc539534-08a8-4ad5-97a7-ad870ad270c1/<endpoint>
Ready to send
Fill in the parameters and hit sign in to send to see live response data here.
Call it over HTTPgrab a free API key at signup
curl -X GET 'https://api.parse.bot/scraper/fc539534-08a8-4ad5-97a7-ad870ad270c1/list_weekly_offers?week=current&category=top-angebote' \
  -H 'X-API-Key: $PARSE_API_KEY'
Python SDK · recommended

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 penny-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: PENNY weekly offers – find a store, then browse its regional deals."""
from parse_apis.penny_de_api import Penny, Week, InputNotFound

client = Penny()

# Find the nearest PENNY store by postal code.
market = client.markets.search(zip_code="10115", limit=5).first()
if market is not None:
    print(market.name, market.street, market.city)
    print("Opening hours:", market.opening_hours)
    print("Selling region:", market.selling_region)

    # Fetch this week's offers for that store's selling region.
    week = client.offer_weeks.get(
        week=Week.CURRENT,
        selling_region=market.selling_region,
    )
    print(f"\nWeek {week.week_id} — {week.total_offers} offers")

    # Walk the offer categories returned alongside the offers.
    if week.categories:
        for cat in week.categories:
            print(f"  {cat.title} ({cat.offer_count} offers, {cat.period})")

    # Show some offers with prices.
    if week.offers:
        for offer in week.offers[:5]:
            savings = f" (was {offer.regular_price})" if offer.regular_price else ""
            print(f"  {offer.title}: €{offer.price}{savings} — {offer.quantity}")

# Point lookup that may fail: a non-existent category.
try:
    client.offer_weeks.get(category="does-not-exist")
except InputNotFound:
    print("\nCategory not found — handled gracefully.")

print("\nexercised: markets.search / offer_weeks.get / InputNotFound")
All endpoints · 2 totalmissing one? ·

Returns the weekly promotional offers published on penny.de for the current or the next week. One row per offer tile, carrying the shelf price, the regular/UVP price it is compared against, the discount percentage, the PENNY-app-only price where one exists, pack size, unit price text, offer category and validity period (e.g. Mo-Sa, Do-Sa, Fr-Sa). Without a category the endpoint walks every offer category of the week (about 25 upstream requests, roughly 200 offers); with a category it is a single cheap call. Category slugs and their human titles are listed in the categories array of a full-week call; the set changes from week to week, so an unknown slug returns a stale_input (input_not_found) error. Passing a selling_region (from search_markets) adds the region-specific offers of that store region on top of the nationwide ones. The next week is only published by the site from Friday onward; before that week=next returns week_available=false with empty arrays (the data branch for week=next was not observed during the build). Prices are EUR as numbers; unit-price texts (base_price, app_base_price) are kept as the site prints them. lowest_price_30_days was null on every offer observed.

Input
ParamTypeDescription
weekstringWhich offer week to read.
categorystringOffer category slug as emitted in categories[*].category (one shape: top-angebote). Omitted = all categories of the week.
selling_regionstringSelling region code of a store, from search_markets.markets[*].selling_region. Omitted = nationwide offers only.
Response
{
  "type": "object",
  "fields": {
    "week": "requested week selector (current|next)",
    "offers": "array of offers: offer_id, title, slug, category, period, quantity, price, regular_price, regular_price_type (uvp|previous|striketrough|null), discount_percent, base_price text, app_price, app_discount_percent, app_base_price text, action_price, bargain_price, lowest_price_30_days, promotion, product_type, tile_type, image_url, url",
    "week_id": "site's ISO week id of that week, e.g. 2026-41",
    "categories": "array of offer categories fetched: category slug, title, product_type (food|nonfood|null), period (validity days label), offer_count",
    "total_offers": "number of offers returned",
    "selling_region": "echo of the region filter or null",
    "week_available": "false when the site has not published that week's categories yet",
    "failed_categories": "array of categories whose upstream call failed, with status_code"
  },
  "sample": {
    "data": {
      "week": "current",
      "offers": [
        {
          "url": "https://www.penny.de/angebote/top-angebote/red-bull-energy-drink",
          "slug": "red-bull-energy-drink",
          "price": 0.99,
          "title": "RED BULL Energy-Drink*",
          "period": "Mo-Sa",
          "category": "top-angebote",
          "offer_id": "322b3a83-659a-4156-8b7b-83ada0379292",
          "quantity": "je 250 ml",
          "app_price": 0.85,
          "image_url": "https://cdn.penny.de/dam/jcr:a06ab81f-3df6-44c4-a8a5-8c07a4f3bc00/55748200.png?impolicy=penny&imwidth=600",
          "promotion": "reduzierter Preis",
          "tile_type": "promoPlus",
          "base_price": "(1 l = 3.96)",
          "action_price": false,
          "product_type": "food",
          "bargain_price": false,
          "regular_price": 1.49,
          "app_base_price": "(1 l = 3.40)",
          "discount_percent": 33,
          "regular_price_type": "uvp",
          "app_discount_percent": 42,
          "lowest_price_30_days": null
        },
        {
          "url": "https://www.penny.de/angebote/top-angebote/helle-kernlose-tafeltrauben",
          "slug": "helle-kernlose-tafeltrauben",
          "price": 2.99,
          "title": "Helle, kernlose Tafeltrauben*",
          "period": "Mo-Sa",
          "category": "top-angebote",
          "offer_id": "ac7ffe81-dd23-4d2d-b54b-992db2cbea60",
          "quantity": "je kg",
          "app_price": null,
          "image_url": "https://cdn.penny.de/dam/jcr:013d9158-26c7-48a0-ad96-368e6bdae41d/45086880.png?impolicy=penny&imwidth=600",
          "promotion": "normaler Preis",
          "tile_type": "offer",
          "base_price": null,
          "action_price": true,
          "product_type": "food",
          "bargain_price": false,
          "regular_price": null,
          "app_base_price": null,
          "discount_percent": null,
          "regular_price_type": null,
          "app_discount_percent": null,
          "lowest_price_30_days": null
        }
      ],
      "week_id": "2026-41",
      "categories": [
        {
          "title": "Top Angebote",
          "period": "Mo-Sa",
          "category": "top-angebote",
          "offer_count": 6,
          "product_type": "food"
        }
      ],
      "total_offers": 6,
      "selling_region": null,
      "week_available": true,
      "failed_categories": []
    },
    "status": "success"
  }
}

About the Penny API

Weekly Promotional Offers

The list_weekly_offers endpoint returns all offer tiles published on penny.de for either the current or the next week. Each offer object includes offer_id, title, slug, category, price, regular_price, regular_price_type (distinguishing UVP, previous price, or strikethrough), quantity, and a discount_percentage. Where PENNY publishes an app-exclusive price for an item, that field is present in the offer object. The response also surfaces week_id (an ISO week string such as 2026-41), a categories array with per-category product_type (food, nonfood, or null) and offer_count, and a failed_categories list so callers can detect partial responses.

Filtering Offers by Region and Category

By default, list_weekly_offers returns nationwide offers only. Pass a selling_region code (obtained from search_markets) to include region-specific promotions. Pass a category slug — matching values emitted in categories[*].category, for example top-angebote — to narrow the result set. If the site has not published the requested week yet, week_available is returned as false rather than an error, so callers can check before rendering.

Store Search and Selling Regions

The search_markets endpoint accepts a zip_code (3–5 leading digits, with leading zeros preserved) and/or a city substring. It returns up to 200 matching stores, each with market_id, name, street, zip_code, city, state, latitude, longitude, selling_region, next_week_selling_region, and opening_hours. The selling_region and next_week_selling_region fields feed directly into the selling_region parameter of list_weekly_offers, letting you retrieve the exact offer set a given store's customers see.

Reliability & maintenanceVerified

The Penny API is a managed, monitored endpoint for Penny.de — not a raw scraper you maintain. Every endpoint is automatically health-checked on a schedule, and when Penny.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 Penny.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.

Last verified
4h ago
Latest check
2/2 endpoints passing
Maintenance
Monitored & self-healing
Will this API break when the source site changes?+
It's built not to. Every endpoint is health-checked on a schedule with automated test probes. When the source site changes and a check fails, the API is automatically queued for repair and re-verified — that's the self-healing layer. Each API page shows when its endpoints were last verified. And because marketplace APIs are shared, any fix reaches everyone using it.
Is this an official API from the source site?+
No — Parse APIs are independent, managed REST wrappers over publicly available data. That is the point: where a site has no official API (or only a limited one), Parse gives you a maintained, monitored endpoint for that data and keeps it working as the site changes — so you get a stable contract over a source that never promised one.
Can I fix or extend this API myself if I need a new endpoint or field?+
Yes — and you don't have to wait on us. This API was generated by the Parse agent, which stays attached. Describe the change in plain English ("add an endpoint that returns reviews", "fix the price field") in the revise box on the API page or via the revise_api MCP tool, and the agent rebuilds it against the live site in minutes. Contributing the change back to the public API is free.
What happens if I call an endpoint that has an issue?+
Errors are machine-readable: a bad call returns a clean status with the list of available endpoints and a repair hint, so an agent (or you) can recover or trigger a fix instead of failing silently. Confirmed failures feed the automatic repair queue.
Common use cases
  • Build a weekly grocery deal tracker that surfaces the lowest-priced food items from PENNY's current Angebote by category.
  • Compare PENNY's UVP-referenced prices against regular_price to identify items with the largest nominal discounts.
  • Resolve a user's postal code to a nearby store's selling_region, then fetch region-specific offers tailored to that store.
  • Detect PENNY app-exclusive prices and alert users who have the app about additional savings on specific offer tiles.
  • Monitor week_available on the next week to know the exact moment new weekly promotions go live.
  • Aggregate store geodata (latitude, longitude) to plot all PENNY locations within a city for a store-finder feature.
  • Track week-over-week changes in discount_percentage and price for specific product categories like top-angebote.
Pricing & limitsSee full pricing →
TierPriceCredits/monthRate limit
Free$0/mo2005 req/min
Hobby$30/mo1,00020 req/min
Developer$100/mo5,000100 req/min
Team$300/mo20,000300 req/min
Company$1,000/mo100,000500 req/min

Each endpoint has a fixed posted price per successful call — most fall between 1 and 10 credits — shown on this API's page before you run it. Exceeding the rate limit returns a 429 response. Authenticate with the X-API-Key header.

Frequently asked questions
Does Penny.de have an official developer API?+
Penny.de does not publish a public developer API or API documentation for third-party access to its offers or store data.
What does `regular_price_type` mean in the offers response?+
It indicates what the regular_price is being compared against: uvp means the manufacturer's suggested retail price, previous means the item's own previous shelf price, and strikethrough means a crossed-out price shown on the offer tile. This lets you correctly label the price comparison in your UI.
How do selling regions work, and do all stores share the same offers?+
Not all stores share identical promotions. Each store object from search_markets carries a selling_region and a next_week_selling_region code. Passing one of those codes to list_weekly_offers returns the offer set specific to stores in that region. Without a selling_region filter, the endpoint returns only nationwide offers.
Does the API return historical weekly offers from past weeks?+
No — the API covers the current week and the next upcoming week only. Historical offer archives are not exposed. You can fork this API on Parse and revise it to add an archiving layer that stores weekly snapshots for longitudinal analysis.
Does the API return individual product detail pages or nutritional information?+
No. The API returns offer-tile level data: price, discount, quantity, category, and validity period. Detailed product pages, ingredient lists, and nutritional data are not covered. You can fork this API on Parse and revise it to add an endpoint that fetches individual product detail data using the slug field already present in each offer object.
Page content last updated . Spec covers 2 endpoints from Penny.de.
Related APIs in Food DiningSee all →
kaufland.de API
Search for current deals and discounts at Kaufland Germany stores, viewing detailed pricing information and offer validity periods. Find nearby store locations and browse the latest promotional products all in one place.
aldi.de API
Browse current and upcoming Aldi Nord offers, search products, and discover deals organized by category or date. Access detailed product information, weekly flyers, and explore items across all available categories to find the best bargains.
rewe.de API
Search REWE online shop products with local delivery pricing by German postal code, browse the delivery catalog, and check whether delivery or pickup is available in a given area.
shop.rewe.de API
Search for grocery products across REWE's online catalog and instantly see current prices for your specific German postal code. Find the items you need with real-time pricing information to compare costs and plan your shopping efficiently.
weekly-ad.tonysfreshmarket.com API
Access data from weekly-ad.tonysfreshmarket.com.
lidl.de API
Find the latest weekly promotions and browse Lidl Germany's bestselling products across different categories to discover deals and availability. Search for specific items to quickly locate what you're looking for in Lidl's product catalog.
meijer.com API
Access data from meijer.com.
lidl.nl API
Browse Lidl Netherlands weekly leaflet offers, search the online assortment, fetch detailed product information by ERP/product IDs, and retrieve current bestsellers with pricing and availability.