# EU Omnibus Discount Checker — 30-Day Lowest Price Audit (`kondasviktor/eu-omnibus-discount-checker`) Actor

Check EU shop discounts against the legally required 30-day lowest price. One verdict per product: compliant, overstated or missing label. 10 languages, no price history needed.

- **URL**: https://apify.com/kondasviktor/eu-omnibus-discount-checker.md
- **Developed by:** [Viktor Kondas](https://apify.com/kondasviktor) (community)
- **Categories:** E-commerce, Automation, AI
- **Features:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $6.00 / 1,000 product checkeds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

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

## EU Omnibus Discount Checker — 30-Day Lowest Price Audit

**Check whether an EU shop's discount is real.** Paste product URLs and get one verdict per product — compliant, overstated, or missing the legally required 30-day lowest price — with the evidence text from the page. JSON, CSV or Excel, via API, schedules, n8n, Make, Zapier and AI agents (MCP). **$0.006 per product checked**, no subscription.

> Independent tool. Not legal advice. Reads publicly visible product pages only — no login, no personal data.

### What does EU Omnibus Discount Checker do?

- Reads the **current price, the "was" price, the % badge and the 30-day lowest price label** from an EU product page.
- Calculates the **real discount against the 30-day lowest price** — the reference EU law requires — and compares it to what the shop claims.
- Recognises the label wording in **10 languages plus English** (HU, DE, PL, CZ, SK, RO, FR, IT, ES, NL, EN) and handles local price formats (1 299 Ft, 1.299,00 €, 24 990 Kč).
- Needs **no price history** — it reads the label shops are obliged to display, so the first run already gives answers.

### Who is it for?

| You are… | You use it to… |
|---|---|
| Deal site or affiliate publisher | Verify discounts before publishing them |
| E-commerce pricing / compliance manager | Audit your own promo pages before a campaign goes live |
| Competitive-intelligence analyst | Compare competitors' claimed vs real discounts every week |
| Journalist or consumer organisation | Sample hundreds of Black Friday deals in minutes |

### Ready-made examples (one click)

| Example | What you get |
|---|---|
| [Audit Black Friday discounts on German shops](https://apify.com/kondasviktor/eu-omnibus-discount-checker/examples/audit-black-friday-discounts-germany) | Verdict per product for major German retailers |
| [Check fake discounts on Hungarian webshops](https://apify.com/kondasviktor/eu-omnibus-discount-checker/examples/check-fake-discounts-hungary) | Hungarian shops, HUF prices, Hungarian labels |
| [Audit Polish e-commerce promotions for Omnibus compliance](https://apify.com/kondasviktor/eu-omnibus-discount-checker/examples/poland-omnibus-price-audit) | Polish shops, PLN, "najniższa cena z 30 dni" |
| [Verify deal discounts before you publish them](https://apify.com/kondasviktor/eu-omnibus-discount-checker/examples/verify-deals-before-publishing) | Mixed EU shops, plain-language explanations |
| [Monitor competitor discount claims weekly](https://apify.com/kondasviktor/eu-omnibus-discount-checker/examples/monitor-competitor-discount-claims) | Schedule-ready competitor watchlist |

### How to use it

1. Paste product page URLs (or open an example above).
2. Set **Max products** — this is also your cost cap.
3. Click **Start**. Filter the dataset by `verdict` or download it.

### Input

| Field | Required | Description |
|---|---|---|
| `productUrls` | yes | Product pages (not category pages) |
| `maxProducts` | no | Cap on products and cost. Default 100 |
| `renderMode` | no | `auto` (default) tries fast HTML first, then a real browser if no price is readable. `html` never uses a browser, `browser` always does |
| `tolerancePct` | no | Allowed rounding gap in percentage points. Default 1 |
| `includeEvidenceScreenshot` | no | Save a full-page screenshot as evidence ($0.01 each). Pages are rendered in the browser |
| `countryOverride` | no | Force a country if auto-detection is wrong |
| `proxyConfiguration` | no | Apify Proxy by default; use residential proxies in the shop's country for big shops |

### Output

```json
{
  "productUrl": "https://shop.example.hu/product/123",
  "domain": "shop.example.hu",
  "country": "HU",
  "currency": "HUF",
  "productName": "Wireless headphones X",
  "currentPrice": 34990,
  "referencePrice": 49990,
  "referenceType": "strikethrough",
  "lowest30dPrice": 36990,
  "lowest30dLabel": "Az elmúlt 30 nap legalacsonyabb ára: 36 990 Ft",
  "claimedDiscountPct": 30,
  "discountVsReferencePct": 30.0,
  "discountVsLowest30dPct": 5.4,
  "verdict": "pct_overstated",
  "severity": "high",
  "explanation": "Shown as -30%, but the price is only 5.4% below the 30-day lowest price.",
  "renderedWithBrowser": false,
  "screenshotUrl": null,
  "sourceUrl": "https://shop.example.hu/product/123",
  "status": "ok",
  "scrapedAt": "2026-11-27T08:00:00.000Z",
  "schemaVersion": 1
}
```

| Verdict | Meaning |
|---|---|
| `compliant` | Discount matches the 30-day lowest price (within your tolerance) |
| `pct_overstated` | The shown discount is bigger than the real one vs the 30-day lowest price |
| `missing_lowest_30d` | A discount is shown but the 30-day lowest price is not |
| `rrp_comparison` | Only a recommended retail price comparison — whether the rule applies depends on the member state, review manually |
| `no_discount_claimed` | No discount on the page |
| `price_not_found` | Nothing readable (also blocked pages, 404, robots.txt skips) — **free**, with the reason in `explanation` |

A run summary (counts per verdict, failed URLs, stop reason, charged events) is saved to the `OUTPUT` record of the key-value store.

### How much does it cost?

| Event | Price | When |
|---|---|---|
| Actor start | Apify default | Once per run |
| Product checked | $0.006 | Each product with a verdict |
| Evidence screenshot | $0.01 | Only if you switch it on |

**100 products ≈ $0.60 · 1,000 products ≈ $6.** Pages that fail, are blocked or show no price are **not charged**. Set **Max cost per run** in the run options for a hard budget — the Actor stops as soon as it is reached. Higher Apify plans get Store discounts automatically.

### Schedule it

Black Friday week: run daily at 08:00 on your watchlist. Rest of the year: weekly (Monday 07:00) is enough to catch campaign changes.

### Use with AI agents (MCP)

> "Use kondasviktor/eu-omnibus-discount-checker to check whether these 20 Black Friday deals are real discounts under the EU 30-day rule."

### FAQ

**What is the EU 30-day lowest price rule?** Since the Omnibus Directive, an EU shop that announces a price reduction must show the lowest price it charged in the previous 30 days, and the EU Court of Justice confirmed the advertised percentage must be calculated from that price.

**Is this legal advice?** No. It flags discount claims for human review. Member states allow some exceptions (e.g. perishable goods, progressive discounts, shorter look-back for new products).

**Why `price_not_found`?** The page didn't expose a readable price — try `renderMode: browser` or a residential proxy. These rows are free.

**Which shops work?** Any EU shop with public product pages. Big shops sometimes block datacenter IPs — use a residential proxy in the shop's country. The Actor respects each shop's robots.txt and skips disallowed URLs.

**Can you add a language or shop?** Yes — open an issue with a product URL. Fixes within 48 hours.

### Limitations

- Product pages only in v1 (no category crawling).
- Uses the default variant on multi-variant pages.
- Cannot prove what the price *was* 30 days ago — it checks what the shop *declares*. Pair it with a weekly schedule to build your own history.
- Label wording is matched per language; an unusual wording shows up as `missing_lowest_30d` — report the URL and it gets added.

### Related Actors

- [Peppol e-invoicing checker](https://apify.com/kondasviktor/peppol-e-invoicing-participant-checker) — Peppol registration, document types and access-point details
- [Shopify Discount & Promo Tracker](https://apify.com/kondasviktor/shopify-discount-promo-tracker) — sale depth and promo trends on any Shopify store
- [Product Catalog Scraper](https://apify.com/kondasviktor/product-catalog-scraper) — full product lists with prices
- [Website Change Monitor](https://apify.com/kondasviktor/website-change-monitor) — watch promo / PDP pages after an audit
- [OpenAI Ads Check & Convert](https://apify.com/kondasviktor/openai-ads-check-convert) — get your shop's products ready for ChatGPT ads

[All Actors](https://apify.com/kondasviktor)

***

Built by [Viktor Kondas](https://apify.com/kondasviktor) · [Vibe Coder's Life](https://vibecoderslife.com/?utm_source=apify\&utm_medium=readme\&utm_campaign=eu-omnibus-discount-checker) · Custom audits: hello@vibecoderslife.com

# Actor input Schema

## `productUrls` (type: `array`):

Product detail pages (not category pages) of EU online shops. Each product with a verdict is one paid `product-checked` event. Replace the prefill with 3 live discounted product pages before publishing.

## `maxProducts` (type: `integer`):

Hard cap on checked products — also your cost cap (100 products = $0.60). Pages without a readable price are free and do not count.

## `renderMode` (type: `string`):

`auto` reads fast HTML first and opens a real browser only for pages without a readable price. `html` never uses a browser. `browser` always uses one (slower, works on JavaScript-only shops).

## `tolerancePct` (type: `number`):

How far the advertised discount may exceed the discount measured from the 30-day lowest price before it is flagged `pct_overstated`. 1 = one percentage point.

## `includeEvidenceScreenshot` (type: `boolean`):

Save a full-page PNG of each checked product to the key-value store ($0.01 each, extra event `evidence-screenshot`). Requires a real browser, so every page is rendered in the browser.

## `countryOverride` (type: `string`):

Force the shop's country if auto-detection (domain, page language, currency) is wrong.

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

Residential proxy in the shop's country is required for most fashion / marketplace PDPs. Datacenter IPs are blocked by about half of big EU shops.

## Actor input object example

```json
{
  "productUrls": [
    {
      "url": "https://www.ikea.com/de/de/p/hektogram-deckenfluter-silberfarben-weiss-40477726/"
    },
    {
      "url": "https://www.ikea.com/de/de/p/lauters-standleuchte-esche-weiss-30405042/"
    },
    {
      "url": "https://www.ikea.com/de/de/p/ikea-ps-2026-deckenfluter-blau-50608519/"
    }
  ],
  "maxProducts": 3,
  "renderMode": "auto",
  "tolerancePct": 1,
  "includeEvidenceScreenshot": false,
  "countryOverride": "auto",
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}
```

# Actor output Schema

## `dataset` (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 = {
    "productUrls": [
        {
            "url": "https://www.ikea.com/de/de/p/hektogram-deckenfluter-silberfarben-weiss-40477726/"
        },
        {
            "url": "https://www.ikea.com/de/de/p/lauters-standleuchte-esche-weiss-30405042/"
        },
        {
            "url": "https://www.ikea.com/de/de/p/ikea-ps-2026-deckenfluter-blau-50608519/"
        }
    ],
    "maxProducts": 3,
    "renderMode": "auto",
    "tolerancePct": 1,
    "includeEvidenceScreenshot": false,
    "countryOverride": "auto",
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ]
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("kondasviktor/eu-omnibus-discount-checker").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 = {
    "productUrls": [
        { "url": "https://www.ikea.com/de/de/p/hektogram-deckenfluter-silberfarben-weiss-40477726/" },
        { "url": "https://www.ikea.com/de/de/p/lauters-standleuchte-esche-weiss-30405042/" },
        { "url": "https://www.ikea.com/de/de/p/ikea-ps-2026-deckenfluter-blau-50608519/" },
    ],
    "maxProducts": 3,
    "renderMode": "auto",
    "tolerancePct": 1,
    "includeEvidenceScreenshot": False,
    "countryOverride": "auto",
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
    },
}

# Run the Actor and wait for it to finish
run = client.actor("kondasviktor/eu-omnibus-discount-checker").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 '{
  "productUrls": [
    {
      "url": "https://www.ikea.com/de/de/p/hektogram-deckenfluter-silberfarben-weiss-40477726/"
    },
    {
      "url": "https://www.ikea.com/de/de/p/lauters-standleuchte-esche-weiss-30405042/"
    },
    {
      "url": "https://www.ikea.com/de/de/p/ikea-ps-2026-deckenfluter-blau-50608519/"
    }
  ],
  "maxProducts": 3,
  "renderMode": "auto",
  "tolerancePct": 1,
  "includeEvidenceScreenshot": false,
  "countryOverride": "auto",
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}' |
apify call kondasviktor/eu-omnibus-discount-checker --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,kondasviktor/eu-omnibus-discount-checker"
        }
    }
}
```

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/ZSEtE4ejFeqo0K0D2/builds/y4tvf6mWKgXmxyPbk/openapi.json
