Loblaws, No Frills, Superstore & Maxi Scraper API - Canada
Pricing
from $0.70 / 1,000 results
Loblaws, No Frills, Superstore & Maxi Scraper API - Canada
Scrape grocery prices from 12 Canadian chains: Loblaws, Real Canadian Superstore, No Frills, Zehrs, Fortinos, Valu-mart, Your Independent Grocer, City Market, Provigo, Maxi, Wholesale Club and Atlantic Superstore. Store-level pricing by postal code. JSON, CSV or Excel.
Pricing
from $0.70 / 1,000 results
Rating
5.0
(2)
Developer
JChaw
Maintained by CommunityActor stats
4
Bookmarked
112
Total users
10
Monthly active users
5.8 hours
Issues response
19 hours ago
Last modified
Categories
Share
Canadian grocery price data from 12 Loblaw banners, priced at the individual store by postal code.
The Loblaws Scraper API returns live shelf prices, sale prices, unit prices and promotions from Loblaws, Real Canadian Superstore, No Frills, Maxi and eight more, with no API key and no browser.
- Chains: Loblaws, Real Canadian Superstore, No Frills, Zehrs, Fortinos, Valu-mart, Your Independent Grocer, Independent City Market, Provigo, Maxi, Wholesale Club, Atlantic Superstore
- Coverage: every province, plus Yukon and the Northwest Territories
- Every row: name, price, was-price, sale flag, unit price, normalized unit price, package size, image, product URL, product ID, store details, multi-buy deals, PC Optimum offers
- Setup: none. No API key, no account, no proxy.
Run it
Paste this into the Input tab (switch to JSON view) and hit Start:
{"banner": "superstore","search_terms": ["eggs", "milk", "chicken breast"],"postal_code": "V5X 0C4"}
Rows stream into Output as they arrive. Download from Storage → Dataset as JSON, CSV or Excel.
Three things to change from there:
- Scrape a whole department by swapping
search_termsforcategories, e.g.["fruits-vegetables", "dairy-eggs"], or["all"]for the entire store - Price a different store by changing
postal_codeto yours - Switch chains with
banner:maxiorprovigofor Quebec,zehrs,fortinosorvalumartfor Ontario,rassfor Atlantic Canada
From the API
Grab a token at console.apify.com/settings/integrations:
curl -X POST \"https://api.apify.com/v2/acts/sunny_eternity~loblaws-grocery-scraper/run-sync-get-dataset-items?token=YOUR_API_TOKEN" \-H "Content-Type: application/json" \-d '{"banner": "superstore", "search_terms": ["eggs", "milk", "chicken breast"], "postal_code": "V5X 0C4"}'
run-sync-get-dataset-itemssuits small runs and can time out on large ones- For scheduled or full-store scrapes, POST to
/runsand read the returneddefaultDatasetId - Official JavaScript and Python clients work too
What you get back
{"store": "Real Canadian Superstore","name": "Bananas","price": "0.69","unit_price": "454 g, $0.15/100g","comparable_unit_price": 0.15,"package_size": "454g","parsed_package_size": { "size": 454, "unit": "g" },"parsed_unit_price": { "value": 0.15, "quantity": 100, "unit": "g", "unit_type": "weight" },"selling_type": "by_weight","was_price": 0.89,"is_on_sale": true,"multi_buy_deal": "2 for $1.00","pc_optimum_offer": "1000 points","image_url": "https://assets.shop.loblaws.ca/products/...","product_url": "https://www.realcanadiansuperstore.ca/bananas/p/...","product_id": "21023456","category": "fresh-fruits","location": "1517","location_name": "Real Canadian Superstore Marine Drive","location_postal_code": "V5X 0C4","location_coordinates": { "lat": 49.2088, "lng": -123.1076 }}
| Field | What it holds |
|---|---|
store | Chain name: Real Canadian Superstore, Maxi, Zehrs and the rest |
name, price | Product name and current price, no $ symbol |
unit_price | Raw unit price string from the store, e.g. "454 g, $0.15/100g" |
comparable_unit_price | Normalized $/100 g or $/100 ml, null when the size will not parse |
parsed_unit_price, parsed_package_size, normalized_package_size | Structured value, quantity and unit forms |
package_size, selling_type | Size string, plus by_weight or by_unit |
was_price, is_on_sale | Pre-sale price and sale flag |
multi_buy_deal, pc_optimum_offer | Promotion text such as "2 for $5.00", and points offers |
image_url, product_url, product_id, article_number | Media and identifiers |
location, location_name, location_postal_code, location_coordinates | The store the prices came from |
variants, variant_count, variant_group_id | Present when group_variants is on |
Export as JSON, CSV or Excel, pull it through the Apify API, schedule recurring runs, or push it into Zapier, Make, Google Sheets and Airbyte.
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.
- Covers 12 banners from one input, including Quebec (Maxi, Provigo), Atlantic Canada and Ontario's regional banners. Most Loblaws scrapers stop at Loblaws, Superstore and No Frills.
- Prices down to the individual store. Postal codes resolve against Loblaw's own store directory, the endpoint the storefronts call to fill their store pickers, and every row names the store, its postal code and its coordinates.
- Runs without a browser. The only runtime dependency is the Apify SDK, reading the same JSON API the storefront reads, so you pay for no headless Chrome and hit no CAPTCHAs.
- Needs no credentials at all: no API key, no account, no third-party geocoder, no proxy configuration.
- Normalizes unit prices to $/100 g or $/100 ml, and leaves
comparable_unit_priceasnullwhere a package size will not parse, which keeps a bad number out of your comparison. - Refuses out-of-footprint input. A postal code a banner does not serve returns an error naming the provinces it does, so a Quebec query never quietly comes back with an Ontario store.
- Groups package-size variants with
group_variants, collapsing a six-size olive oil listing into one row with avariantsarray.
What people build with it
- Grocery price comparison apps that need live Canadian shelf prices keyed to a store
- Food inflation research, by rerunning a fixed basket weekly and diffing
priceover time - CPG competitor monitoring, tracking a brand's shelf price and promotions across all 12 banners
- Deal and flyer sites, pulling
is_on_sale,multi_buy_dealandpc_optimum_offer - AI shopping agents that need grounded prices instead of guessed ones
- Product and price databases keyed by
product_id, store and postal code
Input
| Field | Type | Required | Description |
|---|---|---|---|
banner | string | yes | One of the 12 banners in Supported stores |
categories | string[] | no | Departments or subcategories; 134 entries (all, 13 departments, 120 subcategories) |
categoryUrls | string[] | no | Full category URLs for subcategories missing from the dropdown |
search_terms | string[] | no | Keyword queries; combined with categories they filter by name instead |
postal_code | string | no | Canadian postal code; resolves the nearest store of that banner |
locationId | string | no | Explicit store ID, takes priority over postal_code |
group_variants | boolean | no | Merge package-size variants into one row. Default false |
on_sale_only | boolean | no | Keep only rows with is_on_sale: true. Default false |
- At least one of
categories,categoryUrlsorsearch_termsis required - Selecting a department scrapes every subcategory beneath it, discovered from the store's API at runtime
allscrapes the whole store- Setting
categoriesandsearch_termstogether filters the category results by product name, with no separate search call. Usesearch_termson its own for a dedicated search
Examples
One subcategory:
{ "banner": "superstore", "categories": ["bakery/bread"] }
Departments and subcategories mixed:
{ "banner": "superstore", "categories": ["meat", "dairy-eggs/cheese", "frozen-food/frozen-pizza"] }
Whole store at one location, sale items only:
{ "banner": "superstore", "categories": ["all"], "postal_code": "V6M 2P8", "on_sale_only": true }
Category results filtered by keyword:
{ "banner": "superstore", "categories": ["dairy-eggs"], "search_terms": ["cheese", "yogurt"] }
A subcategory missing from the dropdown:
{ "banner": "superstore", "categoryUrls": ["https://www.realcanadiansuperstore.ca/en/food/fruits-vegetables/fresh-vegetables/lettuce-leafy-vegetables/c/29612"] }
Supported stores
| Banner | Store | Provinces |
|---|---|---|
superstore | Real Canadian Superstore | BC, AB, SK, MB, ON, YT |
nofrills | No Frills | BC, AB, SK, MB, ON, NB, NS, PE, NL |
loblaw | Loblaws | BC, AB, ON |
zehrs | Zehrs | ON |
fortinos | Fortinos | ON |
valumart | Valu-mart | ON, QC |
independent | Your Independent Grocer | BC, AB, SK, ON, NB, NS, PE, NL, YT, NT |
independentcitymarket | Independent City Market | ON |
provigo | Provigo | QC |
maxi | Maxi | QC, NB |
wholesaleclub | Wholesale Club | BC, AB, SK, MB, ON, QC, NB, NS, NL |
rass | Atlantic Superstore | NB, NS, PE |
- Each banner prices independently, so the same SKU can differ by a dollar or more between them
rassis Atlantic Superstore's internal code, short for "Real Atlantic SuperStore"- Aliases accepted:
"atlantic","atlantic superstore","loblaws","rcss","no frills","valu-mart","yig"
FAQ
How do I scrape Real Canadian Superstore prices? Set "banner": "superstore" and give either search_terms or categories, plus a postal_code for store-level pricing. The Run it input above is a working example.
Can I get grocery prices for a specific postal code? Yes. Pass any Canadian postal_code and the Actor resolves the nearest store of that banner, then reports the store's name, postal code and coordinates on every row.
Does this work for Quebec? Yes. Use maxi or provigo, the two Loblaw banners that operate in Quebec. valumart and wholesaleclub also have Quebec locations.
Is there an official Loblaws API? No. Loblaw publishes no public product or pricing API, which is why this Actor reads the same JSON endpoints the storefronts use.
How do I find my store's location ID? In most cases postal_code is enough. Pass locationId when you want one specific store:
1517Superstore Vancouver Marine Dr,3641No Frills Vancouver Denman,1000Loblaws Toronto Queen St7234Maxi Montréal Mt-Royal Ouest,7907Provigo Montréal Parc0560Zehrs Kitchener Laurentian,2265Fortinos Hamilton Dundurn,0315Atlantic Superstore Oromocto NB
Which banner covers my region?
- Quebec: Maxi, Provigo
- Atlantic Canada: Atlantic Superstore, No Frills, Your Independent Grocer
- Ontario: the widest choice, all eight Ontario banners
- Western Canada: Superstore, No Frills, Your Independent Grocer, Wholesale Club
Can I compare the same product across banners? Yes. Run once per banner with the same search_terms and region, then join on product_id, which is shared across the Loblaw catalogue. For a ready-made cross-chain comparison, use the Canadian Grocery Price Comparison API.
How do I track prices over time? Schedule the Actor daily or weekly in Apify, keep each run's dataset, and compare price per product_id per store. The Actor returns current prices and stores no history itself.
How many products can one run return? A single subcategory is typically tens to hundreds of products; categories: ["all"] walks the entire store. Runs stream to the dataset as they go, so partial results are available while the run continues.
Is scraping Loblaws legal? Scraping publicly available product and price information is generally legal. Complying with the retailer's terms of service and the law in your jurisdiction remains your responsibility, so keep request volume reasonable.
Canadian grocery Actors
| Actor | Chains | Coverage |
|---|---|---|
| Canadian Grocery Price Comparison API | 16, matched and ranked in one run | Nationwide |
| Loblaws, No Frills, Superstore & Maxi Scraper API - Canada (this Actor) | 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 |
All four retailer Actors emit the same 21 core fields, among them name, price, was_price, is_on_sale, unit_price, comparable_unit_price, package_size, selling_type and the location set. Their datasets concatenate without a mapping layer. Chain-specific extras such as pc_optimum_offer sit alongside those fields.
Feedback
Found a bug or have technical feedback? Open an issue on the Actor's Issues tab.