Unit Price Checker for Grocery & Retail Listings avatar

Unit Price Checker for Grocery & Retail Listings

Pricing

from $1.00 / 1,000 results

Go to Apify Store
Unit Price Checker for Grocery & Retail Listings

Unit Price Checker for Grocery & Retail Listings

Check grocery and retail product data for unit price problems: parses sizes like 6 x 330 ml, 12 fl oz or 1.5 kg, recomputes the price per kg, litre or item, and flags missing or wrong unit prices, unit prices left on the old price, and Germany's per 1 kg / 1 l rule.

Pricing

from $1.00 / 1,000 results

Rating

0.0

(0)

Developer

Ultimate Foresight Inc

Ultimate Foresight Inc

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

19 hours ago

Last modified

Share

Check grocery and retail product data for unit price problems. The Unit Price Checker parses pack sizes like "6 x 330 ml", "12 pack 12 fl oz", "1.5kg" or "500 g (pack of 4)", recomputes the price per kg, litre, 100 g or item, and flags missing unit prices, unit prices that don't match the selling price, unit prices still based on the old price during a promotion, and Germany's per 1 kg / 1 l rule under PAngV §4. Works with Tesco, Coles, Woolworths, Aldi, Lidl, Rewe, Carrefour, Walmart and Kroger scraper output. Click Start with the prefilled example to see it work.

This is an automated check of the price and size data you supply. Sizes are parsed from text and can be misread, and unit-pricing rules differ by country and US state. Findings are possible gaps, not a legal determination. Not legal advice; every row carries this disclaimer and a timestamp.

What does the Unit Price Checker do?

  • ✅ Unit price mismatch: the shown unit price differs from price divided by size by more than your tolerance (2% by default; high above 5%).
  • ✅ Unit price from the old price: the unit price matches the regular or 'was' price instead of the current price.
  • ✅ Missing unit price: medium in EU, UK and DE markets, where it's required for goods sold by weight or volume; low elsewhere.
  • ✅ Basis mismatch (e.g. a per-kg unit price on a product sold by the litre) and Germany's PAngV §4 rule that unit prices use 1 kg or 1 l (not 100 g) since May 28, 2022.
  • ✅ Size parsing for metric and US units, multipacks and counts, with the parsed size in the output so you can spot misreads.
  • ✅ Output per row: price, sizeParsed, shownUnitPrice, computedUnitPrice, computedUnitPriceBasis, riskLevel, issueCount, categoriesFlagged, issues (ruleId, severity, message, quote, sourceUrl, fixHint), checkedAt and a disclaimer.

Who is it for?

  • Grocery and retail e-commerce teams checking catalog feeds before they go live.
  • Price comparison and grocery data companies cleaning scraped price data.
  • Consumer groups and journalists looking for misleading unit prices and promotions.
  • Retail analysts comparing value per kg or litre across stores.

How to check unit prices in product data

  1. Click Start with the prefilled example (a wrong per-kg price, a correct multipack, a German per-100 g price, a promo using the old price and a US pack with no unit price).
  2. Replace Products with your own: title, price, optional size, unitPrice as shown, regularPrice and market.
  3. Or enter a Dataset ID from a supermarket scraper; use Field map for fields like CupString or PackageSize.
  4. Set Default market and Mismatch tolerance if needed, and turn on Only save rows with findings to pay only for problem rows.
  5. Export results as CSV, Excel or JSON, or fetch them through the API.

Input example

This is the prefilled input:

{
"products": [
{
"id": "EXAMPLE-RICE",
"title": "Example basmati rice 1.5kg",
"price": 4.5,
"unitPrice": "£3.50/kg",
"market": "UK"
},
{
"id": "EXAMPLE-COLA",
"title": "Example cola 6 x 330ml",
"price": "€3.96",
"unitPrice": "€2.00 / l",
"market": "FR"
},
{
"id": "EXAMPLE-COFFEE",
"title": "Example ground coffee 500 g",
"price": "5,99 €",
"unitPrice": "1,20 € / 100 g",
"market": "DE"
},
{
"id": "EXAMPLE-CEREAL",
"title": "Example corn flakes 500g",
"price": 2.0,
"regularPrice": 3.0,
"unitPrice": "£6.00/kg",
"market": "UK"
},
{
"id": "EXAMPLE-WATER",
"title": "Example sparkling water, 12 pack 12 fl oz cans",
"price": 5.49,
"market": "US"
}
]
}

Dataset mode:

{"datasetId": "YOUR_DATASET_ID", "fieldMap": {"unitPrice": "CupString", "size": "PackageSize", "title": "DisplayName"}, "market": "AU", "onlyFlagged": true}

Output example

Real output from a run of the prefilled input on 2026-11-01 (long finding lists are shortened here; the run returns all of them):

[
{
"itemNo": 1,
"productId": "EXAMPLE-RICE",
"title": "Example basmati rice 1.5kg",
"price": 4.5,
"sizeParsed": "1.5kg",
"netQuantity": 1500,
"baseUnit": "g",
"shownUnitPrice": {
"amount": 3.5,
"basisQty": 1000,
"base": "g",
"label": "per kg"
},
"computedUnitPrice": 3,
"computedUnitPriceBasis": "per kg",
"market": "UK",
"riskLevel": "high",
"issueCount": 1,
"categoriesFlagged": [
"unit_price_mismatch"
],
"issues": [
{
"ruleId": "unit_price_mismatch",
"severity": "high",
"message": "Shown unit price 3.50 per kg differs by +16.7% from price 4.5 / size 1.5kg = 3.00 per kg.",
"sourceUrl": "https://www.legislation.gov.uk/uksi/2004/102/contents",
"fixHint": "Check the net quantity and recompute the unit price."
}
],
"url": null,
"checkedAt": "2026-11-01T19:35:04+00:00",
"disclaimer": "Automated check of the price and size data supplied. Sizes are parsed from text and can..."
},
{
"itemNo": 2,
"productId": "EXAMPLE-COLA",
"title": "Example cola 6 x 330ml",
"price": 3.96,
"sizeParsed": "6 x 330 ml",
"netQuantity": 1980,
"baseUnit": "ml",
"shownUnitPrice": {
"amount": 2,
"basisQty": 1000,
"base": "ml",
"label": "per l"
},
"computedUnitPrice": 2,
"computedUnitPriceBasis": "per l",
"market": "FR",
"riskLevel": "none found",
"issueCount": 0,
"categoriesFlagged": [],
"issues": [],
"url": null,
"checkedAt": "2026-11-01T19:35:04+00:00",
"disclaimer": "Automated check of the price and size data supplied. Sizes are parsed from text and can..."
},
{
"itemNo": 3,
"productId": "EXAMPLE-COFFEE",
"title": "Example ground coffee 500 g",
"price": 5.99,
"sizeParsed": "500 g",
"netQuantity": 500,
"baseUnit": "g",
"shownUnitPrice": {
"amount": 1.2,
"basisQty": 100,
"base": "g",
"label": "per 100 g"
},
"computedUnitPrice": 1.198,
"computedUnitPriceBasis": "per 100 g",
"market": "DE",
"riskLevel": "medium",
"issueCount": 1,
"categoriesFlagged": [
"unit_basis_not_allowed_de"
],
"issues": [
{
"ruleId": "unit_basis_not_allowed_de",
"severity": "medium",
"message": "Unit price is given per 100 g. Since May 28, 2022 Germany's PAngV §4 requires the price per 1 kg or 1 l (per 100 g / 100 ml is no longer allowed).",
"sourceUrl": "https://www.gesetze-im-internet.de/pangv_2022/__4.html",
"fixHint": "Show the price per 1 kg."
}
],
"url": null,
"checkedAt": "2026-11-01T19:35:04+00:00",
"disclaimer": "Automated check of the price and size data supplied. Sizes are parsed from text and can..."
},
{
"itemNo": 4,
"productId": "EXAMPLE-CEREAL",
"title": "Example corn flakes 500g",
"price": 2,
"sizeParsed": "500g",
"netQuantity": 500,
"baseUnit": "g",
"shownUnitPrice": {
"amount": 6,
"basisQty": 1000,
"base": "g",
"label": "per kg"
},
"computedUnitPrice": 4,
"computedUnitPriceBasis": "per kg",
"market": "UK",
"riskLevel": "high",
"issueCount": 1,
"categoriesFlagged": [
"unit_price_from_old_price"
],
"issues": [
{
"ruleId": "unit_price_from_old_price",
"severity": "high",
"message": "Shown unit price 6.00 per kg matches the regular price 3, not the current price 2 (expected about 4.00). The unit price should follow the selling price.",
"sourceUrl": "https://www.legislation.gov.uk/uksi/2004/102/contents",
"fixHint": "Update the unit price to 4.00 per kg."
}
],
"url": null,
"checkedAt": "2026-11-01T19:35:04+00:00",
"disclaimer": "Automated check of the price and size data supplied. Sizes are parsed from text and can..."
},
{
"itemNo": 5,
"productId": "EXAMPLE-WATER",
"title": "Example sparkling water, 12 pack 12 fl oz cans",
"price": 5.49,
"sizeParsed": "12 x 12 fl oz",
"netQuantity": 4258.5883,
"baseUnit": "ml",
"shownUnitPrice": null,
"computedUnitPrice": 1.2892,
"computedUnitPriceBasis": "per l",
"market": "US",
"riskLevel": "low",
"issueCount": 1,
"categoriesFlagged": [
"unit_price_missing"
],
"issues": [
{
"ruleId": "unit_price_missing",
"severity": "low",
"message": "No unit price shown. Many US states require or regulate unit pricing (NIST Handbook 130 Uniform Unit Pricing Regulation); it's also how shoppers compare sizes.",
"sourceUrl": "https://www.nist.gov/pml/owm/nist-handbook-130-current-edition",
"fixHint": "Show the unit price, e.g. 1.29 per l."
}
],
"url": null,
"checkedAt": "2026-11-01T19:35:04+00:00",
"disclaimer": "Automated check of the price and size data supplied. Sizes are parsed from text and can..."
}
]

How much does it cost to check unit prices?

This Actor uses pay-per-event pricing: $0.001 per product saved plus a $0.00005 start fee per run, plus small platform usage paid by you (a few hundredths of a cent for small runs). That's about $1.00 for 1,000 products and $10.00 for 10,000 plus usage. With Only save rows with findings on, rows without findings aren't saved or charged. You can set a maximum cost per run in the run options.

Use it through the API, integrations or AI agents

  • Run it and get results in one call: https://api.apify.com/v2/acts/ultimatemc~unit-price-checker/run-sync-get-dataset-items
  • Use it from AI agents through the Apify MCP server: https://mcp.apify.com?tools=ultimatemc/unit-price-checker
  • Schedule it after a daily scraper run, send flagged rows to Slack or email with webhooks, or connect it to Make, Zapier, n8n or Google Sheets.
  • Chain it after a supermarket scraper by passing the scraper's dataset ID.

How it works

Prices and sizes are parsed from numbers or text in any common format ("£1.20/kg", "2,49 €/1 kg", "$0.18/fl oz"), converted to a common unit, and compared. Rules were written from the EU Price Indication Directive, the UK Price Marking Order, Germany's PAngV §4 and NIST Handbook 130, checked on 2026-11-01. No AI and no external calls.

Sources:

FAQ

Is unit pricing required in the US?

There's no federal rule; some states and cities require it and NIST Handbook 130 gives a model regulation. US rows missing a unit price get a low note.

Why is a German per-100 g price flagged?

Since May 28, 2022 PAngV §4 requires the unit price per 1 kg or 1 l in Germany (exceptions apply, for example for some small items).

What if the size isn't in my data?

The checker looks for it in the title too. If it can't find one, the row gets a 'size not found' note.

Can I loosen the comparison?

Yes. Set Mismatch tolerance (%) to allow for rounding.

Is it AI?

No. It's a fixed set of rules, so the same input always gives the same result.

Limitations

  • Sizes are parsed from text and can be misread on unusual formats; check sizeParsed.
  • Drained weight, per-wash or per-sheet bases aren't computed.
  • Country rules are simplified to the main cases.

Other tools by Ultimate Foresight

Found a false positive? Open an issue on the Issues tab with the product data and what you expected, and we'll review the rule.