Canadian Grocery Price Comparison API
Pricing
from $10.00 / 1,000 searches
Canadian Grocery Price Comparison API
Compare grocery prices across 16 Canadian chains, Loblaws, Superstore, No Frills, Zehrs, Fortinos, Valu-mart, etc 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 $10.00 / 1,000 searches
Rating
0.0
(0)
Developer
JChaw
Maintained by CommunityActor stats
1
Bookmarked
21
Total users
4
Monthly active users
19 hours ago
Last modified
Categories
Share
Compare Canadian grocery prices across 16 chains in one run, with every result matched, normalized and scored.
The Canadian Grocery Price Comparison API takes a grocery list and a location and returns one comparison row per item per retailer, so you can see which store is cheapest without joining four datasets yourself.
- Loblaw Companies: Loblaws, Real Canadian Superstore, No Frills, Zehrs, Fortinos, Valu-mart, Your Independent Grocer, Provigo, Maxi, Wholesale Club, Atlantic Superstore
- Pattison Food Group: Save-On-Foods, PriceSmart Foods, Urban Fare, Quality Foods
- T&T Supermarket
- Every row: matched product, retailer, store, price, sale price, normalized unit price, availability, product URL, match confidence
- Setup: none. No API key, no account, no proxy.
Run it
Paste this into the Input tab (switch to JSON view) and hit Start:
{"queries": ["eggs", "chicken breast", "celery"],"location": "Vancouver, BC","retailers": ["loblaws", "saveonfoods", "tnt"]}
Comparison rows stream into Output as each retailer finishes. Download from Storage → Dataset as JSON, CSV or Excel.
Three things to change from there:
- Compare a real basket by extending
queriesto your weekly list - Move region by editing
location, then naming the banners that serve it: Montréal is["maxi", "provigo", "valumart"], Halifax is["atlanticsuperstore", "nofrills", "independent"] - Add basket totals with
"includeSummaries": true
From the API
Grab a token at console.apify.com/settings/integrations:
curl -X POST \"https://api.apify.com/v2/acts/sunny_eternity~canada-grocery-price-comparison/run-sync-get-dataset-items?token=YOUR_API_TOKEN" \-H "Content-Type: application/json" \-d '{"queries": ["eggs", "chicken breast", "celery"], "location": "Vancouver, BC", "retailers": ["loblaws", "saveonfoods", "tnt"]}'
run-sync-get-dataset-itemssuits small runs and can time out on large ones- For scheduled runs or large baskets, POST to
/runsand read the returneddefaultDatasetId - Official JavaScript and Python clients work too
What you get back
One query against three retailers returns one row each:
| query | retailer | matched product | price | unit price | sale | confidence |
|---|---|---|---|---|---|---|
| eggs | loblaws | No Name Large Eggs 12-pack | 4.49 | 0.37/each | false | high |
| eggs | saveonfoods | Western Family Large Eggs 12-pack | 5.29 | 0.44/each | false | high |
| eggs | tnt | Large White Eggs 12-pack | 4.99 | 0.42/each | true | medium |
Each row in full:
{"_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,"comparable_unit_basis": "100g","sale_price": null,"was_price": null,"is_on_sale": false,"availability": "in_stock","match_confidence": "high","match_score": 0.86,"match_reasons": ["brand_match", "size_match"],"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"}
Every dataset record carries a _type. Branch on it: comparison and category_browse_product are product rows, the rest are roll-ups and run metadata.
Why this Actor
- 705 runs across the suite in the last 30 days, none ended in a failed state. Run stats are public on the Apify API; figures from August 2026.
- One call replaces four. Running the retailer scrapers yourself leaves you with four schemas, four location systems and a matching problem. This Actor handles the fan-out, the normalization and the matching in one run.
- Every match shows its work.
match_scoreruns 0 to 1,match_confidencebuckets it high, medium or low, andmatch_reasonsandmismatch_reasonsname the signals behind the score, such as brand agreement or a differing package size. - Unit prices compare across chains.
comparable_unit_priceandcomparable_unit_basis(100g,100ml,each,lb) put a 1.89 L Superstore carton and a 2 L Save-On-Foods one on the same footing, andis_comparable_unit_pricemarks the rows where that holds. - Every retailer gets a verdict.
run_meta.retailer_statusreportssuccess,no_results,failedwith a reason, orskipped, andrun_meta.warningscollects location and search failures, so a partial run tells you which retailer came up short. - Defaults stay small. Naming no retailers runs the six national chains; the other ten are opt-in, so an unspecified run stays predictable.
- Runs without a browser, over plain HTTP against each retailer's own JSON API, with the Apify SDK as its only runtime dependency and no API keys.
What people build with it
- Fixed-basket inflation tracking, rerunning the same list weekly and charting
basket_summarytotals - Grocery price comparison apps, using comparison rows straight as backend data
- AI shopping agents, which get one normalized table instead of four retailer schemas
- CPG competitor monitoring across banners and parent companies at once
- Household budgeting dashboards in Google Sheets or Excel, fed by a scheduled run
- Academic and journalistic food-price research needing store-level Canadian data
Input
| Field | Type | Required | Description |
|---|---|---|---|
queries | string[] | yes | Grocery search terms. Also accepted as items |
retailers | string[] | no | Any subset of the 16 keys below. Default: tnt, loblaws, superstore, nofrills, saveonfoods, pricesmart |
location | string | no | City and province (Vancouver, BC) or postal code. Alias for region and postal_code |
region | string | no | One of 8 metros: Vancouver, Calgary, Edmonton, Toronto, Ottawa, Montreal, Quebec City, Halifax. Default metro_vancouver |
postal_code | string | no | Overrides region |
locationIds | object | no | Per-retailer store overrides, e.g. { "tnt": "MGFS", "superstore": "1517" } |
categories | string[] | no | 17 unified category slugs, used by category_browse and intel modes |
maxResultsPerQueryPerRetailer | integer | no | Default 3 |
retailerConcurrency | integer | no | Default 3 |
minMatchConfidence | string | no | low (default), medium or high |
strictItemBest | boolean | no | Default true. Restricts item_best_options to rows with a comparable unit price and medium or high confidence |
includeSummaries | boolean | no | Default false. Adds basket_summary, item_best_options and run_meta rows |
outputMode | string | no | See below. Default comparison |
Output modes
| Mode | Best for |
|---|---|
comparison | Flat rows, one matched product per query per retailer. CSV, Excel and ETL |
comparison_grouped | One record per query with all retailer results nested. LLM and agent input |
summary | Cheapest retailer, price range, median price and sale count per query |
category_browse | Full category listings per retailer, with no query matching |
intel | Comparison rows plus summaries, category stats, top deals and a run summary |
Start with comparison unless you know you need another one.
Fixed-basket tracking
Run the same basket on a schedule to build a price history:
{"queries": ["eggs", "milk", "bread", "bananas", "chicken breast", "ground beef", "rice", "celery"],"location": "Vancouver, BC","retailers": ["loblaws", "saveonfoods", "tnt"],"includeSummaries": true}
With includeSummaries on, each run also emits:
basket_summary, the basket total per retaileritem_best_options, the cheapest source per itemrun_meta, per-retailer status and warnings
That covers basket totals, per-item winners and sale frequency over time with no post-processing.
Supported retailers
| Key | Chain | Where |
|---|---|---|
loblaws | Loblaws | BC, AB, ON |
superstore | Real Canadian Superstore | BC, AB, SK, MB, ON, YT |
nofrills | No Frills | Nationwide |
zehrs | Zehrs | ON |
fortinos | Fortinos | ON |
valumart | Valu-mart | ON, QC |
independent | Your Independent Grocer | Nationwide |
provigo | Provigo | QC |
maxi | Maxi | QC, NB |
wholesaleclub | Wholesale Club | Nationwide |
atlanticsuperstore | Atlantic Superstore | NB, NS, PE |
saveonfoods | Save-On-Foods | BC, AB, SK, MB |
pricesmart | PriceSmart Foods | Metro Vancouver |
urbanfare | Urban Fare | Vancouver, Kelowna |
qualityfoods | Quality Foods | Vancouver Island, Sunshine Coast |
tnt | T&T Supermarket | BC, AB, ON, QC |
T&T serves one catalogue chain-wide, so its resolved store labels the rows while prices stay constant. Loblaw and Pattison banners price per store.
FAQ
How do I compare grocery prices across Canadian stores? Give queries (your grocery list), a location, and the retailers you want. Each run returns one matched row per item per retailer, with price, unit price and a confidence score.
Which is cheapest for my basket? Set "includeSummaries": true and read the basket_summary rows, which total the basket per retailer, and item_best_options, which names the cheapest source per item.
Are the matches exact? Not always. The Actor compares retailer search results, and grocery products vary by brand, size and naming. Every row carries match_score, match_confidence and the reasons behind them; filter with minMatchConfidence.
Which retailers run by default? The six national chains: tnt, loblaws, superstore, nofrills, saveonfoods and pricesmart. The other ten are opt-in.
Does it cover Sobeys, Metro, Walmart or Costco? Sobeys, Metro and Walmart Canada are outside the 16. Costco has a separate Actor.
Does it track price history? No. Each run returns current prices. Schedule the same basket and keep each dataset to build history.
Should I use this or a single-retailer Actor? Use this one to compare across chains. Use a retailer Actor when you want one chain in depth, with full category trees and whole-store scrapes.
Is scraping these retailers legal? Scraping publicly available product and price information is generally legal. Complying with each retailer's terms of service and the law in your jurisdiction remains your responsibility, so keep request volume reasonable.
Limitations
- This Actor compares retailer search results, and makes no guarantee of exact product equivalence across stores, because grocery products vary by brand, size, store and naming. Review matches with
match_confidence,package_size,comparable_unit_priceandsource_url, and filter them withminMatchConfidence. - Prices and availability vary by store, postal code, time of scrape, loyalty program and retailer search behaviour.
- Coverage stops at 16 chains. Sobeys, Metro and Walmart Canada fall outside it, and Costco has a separate Actor.
- Each run returns current prices and keeps no history between runs. Schedule the same basket and store the datasets to build that history yourself.
Canadian grocery Actors
| Actor | Chains | Coverage |
|---|---|---|
| Canadian Grocery Price Comparison API (this Actor) | 16, matched and ranked in one run | Nationwide |
| Loblaws, No Frills, Superstore & Maxi Scraper API - Canada | 12 Loblaw banners | Every province, YT, NT |
| Save-On-Foods, PriceSmart & Urban Fare Scraper API - Canada | 4 Pattison Food Group banners | BC, AB, SK, MB |
| T&T Asian Supermarket Grocery Price Scraper API - Canada | T&T | BC, AB, ON, QC |
| Costco Scraper API - Warehouse Prices & Deals | Costco warehouses | Canada and US |
Use this Actor to compare across chains. Use a retailer Actor when you want one chain in depth, with full category trees, whole-store scrapes and every field that chain exposes. All four retailer Actors share 21 core output fields, so their datasets concatenate without a mapping layer.
Feedback
Found a bug or have technical feedback? Open an issue on the Actor's Issues tab.