# Instacart Grocery Scraper: Prices, Deals & Stock (US + Canada) (`yugenox/instacart-grocery-scraper`) Actor

Store-level Instacart prices for any US ZIP or Canadian postal code: Costco, Walmart, Safeway, Kroger, Loblaws, T\&T and every other store on Instacart. Search terms or whole-department crawls, sale and regular price, unit price, promotions, stock level, ratings and store hours. No login.

- **URL**: https://apify.com/yugenox/instacart-grocery-scraper.md
- **Developed by:** [Yugenox Corp](https://apify.com/yugenox) (community)
- **Categories:** E-commerce, Automation, Integrations
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.00 / 1,000 results

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## 🛒 Instacart Grocery Scraper: Prices, Deals & Stock (US + Canada)

**Store-level grocery prices from Instacart for any US ZIP code or Canadian postal code.** Costco, Walmart, Safeway, Kroger, Aldi, Publix, Whole Foods, CVS, Loblaws, No Frills, Real Canadian Superstore, T\&T, Sobeys, Metro, Shoppers Drug Mart, LCBO: if a store is on Instacart where you are, this actor can price it.

Enter a location, pick stores, and choose **search terms**, **whole departments**, or just the **list of stores**. You get clean rows with the current price, regular price, discount, promotion text, unit price, stock level, ratings, images and product links.

No login, no browser, no cookies to paste.

***

### ✨ What makes it different

| | |
|---|---|
| 🇨🇦 🇺🇸 **Canada and the US in one actor** | instacart.ca and instacart.com. Postal codes and ZIP codes are routed automatically, so one run can compare Toronto, Vancouver and Chicago. |
| 📍 **Prices for your exact location** | Instacart prices differ by store and by area. Every row carries the postal / ZIP code and the store location it was priced at. |
| 🗂️ **Whole-store crawls** | Catalog mode walks every department and aisle of a store, not just the first page of a search. Thousands of products per store. |
| 🏷️ **Deal detail** | Sale price *and* regular price, % off, "$6 off; limit 5", "Spend $30, save $6", member prices where shown. |
| 🏪 **Store directory** | Every store Instacart serves at a location, with store type, delivery / pickup and 7-day opening hours. |
| 📊 **Search rank** | Search mode records each product's position and flags sponsored placements. |

***

### 🎯 Use cases

- **Price monitoring**: track the same basket at Costco, Walmart and Kroger every week.
- **Competitive pricing for CPG brands**: see your product and competitors' shelf prices and promotions store by store.
- **Deal hunting and flyers**: pull only on-sale items with their discount and promo text.
- **Retail and market research**: assortment by department, private-label share (`isStoreBrand`), ratings.
- **Canadian grocery price comparison**: Loblaws banners, Costco, Walmart, T\&T, Sobeys and Metro side by side.
- **Store coverage maps**: which retailers deliver where, and their hours.
- **Search position tracking**: where your products rank for a keyword, and who is paying for placement.

***

### ⚙️ Input

| Field | What it does |
|---|---|
| **Locations** | Canadian postal codes (`M5V 3L9`, or just `M5V`), US ZIP codes (`60614`), `latitude,longitude`, or `City, ST` (`Seattle, WA`). Postal / ZIP codes are the most precise. |
| **What to scrape** | `search` (products for your search terms), `catalog` (departments / aisles / whole store) or `stores` (the store list). |
| **Search terms** | e.g. `milk`, `paper towels`, `kirkland coffee`. |
| **Stores** | Names, Instacart slugs or store links, e.g. `Costco`, `Walmart`, `Safeway`, `Loblaws`, `T&T`. Empty = every store at the location. |
| **Departments or aisles** | Catalog mode: e.g. `Dairy & Eggs`, `Snacks`, `cheese`. Empty = whole store. |
| **Max results** | Cap for the whole run. |
| **Max products per search term per store** | Default 200. Instacart returns up to about 300 matches per term. With a filter on, the actor keeps reading down the results until this many matching products are saved. |
| **Max products per store** | Catalog mode cap per store. |
| **Max stores per location** | When no stores are named. |
| **Delivery or pickup prices** | Some stores price these differently. |
| **Filters** | Only on sale, only in stock, skip sponsored. |
| **Include opening hours** | Stores mode: next 7 days of hours. |
| **Proxy** | Residential is recommended and is matched to each location's country automatically. |

#### Example: compare milk at three chains in Toronto

```json
{
  "locations": ["M5V 3L9"],
  "mode": "search",
  "searchTerms": ["milk", "eggs"],
  "retailers": ["Loblaws", "Costco", "Walmart"],
  "maxItemsPerSearch": 100
}
```

#### Example: every dairy product at a Chicago Mariano's

```json
{
  "locations": ["60614"],
  "mode": "catalog",
  "retailers": ["Mariano's"],
  "categories": ["Dairy & Eggs"]
}
```

#### Example: which stores deliver in Vancouver, with hours

```json
{
  "locations": ["V6B 1A1"],
  "mode": "stores",
  "includeStoreHours": true
}
```

***

### 📤 Output

One row per product per store. A sale item at Costco (Chicago):

```json
{
  "dataType": "product",
  "name": "NESCAFE Taster's Choice Instant Coffee, House Blend, Light-Medium Roast, 14 oz",
  "brand": "nescafé",
  "size": "each",
  "price": 19.89,
  "priceString": "$19.89",
  "regularPrice": 25.89,
  "isOnSale": true,
  "discountPercent": 23,
  "unitPrice": null,
  "promotion": "$6 off; limit 5",
  "promotions": ["$6 off; limit 5"],
  "inStock": true,
  "stockLevel": "highlyInStock",
  "stockLabel": "Many in stock",
  "isStoreBrand": false,
  "rating": 4.5,
  "ratingCount": 413,
  "imageUrl": "https://d2lnr5mha7bycj.cloudfront.net/product-image/file/large_efdf313a-2c3e-4c03-9d79-f28390c5f4fe.jpg",
  "productUrl": "https://www.instacart.com/store/products/19032111-nescaf-house-blend-instant-coffee-14-0-oz",
  "productId": "19032111",
  "store": "Costco",
  "retailerSlug": "costco",
  "serviceType": "delivery",
  "searchTerm": "coffee",
  "position": 16,
  "isSponsored": false,
  "location": "60614",
  "postalCode": "60614",
  "country": "US",
  "currency": "USD",
  "scrapedAt": "2026-09-24T05:00:21.583Z"
}
```

Also on product rows: `unitPrice` (e.g. `$1.86/100g`), `pricingUnit`, `isEstimatedPrice` and `soldBy` for items sold by weight, `loyaltyPrice`, `category`, `dietary` badges (Organic, Gluten-free…), `nutrition` highlights, `tags`, `maxPerOrder`, `department` and `aisle` (catalog mode), and store / location ids.

Store rows (`dataType: "store"`) carry the store name, slug, type (e.g. `Club/Warehouse Store`), what it sells, delivery / pickup, logo, storefront link and, on request, opening hours.

The dataset has three ready-made views: **Products**, **Deals** and **Stores**. Export as JSON, CSV, Excel or via the API.

***

### ❓ FAQ

**How many products can I get?**
Search mode returns up to about 300 matches per term per store. For more, use Catalog mode: it walks every aisle, and each aisle can list up to 1,000 products, so large supermarkets yield many thousands of products.

**Are the prices the in-store prices?**
They are the prices Instacart shows for that store and location. Many retailers use the same prices online and in store; some add a markup on Instacart. Pickup prices can differ from delivery prices, so pick the one you need.

**Why do I get different prices for different postal codes?**
Chains price by region and by store. That is exactly what the location input is for: every row is tied to the postal / ZIP code and store location it came from.

**My store name did not match.**
Run the same location in `stores` mode to see every store name and slug available there, then use one of those.

**Which proxy should I use?**
Residential (the default) gives the most reliable results. Datacenter proxies also work: addresses that get refused are skipped automatically and the run moves to residential if needed.

**Can I schedule it?**
Yes. Save your input as a task and schedule it daily or weekly for price tracking; connect the dataset to Google Sheets, a webhook or your database.

**Does it need an Instacart account?**
No.

**Is it legal to scrape Instacart?**
This Actor only collects publicly available data: product listings, prices, promotions, stock levels and store details that anyone can see on Instacart's website without an account. Collecting publicly available data is generally legal, but you're responsible for how you use it. You must follow privacy laws such as GDPR, PIPEDA and CCPA, as well as Instacart's terms. If you're unsure, check with a lawyer. More on this: [Is web scraping legal?](https://blog.apify.com/is-web-scraping-legal/)

**Does it access any private data?**
No. Everything comes from pages Instacart shows to any visitor without logging in. It never uses a login, never touches private or restricted accounts, and never reaches password-protected areas.

# Actor input Schema

## `locations` (type: `array`):

Where to shop. Canadian postal codes (M5V 3L9) or just the first three characters (M5V), US ZIP codes (60614), "latitude,longitude" or "City, ST" (Seattle, WA). Postal and ZIP codes are the most precise. Each location gets its own store list and prices: instacart.ca for Canada, instacart.com for the US.

## `mode` (type: `string`):

Search: products matching your search terms (about 300 results per term per store). Catalog: every product in whole departments or aisles, or the whole store. Stores: the list of stores Instacart serves at each location, with store types and optional opening hours.

## `searchTerms` (type: `array`):

Products to look up in Search mode, e.g. "milk", "paper towels", "kirkland coffee". Each term is searched at every selected store. Terms longer than 200 characters are shortened.

## `retailers` (type: `array`):

Store names, Instacart store slugs or store links, e.g. Costco, Walmart, Safeway, Kroger, Whole Foods, Loblaws, No Frills, T\&T, Sobeys, Metro, or https://www.instacart.ca/store/costco-canada/storefront. Leave empty to use every store that serves the location (use "Max stores per location" to cap it). A name that is not available at a location is skipped with a note listing the stores that are.

## `categories` (type: `array`):

Which departments or aisles to crawl in Catalog mode, e.g. "Dairy & Eggs", "Snacks", "cheese", "frozen". Leave empty to crawl the whole store.

## `maxItems` (type: `integer`):

Maximum number of rows for the whole run. Leave empty for no limit.

## `maxItemsPerSearch` (type: `integer`):

Search mode: how many products to save for each term at each store. Instacart returns up to about 300 matches per term. With filters on (e.g. only on sale), the actor reads further down the results until this many matching products are saved.

## `maxItemsPerStore` (type: `integer`):

Catalog mode: stop crawling a store after this many products. Leave empty for the whole store.

## `maxStoresPerLocation` (type: `integer`):

When "Stores" is empty, use at most this many stores per location (in Instacart's own order). Leave empty for all.

## `serviceType` (type: `string`):

Some stores price delivery and pickup differently on Instacart. Pick which prices you want; a store that offers only one uses that one.

## `onlyOnSale` (type: `boolean`):

Keep only products with a reduced price or store sale. Some stores (for example Loblaw banners and T\&T in Canada) show few or no sale prices on Instacart.

## `onlyInStock` (type: `boolean`):

Drop products Instacart marks as out of stock at that store.

## `skipSponsored` (type: `boolean`):

Search mode: leave out paid placements (they are flagged with isSponsored otherwise).

## `includeStoreHours` (type: `boolean`):

Add the next 7 days of opening hours to each store row.

## `country` (type: `string`):

Only matters for city names without a state or province. Postal codes and ZIP codes pick the country by themselves.

## `maxConcurrency` (type: `integer`):

Parallel connections, each with its own IP address.

## `proxyConfiguration` (type: `object`):

Residential proxies are recommended; the country is matched to each location automatically. Datacenter proxies work as well: blocked addresses are skipped, and the run switches to residential if too many are blocked.

## Actor input object example

```json
{
  "locations": [
    "M5V 3L9"
  ],
  "mode": "search",
  "searchTerms": [
    "milk"
  ],
  "retailers": [
    "loblaws"
  ],
  "maxItems": 50,
  "maxItemsPerSearch": 200,
  "serviceType": "delivery",
  "onlyOnSale": false,
  "onlyInStock": false,
  "skipSponsored": false,
  "includeStoreHours": false,
  "country": "auto",
  "maxConcurrency": 6,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}
```

# Actor output Schema

## `results` (type: `string`):

Every row as JSON: product rows carry price, regular price, unit price, promotions, stock and the store they were priced at; store rows carry the store directory fields.

## `resultsCsv` (type: `string`):

The same rows as CSV, for a spreadsheet or price-tracking sheet.

## `productsTable` (type: `string`):

Product rows narrowed to the key columns: product, brand, store, price, regular price, promotion, unit price and stock.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "locations": [
        "M5V 3L9"
    ],
    "searchTerms": [
        "milk"
    ],
    "retailers": [
        "loblaws"
    ],
    "maxItems": 50,
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ]
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("yugenox/instacart-grocery-scraper").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "locations": ["M5V 3L9"],
    "searchTerms": ["milk"],
    "retailers": ["loblaws"],
    "maxItems": 50,
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
    },
}

# Run the Actor and wait for it to finish
run = client.actor("yugenox/instacart-grocery-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "locations": [
    "M5V 3L9"
  ],
  "searchTerms": [
    "milk"
  ],
  "retailers": [
    "loblaws"
  ],
  "maxItems": 50,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}' |
apify call yugenox/instacart-grocery-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,yugenox/instacart-grocery-scraper"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/o4RNQE7zfcqRT4MTv/builds/Kmy6T4tJV60CPVUsM/openapi.json
