Canadian Grocery Price Comparison Scraper API
Pricing
from $50.00 / 1,000 searches
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
Maintained by CommunityActor stats
1
Bookmarked
2
Total users
1
Monthly active users
2 days ago
Last modified
Categories
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?
- Loblaws / Superstore / No Frills Grocery Price API
- Save-On-Foods / PriceSmart Grocery Price API
- T&T Supermarket Grocery Price API
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, orcelery - a location, such as
Vancouver, BC - retailers, such as
loblaws,saveon, andtnt
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:
| item | retailer | matched product | price | unit price | sale | confidence |
|---|---|---|---|---|---|---|
| eggs | loblaws | No Name Large Eggs 12-pack | 4.49 | 0.37/each | false | high |
| eggs | saveon | 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 |
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 family | Banners |
|---|---|
| Loblaws Cos. | Loblaws, Real Canadian Superstore, No Frills |
| Pattison Food Group | Save-On-Foods, PriceSmart Foods |
| T&T | T&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 / banner | Actor | Best for |
|---|---|---|
| Loblaws / Superstore / No Frills | Loblaws / Superstore / No Frills Grocery Price API | Loblaws-owned grocery price and product data |
| Save-On-Foods / PriceSmart Foods | Save-On-Foods / PriceSmart Grocery Price API | Western Canada grocery prices and product data |
| T&T Supermarket | T&T Supermarket Grocery Price API | T&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.
| Mode | Best for | Description |
|---|---|---|
comparison | Most users | Flat rows, one matched product per item per retailer. Best for CSV, Excel, API, and ETL. |
comparison_grouped | AI / LLM workflows | One record per item with retailer results grouped together. |
summary | quick analysis | Cheapest retailer, price range, median price, and sale count per item. |
category_browse | advanced catalog scraping | Browse full categories by retailer. |
intel | heavy analysis | Comparison rows plus summaries, category data, deals, and run summary. |
Start with comparison unless you know you need another mode.
Input reference
| Field | Type | Required | Description |
|---|---|---|---|
items | string[] | yes (beginner) | Grocery item search terms. Alias of queries. |
queries | string[] | conditional | Same as items. Required for comparison, comparison_grouped, summary modes. |
location | string | no | City/province (e.g. Vancouver, BC) or postal code. Beginner-friendly alias for region / postal_code. |
retailers | string[] | no | Subset of tnt, loblaws, superstore, nofrills, saveonfoods, pricesmart. Default: all supported. |
region | string | conditional | Metro region; maps to a representative postal code. |
postal_code | string | no | Overrides region. |
locationIds | object | no | Per-retailer store ID overrides (e.g. { "tnt": "MGFS", "superstore": "1517", "saveonfoods": "1982" }). |
categories | string[] | conditional | Unified category slugs (used in category_browse / intel modes). |
maxResultsPerQueryPerRetailer | integer | no | Default 3. |
retailerConcurrency | integer | no | Default 3. |
minMatchConfidence | string | no | low (default) | medium | high. |
strictItemBest | boolean | no | Default true. When true, item_best_options only chooses rows with comparable unit-price + medium/high confidence. |
includeSummaries | boolean | no | Default false. In comparison mode, set true to also emit basket_summary, item_best_options, and run_meta. |
outputMode | string | no | See Output modes. Default comparison. |
Output fields
Each comparison record includes:
query,retailer,banner,store,store_idmatched_product,product_id,package_size,selling_typeprice,sale_price,was_price,is_on_saleunit_price,comparable_unit_priceavailabilitymatch_confidence(high/medium/low),match_scoresource_url,image_urlmulti_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 rowno_results— retailer executed but returned zero matchesfailed— 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:
- Loblaws / Superstore / No Frills Grocery Price API
- Save-On-Foods / PriceSmart Grocery Price API
- T&T Supermarket Grocery Price API
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
SearchandResultevents - advanced users can inspect raw output depending on selected output mode
How charging is implemented
Searchis manually charged viaActor.charge({ eventName: "retailer-search" })before each item-retailer child actor invocation. If the charge fails (limit reached orchargedCount < 1), the child actor is never called, so the user is never billed for work they cannot be charged for.Resultis charged automatically by the Apify SDK: every push to the default dataset viaActor.pushData(...)increments theapify-default-dataset-itemevent count and respects themaxTotalChargeUsdbudget. We do not pass a second event name topushData— doing so would double-charge.- The synthetic
apify-actor-startevent 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-searchevent is charged per valid item-retailer pair. - One
apify-default-dataset-itemevent is charged for each row pushed. - The synthetic
apify-actor-startevent 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_KEYandBULLSEYE_CLIENT_IDenv 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