# Blinkit Products & Prices Scraper (`zapticx/blinkit-products-prices-scraper`) Actor

Scrape Blinkit product data by search term, category or product URL: prices, MRP, discounts, pack sizes, stock levels, delivery ETAs and ratings — for any Indian city, PIN code or coordinates.

- **URL**: https://apify.com/zapticx/blinkit-products-prices-scraper.md
- **Developed by:** [Zapticx](https://apify.com/zapticx) (community)
- **Categories:** E-commerce
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per event

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?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## ⚡ Blinkit Products & Prices Scraper

**Extract live Blinkit products, prices, discounts, stock levels, delivery ETAs and ratings — across any Indian location.**

**🔎 Search products** · **💰 Track prices** · **📦 Check stock** · **📍 Compare locations** · **⚡ Fast extraction**

***

|  |  |
|---|---|
| 🛒 **Products** | Search terms, whole categories, or specific product URLs |
| 💰 **Pricing** | Price, MRP, discount amount & percent, price per 100 g/ml |
| 📦 **Availability** | Stock status plus live inventory counts per store |
| 🚚 **Delivery** | Location-specific delivery ETA in minutes |
| 📍 **Locations** | City name, 6-digit PIN code, or exact coordinates |
| 📊 **Comparison** | The same product priced across as many locations as you like |

> ### 📍 Blinkit prices are set per dark store — not nationally
>
> In a verified three-city run, **26 of the 69 products** found in more than one city were priced differently, and stock diverged completely:
>
> | Product | Delhi | Mumbai | Bengaluru |
> |---|---|---|---|
> | English Oven Zero Maida Multigrain Bread | ₹70 | **₹65** | ₹70 |
> | Amul Moti Toned Milk | ₹33 | — | **₹30** |
> | Amul Taaza Toned Milk | **Out of stock** | 12 in stock | — |
>
> A national average would hide every one of these. This Actor returns **one row per product per location**, so the gaps stay visible.

***

### 🚀 Get started in seconds

Paste this, click **Start**, and you'll have products in about 8 seconds:

```json
{
  "searchQueries": ["chocolate"],
  "locations": ["Delhi"]
}
```

That's the whole setup — no account, no login, no cookies, nothing to configure. To compare cities, just add more locations:

```json
{
  "searchQueries": ["amul milk"],
  "locations": ["Delhi", "Mumbai", "560001"],
  "maxResults": 100
}
```

***

### What you can use it for

- **Price monitoring** — track competitor pricing on FMCG products over time
- **Multi-city price comparison** — quantify how the same SKU is priced across metros
- **Stockout tracking** — live per-store inventory counts, not just an in/out flag
- **Discount monitoring** — find where the MRP-to-price gap is widening
- **Brand monitoring** — follow your own products' listings, ratings and shelf presence
- **Catalogue extraction** — pull an entire Blinkit category for market research

### What makes this different

|  | This Actor | Typical Blinkit scrapers |
|---|---|---|
| Discounts | Numeric `discountAmount` **and** `discountPercent` | A text badge like `"10% OFF"` you have to parse |
| Pack sizes | Parsed to `unitQuantity` + `unitMeasure`, plus price per 100 g/ml | Raw string only |
| Paid placements | Flagged with `isSponsored` | Mixed silently into results |
| Inputs | Search **and** categories **and** product URLs | Usually search only |
| Locations | City name, PIN code, or coordinates | Often raw latitude/longitude only |
| Missing data | Reported as `null` | Sometimes zero-filled or invented |

#### Why `isSponsored` matters

Blinkit injects paid placements into results, heavily concentrated at the top. Measured across 1,000 products collected by this Actor:

| Result positions | Share that are ads |
|---|---|
| 1–12 (first screen) | **58%** |
| 13–24 | 47% |
| 25–50 | 32% |
| 51–100 | 5% |
| 100+ | 0% |

If you sample the first page to measure share of shelf or organic ranking and can't tell ads apart, more than half your sample is advertising rather than ranking.

***

### How it works

1. You give it search terms, categories or product URLs, plus one or more locations.
2. Each location is resolved to coordinates and checked against Blinkit's serviceability API. Unserviceable locations are reported and skipped — the run carries on.
3. For each location, the Actor collects products exactly as a customer in that area would see them, following Blinkit's own pagination.
4. Rows are normalised, de-duplicated per location, and streamed to your dataset.

There is no browser involved, which is why runs are measured in seconds and fit comfortably in 256 MB.

### Input

Everything is optional — the defaults run as-is. Provide at least one of **search terms**, **categories** or **product URLs**.

| Field | Type | Default | What it does |
|---|---|---|---|
| `searchQueries` | array | `["chocolate"]` | Search terms, e.g. `Amul milk`, `Red Bull` |
| `locations` | array | `["Delhi"]` | City, PIN code, or `"28.6139,77.2090"` |
| `maxResults` | integer | `50` | Max products **per location** |
| `categories` | array | `[]` | Category name (`ice cream`) or a Blinkit category URL |
| `productUrls` | array | `[]` | Specific Blinkit product links |
| `brandFilter` | array | `[]` | Keep only these brands |
| `includeOutOfStock` | boolean | `true` | Keep products the store has run out of |
| `includeSponsored` | boolean | `true` | Keep paid placements (always flagged) |
| `maxRequestRetries` | integer | `3` | Retries before giving up on a request |
| `proxyConfiguration` | object | Apify residential | Pre-configured; see [Proxies](#proxies) |

### Output

One row per product, per location.

| Field | Type | Description |
|---|---|---|
| `productId` | string | Blinkit's stable SKU id |
| `name` · `brand` | string | Product name and brand |
| `subcategory` | string | Blinkit's product type, e.g. `Potato Chips` |
| `price` · `mrp` | number | Selling price and maximum retail price, in INR |
| `discountAmount` · `discountPercent` | number | Calculated from MRP and price |
| `packSize` | string | As shown by Blinkit, e.g. `500 ml`, `4 x 250 ml` |
| `unitQuantity` · `unitMeasure` | number · string | Pack size normalised to grams or millilitres |
| `pricePerUnit` · `pricePerUnitBasis` | number · string | Price per 100 g / 100 ml, for fair comparison |
| `availability` · `stockStatus` | boolean · string | Whether it can be bought right now |
| `inventoryCount` | integer | Units on hand at that dark store |
| `deliveryEtaMinutes` | integer | Delivery estimate for that store |
| `rating` | number | Average customer rating, 0–5 |
| `isSponsored` | boolean | `true` for Blinkit paid placements |
| `productUrl` · `imageUrl` · `imageUrls` | string · array | Links and images (up to 5) |
| `variantGroupId` | string | Links variants of the same product |
| `merchantId` · `merchantType` | string | Which dark store served this price |
| `location` · `cityName` · `pincode` | string | The location this row was priced for |
| `latitude` · `longitude` | number | Coordinates used |
| `source` · `sourceTerm` | string | Whether the row came from a search, category or product URL — and which one |
| `currency` | string | `INR` |
| `scrapedAt` | string | ISO 8601 UTC timestamp |

#### Example output

```json
{
  "productId": "212722",
  "name": "Nestle KitKat 4 Fingers Choco Coated Wafer Bar",
  "brand": "Nestle KitKat",
  "subcategory": "Chocolates",
  "price": 30.0,
  "mrp": 30.0,
  "discountAmount": 0.0,
  "discountPercent": 0.0,
  "currency": "INR",
  "packSize": "38.5 g",
  "unitQuantity": 38.5,
  "unitMeasure": "g",
  "pricePerUnit": 77.9221,
  "pricePerUnitBasis": "per 100 g",
  "availability": true,
  "stockStatus": "in_stock",
  "inventoryCount": 50,
  "deliveryEtaMinutes": 13,
  "rating": 4.72,
  "isSponsored": false,
  "productUrl": "https://blinkit.com/prn/nestle-kitkat-4-fingers-choco-coated-wafer-bar/prid/212722",
  "imageUrl": "https://cdn.grofers.com/da/cms-assets/cms/product/....png",
  "variantGroupId": "1097667",
  "merchantId": "36778",
  "merchantType": "express",
  "location": "Delhi",
  "cityName": "Delhi",
  "pincode": null,
  "latitude": 28.6139,
  "longitude": 77.209,
  "source": "search",
  "sourceTerm": "chocolate",
  "scrapedAt": "2026-08-27T14:31:05+00:00"
}
```

The dataset ships with four ready-made views: **Products & prices**, **Compare across locations**, **Discounts & unit economics**, and **Search placement** (which flags paid placements alongside organic results).

> To exclude paid placements from the data altogether, set `includeSponsored` to `false` in the input. Dataset views select columns rather than filtering rows, so the filtering happens at collection time.

### More examples

**Track one product across cities** — the fastest way to see location pricing:

```json
{
  "productUrls": ["https://blinkit.com/prn/amul-gold-milk/prid/14639"],
  "locations": ["Delhi", "Mumbai", "560001"],
  "maxResults": 10
}
```

**Monitor your brand inside a category**, excluding ads:

```json
{
  "categories": ["chips"],
  "brandFilter": ["Lay's", "Bingo"],
  "locations": ["Gurugram"],
  "maxResults": 300,
  "includeSponsored": false
}
```

**Pull a whole category catalogue** for one city:

```json
{
  "categories": ["https://blinkit.com/cn/munchies/cid/1237/940"],
  "locations": ["Mumbai"],
  "maxResults": 2000
}
```

### Multi-location scraping

Blinkit assigns every customer a dark store from their coordinates, and that store sets the price, the stock and the delivery time. Specify a location three ways:

| Input | Example | Resolves to |
|---|---|---|
| City name | `Mumbai` | City centre |
| PIN code | `110001` | The PIN's city |
| Coordinates | `19.1176,72.9060` | That exact point |

City names and PIN codes resolve to a **city-level** point, which is enough to reach the right city's store. For a specific neighbourhood's store, pass coordinates.

Because pricing is per store, rows are de-duplicated **per location**: one SKU scraped for three cities gives three rows. That is what makes the comparison possible.

### Proxies

Blinkit refuses connections from data-centre IP ranges, so runs use Apify **residential** proxies. This is already configured in the default input and you should not need to touch it.

Residential traffic is billed by Apify separately from this Actor's price. Responses are compressed, so 1,000 products moves only about 1 MB — well under a cent.

### Performance

Measured on the Apify platform at 256 MB:

| Run | Products | Time |
|---|---|---|
| Default, 1 location | 50 | 7–19 s |
| 3 locations × 100 | 300 | 30 s |
| 1 location × 1,000 | 1,000 | 2 min 6 s |

Rows stream to the dataset in batches, so memory stays flat no matter how large `maxResults` is.

### Pricing

| Event | Price |
|---|---|
| Actor start | $0.00005 |
| Per product scraped | $0.0015 |

1,000 products costs about **$1.50**, plus a fraction of a cent in residential proxy traffic. You are charged per product actually written to your dataset — a run that finds nothing costs only the start fee.

### Limitations

- **No review counts.** Blinkit's web API publishes an average rating but no number of reviews, so that field is not offered rather than shipped permanently empty.
- **No top-level category field.** Blinkit leaves its category hierarchy blank in the responses used here, so it is omitted. `subcategory` (its product type, e.g. `Potato Chips`) is populated on essentially every row, and `sourceTerm` records which category a row came from.
- **One store per location.** Prices reflect the dark store Blinkit assigns to those coordinates, not a city-wide average.
- **Out-of-stock products may have no price.** Blinkit reports `0` for products a store isn't selling; that is returned as `null`, not as free.
- **City and PIN inputs are city-level.** Use coordinates for neighbourhood precision.
- **Ambiguous category names are rejected, not guessed.** If a name could mean several categories, the run lists the candidates instead of silently scraping the wrong one. Paste a category URL when in doubt.
- Blinkit operates only in India, and only in the cities it serves.

### FAQ

**Do I need a Blinkit account?** No. Only publicly accessible catalogue data is collected — no login, no cart, no personal data.

**Why did I get fewer products than `maxResults`?** Blinkit ran out of matching results for that term at that store. `maxResults` is a ceiling, not a target.

**Can I compare one SKU across cities?** Yes — put its URL in `productUrls` and list several `locations`.

**Why are some rows marked `isSponsored`?** Blinkit injects paid placements into results. They're kept and flagged by default; set `includeSponsored: false` to drop them.

**How do I find a category URL?** Open the category on blinkit.com and copy the address — it looks like `https://blinkit.com/cn/munchies/cid/1237/940`.

**How often should I run it?** Quick-commerce pricing moves daily. Most price-monitoring users schedule a daily run; stockout tracking benefits from a few runs a day.

***

*Collects publicly accessible data only. Blinkit is a trademark of its respective owner; this Actor is not affiliated with or endorsed by Blinkit. You are responsible for ensuring your use of the data complies with applicable laws and Blinkit's terms.*

# Actor input Schema

## `searchQueries` (type: `array`):

What to search for on Blinkit — the same words you would type into its search box. One term per line. Example: chocolate, Amul milk, Red Bull.

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

Where to price the products. Blinkit charges different prices and holds different stock in each city, so add several to compare them side by side. Accepts a city name (Delhi), a 6-digit PIN code (110001), or exact coordinates (28.6139,77.2090).

## `maxResults` (type: `integer`):

Stops each location once it has this many products. With 3 locations and a limit of 100 you get up to 300 rows. Start small to preview the data, then raise it.

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

Scrape whole categories instead of, or as well as, searching. Enter a category name (ice cream, chips, atta) or paste a category URL from Blinkit such as https://blinkit.com/cn/munchies/cid/1237/940. Names are matched against Blinkit's live category list; if a name is ambiguous the run tells you which categories it meant.

## `productUrls` (type: `array`):

Track specific products. Paste Blinkit product links such as https://blinkit.com/prn/amul-gold-milk/prid/14639. Each one is checked in every location you listed, which is the quickest way to compare one product across cities.

## `brandFilter` (type: `array`):

Keep only products matching these brand names, e.g. Amul, Cadbury. Leave empty to keep everything.

## `includeOutOfStock` (type: `boolean`):

Keep products the local store has run out of. Useful for tracking stockouts; turn off if you only want products a customer could buy right now.

## `includeSponsored` (type: `boolean`):

Blinkit mixes paid placements into its results. They are always marked with isSponsored so you can filter them later — turn this off to leave them out of the dataset entirely.

## `maxRequestRetries` (type: `integer`):

How many times to retry a request that fails before giving up on it. The default suits almost every run.

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

Blinkit refuses connections from data-centre servers, so runs need residential proxies. This is already set up correctly — leave it as it is unless you have your own proxy setup.

## Actor input object example

```json
{
  "searchQueries": [
    "chocolate"
  ],
  "locations": [
    "Delhi"
  ],
  "maxResults": 50,
  "categories": [],
  "productUrls": [],
  "brandFilter": [],
  "includeOutOfStock": true,
  "includeSponsored": true,
  "maxRequestRetries": 3,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}
```

# Actor output Schema

## `products` (type: `string`):

One record per Blinkit product per delivery location, with price, MRP, discount, pack size, per-unit price, stock status, live inventory count, delivery ETA, rating and a sponsored-placement flag. Switch between the Products & prices, Compare across locations, Discounts and Search placement views in the Output tab.

# 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 = {
    "searchQueries": [
        "chocolate"
    ],
    "locations": [
        "Delhi"
    ],
    "maxResults": 50,
    "categories": [],
    "productUrls": [],
    "brandFilter": [],
    "includeOutOfStock": true,
    "includeSponsored": true,
    "maxRequestRetries": 3,
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ]
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("zapticx/blinkit-products-prices-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 = {
    "searchQueries": ["chocolate"],
    "locations": ["Delhi"],
    "maxResults": 50,
    "categories": [],
    "productUrls": [],
    "brandFilter": [],
    "includeOutOfStock": True,
    "includeSponsored": True,
    "maxRequestRetries": 3,
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
    },
}

# Run the Actor and wait for it to finish
run = client.actor("zapticx/blinkit-products-prices-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 '{
  "searchQueries": [
    "chocolate"
  ],
  "locations": [
    "Delhi"
  ],
  "maxResults": 50,
  "categories": [],
  "productUrls": [],
  "brandFilter": [],
  "includeOutOfStock": true,
  "includeSponsored": true,
  "maxRequestRetries": 3,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}' |
apify call zapticx/blinkit-products-prices-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,zapticx/blinkit-products-prices-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/boe8aOsEUY8g0lBj0/builds/QBdqPnqZhABSJDpzX/openapi.json
