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
25
Total users
4
Monthly active users
a day ago
Last modified
Categories
Share
Same product, compared across Loblaws, No Frills, Save-On-Foods & PriceSmart in one call.
Loblaw Companies and Pattison Food Group run separate websites, separate catalogues and different house brands, so the same tub of butter shows up under different names. This Actor searches both companies (plus T&T), matches each item across them, and gives every match a confidence score, so you compare like with like instead of lining up four datasets yourself.
Sample output for "queries": ["salted butter"] (prices illustrative):
| store | company | matched product | price | unit price | match confidence |
|---|---|---|---|---|---|
| No Frills | Loblaw Companies | No Name Salted Butter 454 g | 6.00 | $1.32/100g | high |
| Loblaws | Loblaw Companies | No Name Salted Butter 454 g | 6.49 | $1.43/100g | high |
| Save-On-Foods | Pattison Food Group | Western Family Salted Butter 454 g | 7.49 | $1.65/100g | high |
| PriceSmart Foods | Pattison Food Group | Lactantia Salted Butter 454 g | 6.99 | $1.54/100g | medium |
Cost: billed per search, where one search is one item on one retailer. 5 items × 4 retailers = 20 searches. 100 searches ≈ $1–$3.67 USD on paid Apify plans ($5 on the free plan), plus $0.0015 per result row, about $0.45 at the default 3 results per search. The free Apify plan runs up to 5 items (or 5 categories) and 100 product results per run.
- 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
Each comparison 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.
- 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. Free Apify plan: first 5 per run, the rest are skipped |
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. Free Apify plan: first 5 per run, the rest are skipped |
maxResultsPerQueryPerRetailer | integer | no | Default 3. Free Apify plan: 100 product results per run in total |
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.
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.
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.