Canadian Grocery Price Comparison Scraper API avatar

Canadian Grocery Price Comparison Scraper API

Pricing

from $50.00 / 1,000 searches

Go to Apify Store
Canadian Grocery Price Comparison Scraper API

Canadian Grocery Price Comparison Scraper API

Compare grocery prices across Loblaws, Superstore, No Frills, Save-On-Foods, PriceSmart, and T&T from one input. Get normalized product matches, prices, unit prices, sale flags, store details, product URLs, and CSV/JSON/Excel-ready output for apps, AI agents, and research.

Pricing

from $50.00 / 1,000 searches

Rating

0.0

(0)

Developer

JChaw

JChaw

Maintained by Community

Actor stats

1

Bookmarked

2

Total users

1

Monthly active users

2 days ago

Last modified

Share

Canadian Grocery Price Comparison API

Compare grocery prices across supported Canadian retailers from one input.

Enter a grocery list, location, and retailers. Get normalized comparison-ready output with matched products, prices, unit prices, sale flags, store details, product URLs, and match confidence.

Supported retailers and banners:

  • Loblaws / Real Canadian Superstore / No Frills
  • Save-On-Foods / PriceSmart Foods
  • T&T Supermarket

Best for:

  • fixed basket grocery tracking
  • grocery price comparison apps
  • AI grocery shopping agents
  • CPG competitor price monitoring
  • food inflation research
  • Google Sheets / Excel grocery tracking workflows

Need data from only one retailer?

What this Actor does

This Actor lets you compare grocery prices across multiple Canadian retailers without running separate APIs manually.

You provide:

  • grocery items, such as eggs, milk, chicken breast, or celery
  • a location, such as Vancouver, BC
  • retailers, such as loblaws, saveon, and tnt

The Actor returns:

  • matched grocery products
  • retailer and banner
  • store details
  • price and sale price
  • normalized unit price
  • package size
  • availability
  • product URL
  • match confidence
  • CSV/JSON/Excel-ready output

Use it when you want one normalized comparison table instead of separate retailer-specific API outputs.

Quick start

The simplest run only needs grocery items, a location, and retailers:

{
"items": ["eggs", "chicken breast", "celery"],
"location": "Vancouver, BC",
"retailers": ["loblaws", "saveon", "tnt"]
}

This returns comparison rows for each item across the selected retailers.

Use items for beginner-friendly input. Advanced users can use queries, region, postal_code, and locationIds for more control.

Retailer aliases accepted: saveon, save-on, t&t, rcss, no-frills.

Example output

Input:

{
"items": ["eggs"],
"location": "Vancouver, BC",
"retailers": ["loblaws", "saveon", "tnt"]
}

Example comparison output:

itemretailermatched productpriceunit pricesaleconfidence
eggsloblawsNo Name Large Eggs 12-pack4.490.37/eachfalsehigh
eggssaveonWestern Family Large Eggs 12-pack5.290.44/eachfalsehigh
eggstntLarge White Eggs 12-pack4.990.42/eachtruemedium

The exact returned fields depend on retailer availability and selected output mode.

Each row in comparison mode is a full record like:

{
"_type": "comparison",
"schema_version": "2026-05-compare-v1",
"query": "ground beef",
"retailer": "loblaws",
"banner": "Loblaws",
"store": "Robson Street",
"store_id": "1050",
"matched_product": "PC Lean Ground Beef",
"price": 7.99,
"unit_price": "$1.76/100g",
"comparable_unit_price": 1.76,
"sale_price": null,
"was_price": null,
"is_on_sale": false,
"availability": "in_stock",
"match_confidence": "high",
"match_score": 0.86,
"source_url": "https://www.loblaws.ca/...",
"image_url": "https://...",
"product_id": "20123456",
"package_size": "454 g",
"selling_type": "by_weight",
"multi_buy_deal": null,
"pc_optimum_offer": null,
"category": "search:ground beef",
"country": "CA",
"currency": "CAD",
"region": "BC",
"scraped_at": "2026-05-15T14:32:11.123Z",
"run_id": "abc123"
}

Fixed basket tracking

This Actor works well for tracking the same grocery basket over time.

Example fixed basket:

{
"items": ["eggs", "milk", "bread", "bananas", "chicken breast", "ground beef", "rice", "celery"],
"location": "Vancouver, BC",
"retailers": ["loblaws", "saveon", "tnt"],
"includeSummaries": true
}

Run the same basket weekly to track:

  • basket total changes
  • cheapest retailer by item
  • sale items
  • unit price changes
  • store-by-store differences
  • food inflation for your usual groceries

This is useful for personal grocery tracking, household budgeting, food price research, and spreadsheet-based grocery dashboards.

Common use cases

Track a fixed grocery basket

Track the same grocery items weekly and compare basket totals across supported retailers.

Build a grocery price comparison app

Use normalized grocery price rows as backend data for Canadian grocery comparison apps.

Power an AI grocery shopping agent

Give an AI agent live grocery price context for supported Canadian retailers.

Monitor CPG and retail pricing

Compare product prices, sale prices, and unit prices across supported grocery banners.

Research food inflation

Collect structured Canadian grocery price data for analysis, charts, and reporting.

Supported retailers

Retailer familyBanners
Loblaws Cos.Loblaws, Real Canadian Superstore, No Frills
Pattison Food GroupSave-On-Foods, PriceSmart Foods
T&TT&T Supermarket

T&T's product catalog is unified across stores; the resolved store is used purely to label output records.

Individual retailer APIs

This Actor is best when you want to compare prices across multiple retailers from one input.

If you only need data from one retailer, use the individual API instead:

Retailer / bannerActorBest for
Loblaws / Superstore / No FrillsLoblaws / Superstore / No Frills Grocery Price APILoblaws-owned grocery price and product data
Save-On-Foods / PriceSmart FoodsSave-On-Foods / PriceSmart Grocery Price APIWestern Canada grocery prices and product data
T&T SupermarketT&T Supermarket Grocery Price APIT&T and Asian grocery product price data

Pricing

This Actor uses pay-per-event pricing.

You are charged for:

  • Search: one grocery item searched on one selected retailer
  • Result: one normalized comparison row returned

Example:

If you compare 3 grocery items across 3 retailers, that counts as 9 searches.

A small run with 3 items across 3 retailers usually costs around $0.50–$0.75 depending on the number of results returned.

Platform usage is included.

Output modes

Most users should start with comparison.

ModeBest forDescription
comparisonMost usersFlat rows, one matched product per item per retailer. Best for CSV, Excel, API, and ETL.
comparison_groupedAI / LLM workflowsOne record per item with retailer results grouped together.
summaryquick analysisCheapest retailer, price range, median price, and sale count per item.
category_browseadvanced catalog scrapingBrowse full categories by retailer.
intelheavy analysisComparison rows plus summaries, category data, deals, and run summary.

Start with comparison unless you know you need another mode.

Input reference

FieldTypeRequiredDescription
itemsstring[]yes (beginner)Grocery item search terms. Alias of queries.
queriesstring[]conditionalSame as items. Required for comparison, comparison_grouped, summary modes.
locationstringnoCity/province (e.g. Vancouver, BC) or postal code. Beginner-friendly alias for region / postal_code.
retailersstring[]noSubset of tnt, loblaws, superstore, nofrills, saveonfoods, pricesmart. Default: all supported.
regionstringconditionalMetro region; maps to a representative postal code.
postal_codestringnoOverrides region.
locationIdsobjectnoPer-retailer store ID overrides (e.g. { "tnt": "MGFS", "superstore": "1517", "saveonfoods": "1982" }).
categoriesstring[]conditionalUnified category slugs (used in category_browse / intel modes).
maxResultsPerQueryPerRetailerintegernoDefault 3.
retailerConcurrencyintegernoDefault 3.
minMatchConfidencestringnolow (default) | medium | high.
strictItemBestbooleannoDefault true. When true, item_best_options only chooses rows with comparable unit-price + medium/high confidence.
includeSummariesbooleannoDefault false. In comparison mode, set true to also emit basket_summary, item_best_options, and run_meta.
outputModestringnoSee Output modes. Default comparison.

Output fields

Each comparison record includes:

  • query, retailer, banner, store, store_id
  • matched_product, product_id, package_size, selling_type
  • price, sale_price, was_price, is_on_sale
  • unit_price, comparable_unit_price
  • availability
  • match_confidence (high / medium / low), match_score
  • source_url, image_url
  • multi_buy_deal, pc_optimum_offer (retailer-specific extras, nullable)
  • country, currency, region, scraped_at, run_id

When includeSummaries is true, the dataset also includes:

  • _type: "basket_summary"
  • _type: "item_best_options"
  • _type: "run_meta"

run_meta.retailer_status labels each requested retailer as one of:

  • success — retailer returned at least one matched row
  • no_results — retailer executed but returned zero matches
  • failed — retailer failed (reason included)
  • skipped — retailer was requested but not executed in the final run path

run_meta.warnings collects runtime warnings from location resolution, query search, and category scrape failures.

Limitations

This Actor compares retailer search results. It does not guarantee exact product equivalence across stores.

Prices and availability may vary by:

  • store location
  • postal code
  • time of scrape
  • loyalty program
  • product availability
  • retailer search behavior

Use matchConfidence, product names, package sizes, unit prices, and product URLs to review matches.

This Actor currently supports selected Canadian grocery retailers and banners. It does not cover every grocery retailer in Canada.

FAQ

Should I use this Actor or the individual retailer APIs?

Use this Actor if you want to compare the same grocery items across multiple supported retailers.

Use the individual retailer APIs if you only need data from one retailer:

Does this Actor track price history?

Not by itself. Each run returns current comparison output. To track history, run the same basket regularly and store the results in a spreadsheet, database, or BI tool.

Can I use this for fixed basket tracking?

Yes. Run the same list of items weekly or monthly and compare basket totals, item prices, unit prices, and sales over time.

Can I export the results?

Yes. Apify datasets can be exported as CSV, JSON, Excel, and other formats.

Are the matches exact?

Not always. Grocery products vary by brand, package size, store, and retailer naming. Use match confidence and product URLs to review matches.

Technical notes

This Actor is built on top of retailer-specific grocery APIs and normalizes their outputs into a shared comparison format.

Advanced notes:

  • retailer adapters map each API output into a common schema
  • query matching uses product names, package sizes, unit prices, and match confidence
  • pay-per-event billing charges Search and Result events
  • advanced users can inspect raw output depending on selected output mode

How charging is implemented

  • Search is manually charged via Actor.charge({ eventName: "retailer-search" }) before each item-retailer child actor invocation. If the charge fails (limit reached or chargedCount < 1), the child actor is never called, so the user is never billed for work they cannot be charged for.
  • Result is charged automatically by the Apify SDK: every push to the default dataset via Actor.pushData(...) increments the apify-default-dataset-item event count and respects the maxTotalChargeUsd budget. We do not pass a second event name to pushData — doing so would double-charge.
  • The synthetic apify-actor-start event is never manually charged.

Local PPE testing

To exercise the pay-per-event flow locally (without spending real money on Apify), set the SDK's test env vars before running the actor:

ACTOR_TEST_PAY_PER_EVENT=true \
ACTOR_USE_CHARGING_LOG_DATASET=true \
npm start

Verify the following in the local charging log dataset / OUTPUT:

  • Exactly one retailer-search event is charged per valid item-retailer pair.
  • One apify-default-dataset-item event is charged for each row pushed.
  • The synthetic apify-actor-start event is never manually charged.
  • When the charge limit is reached, no further child actor runs are scheduled.

Billing summary

Every run writes a billing block to the OUTPUT key-value record and to the trailing run_meta dataset record (when summaries are enabled):

{
"billing": {
"searchEventsAttempted": 9,
"searchEventsCharged": 9,
"resultRowsAttempted": 27,
"resultRowsPushed": 27,
"chargeLimitReached": false
}
}

The actor also writes a human-readable SUMMARY Markdown value with the same information, plus a warning section if the charge limit was reached mid-run.

Implementation details

  • The actor runs each retailer in parallel (configurable via retailerConcurrency); within a retailer, queries are processed sequentially with the per-retailer politeness delay each API already enforces.
  • Loblaws location resolution uses a third-party Bullseye API; if BULLSEYE_API_KEY and BULLSEYE_CLIENT_ID env vars are missing the actor falls back to the banner's default store.
  • Retailer adapters live in src/retailer-dispatch.ts; adding a new retailer is one adapter object there.

Schema files

  • Input schema: INPUT_SCHEMA.json
  • Output schema notes: OUTPUT_SCHEMA.md