Skip to content
Menu
Data

Build a Blinkit price tracker in Python with the Rewalto API

Yes, you can track Blinkit prices and stock by pin code in 64 lines of Python: one authenticated call to GET /v1/data/observations, a small SQLite table, and a diff of each product’s two newest readings. It reads Rewalto’s dated Blinkit records, not Blinkit’s own API, and every account gets 1,000 free credits a month.

By , FounderPublished Last updated Part of the quick commerce data and api guideMore on quick commerce

What you need, and what it costs

The tracker is one Python file. It asks the Rewalto API for the Blinkit readings at one pin code, keeps each one in a SQLite file with the time it was read, and then prints every product whose price or stock changed between its two newest readings. You never open Blinkit and you never run a browser. Everything comes from one documented read, GET /v1/data/observations.

  • Python 3.9 or newer, and the requests package. SQLite ships with Python.
  • A Rewalto API key with the data:read scope. Every account gets 1,000 free credits a month.
  • A six-digit pin code Rewalto holds for Blinkit. The live list is below and on the Blinkit data page.

Reads cost 1 credit per 10 records delivered, rounded up per page. A page of 100 records is 10 credits. Reading the same records again within seven days is free, and a page that comes back empty costs nothing. With the free 1,000 credits a month that is 10,000 records; that figure is arithmetic from the published rate, not a promise of what one pin code holds. The credits reference has the full rules.

The current pin codes, refresh and rate for Blinkit are read from the Rewalto data catalogue each time this page is served. The commerce data page lists them too.

The whole script, 64 lines

This is the exact file we ran against the live API on 1 November 2026. Save it as blinkit_tracker.py. It takes three arguments: the pin code, how many days back to read, and an optional brand. The key comes from the environment, never from the file.

blinkit_tracker.py
import os, sqlite3, sys, time
from datetime import datetime, timedelta, timezone
import requests

BASE = "https://api.rewalto.com"
HEAD = {"Authorization": f"Bearer {os.environ['REWALTO_API_KEY']}"}  # keep the key out of the code
PIN = sys.argv[1] if len(sys.argv) > 1 else "560001"  # a six-digit pin code Rewalto holds for Blinkit
DAYS = int(sys.argv[2]) if len(sys.argv) > 2 else 1  # read only the last day; the API default is 30
BRAND = sys.argv[3] if len(sys.argv) > 3 else None  # exact text, case-sensitive, as Blinkit wrote it
MAX_PAGES = 10  # at most 1,000 records, 100 credits, per run

def read_blinkit(pincode, since, brand=None):
    """Yield Blinkit readings for one pin code, newest first, following the cursor."""
    params = {"retailer": "blinkit", "pincode": pincode, "from": since, "limit": "100"}
    if brand:
        params["brand"] = brand
    pages = tries = 0
    while pages < MAX_PAGES:
        r = requests.get(f"{BASE}/v1/data/observations", params=params, headers=HEAD, timeout=60)
        if r.status_code == 402:
            sys.exit("Out of credits: " + r.json()["error"]["message"])
        if r.status_code in (429, 500, 503) and tries < 4:  # retry the same page a few times
            tries += 1
            time.sleep(int(r.headers.get("Retry-After", 2 ** tries)))
            continue
        r.raise_for_status()
        body, pages, tries = r.json(), pages + 1, 0
        print(f"page {pages}: {len(body['data'])} records, {body['meta']['credits']['charged']} credits")
        yield from body["data"]
        if not body["page"]["nextCursor"]:
            return
        params["cursor"] = body["page"]["nextCursor"]  # same filters, next page

def main():
    db = sqlite3.connect("blinkit_prices.db")
    db.execute("""create table if not exists price (
        sku text, pin text, observed_at text, title text, brand text,
        price_paise integer, mrp_paise integer, in_stock integer,
        primary key (sku, pin, observed_at))""")
    since = (datetime.now(timezone.utc) - timedelta(days=DAYS)).strftime("%Y-%m-%dT%H:%M:%SZ")
    new = 0
    for row in read_blinkit(PIN, since, BRAND):
        stock = row["inStock"]  # true, false or null; null stays null, never "out of stock"
        new += db.execute("insert or ignore into price values (?,?,?,?,?,?,?,?)", (
            row["retailerSku"], row["pincode"], row["observedAt"], row["title"], row["brand"],
            row["priceMinor"], row["mrpMinor"], None if stock is None else int(stock))).rowcount
    db.commit()
    print(f"stored {new} new readings for pin code {PIN}")

    # What changed: each product's newest reading against the one before it.
    q = """select title, observed_at, price_paise, in_stock, prev_price, prev_stock from (
             select title, observed_at, price_paise, in_stock,
               lag(price_paise) over (partition by sku order by observed_at) as prev_price,
               lag(in_stock) over (partition by sku order by observed_at) as prev_stock,
               row_number() over (partition by sku order by observed_at desc) as rn
             from price where pin = ?) where rn = 1"""
    for title, at, price, stock, prev_price, prev_stock in db.execute(q, (PIN,)):
        if None not in (price, prev_price) and price != prev_price:
            print(f"PRICE  {title}: Rs {prev_price / 100:.2f} to Rs {price / 100:.2f} (read {at})")
        if None not in (stock, prev_stock) and stock != prev_stock:
            print(f"STOCK  {title}: {'back in stock' if stock else 'out of stock'} (read {at})")

if __name__ == "__main__":
    main()
Set up and run it
python3 -m venv venv && . venv/bin/activate
pip install requests
python blinkit_tracker.py 560001 7 Dove

The steps below take the script apart in the order it runs. If you only want it working, the two blocks above are enough.

Step 1: get a key and check it

Create an API key in your Rewalto account with only the data:read scope, and keep it in your shell or your secret store, not in the code. Then check it. The identity call costs nothing and starts no data read; it tells you which organisation the key belongs to and which scopes it carries.

Check the key
export REWALTO_API_KEY="rwk_..."   # your key, from your own secret store
curl https://api.rewalto.com/v1/whoami -H "Authorization: Bearer $REWALTO_API_KEY"

A 401 here means the key is missing, mistyped, expired or revoked. Fix that before you go further. The first request guide and the API keys reference cover creating, rotating and revoking keys.

Step 2: read one pin code

If you want to see the shape of a record before you spend anything, call the free sample first. It needs no key and returns real rows that are each at least seven days old.

Free sample, no key
curl "https://api.rewalto.com/v1/data/samples?dataset=price_history"

The function read_blinkit in the script makes the paid read. It sends retailer=blinkit, the pin code, a from time and limit=100, plus the brand when you give one. The brand is matched exactly and is case-sensitive, so write it as Blinkit writes it. Without from the API reads the last 30 days, which at a busy pin code is a lot of records; the script asks for one day unless you say otherwise.

Each record carries the retailer, the retailer’s product id, the pin code, the time it was read, the title, brand and pack size, the price and MRP, the currency, the in-stock flag and the source address. Prices come in paise: divide by 100 for rupees. A price that could not be read is null, never 0. The data reference lists every field and filter.

Step 3: follow the cursor and respect the limits

A response holds up to limit records, newest first, and a page.nextCursor value. When it is not null, the script sends it back as cursor with exactly the same filters to get the next page. A cursor sent with different filters is refused, so never change the brand or the time window halfway through a loop.

Each page reports what it cost in meta.credits.charged, and the script prints it, so you see the spend as it happens. MAX_PAGES stops a run after ten pages, at most 100 credits, however much the pin code holds. Raise it once you know what a run costs you.

Two answers stop or slow the loop. A 402 means your credits cannot cover the next page, and the script exits rather than retrying. A 429 means you hit the rate limit; the script waits for the time in the Retry-After header and asks for the same page again. It does the same, a few times only, for a 500 or 503, which the contract marks as safe to retry a bounded number of times. The errors reference lists every code.

Step 4: store every reading

The table is keyed by product id, pin code and the time of the reading, and the insert ignores a row it already has. That makes a second run over the same window harmless: nothing is stored twice, and the API does not charge again for records you read in the last seven days.

SQLite is enough for one pin code and a handful of brands for a long time. When you track many pin codes, or want a dashboard on top, move the same table to Postgres or any database you already run. Keep the same three columns as the key, and the rest of the script does not change.

Keep the time of every reading. A price without its time cannot be checked, and it cannot be set beside tomorrow’s reading. Keep prices in paise as whole numbers, so nothing is lost to rounding. And never turn a missing value into a guess: a null price stays null, and a null stock flag stays null rather than becoming “out of stock”.

Step 5: print what changed

The last query uses two window functions. For each product, lag finds the reading before the newest one and row_number picks the newest. When both prices are known and differ, the script prints a price line; when both stock flags are known and differ, it prints a stock line. A product read only once prints nothing, because there is nothing to compare yet.

Here is the output of the run on 1 November 2026 at 5:49 pm IST: pin code 560001, the last seven days, brand Dove, starting from an empty file. It read 176 records for 18 credits and found 11 price changes. These are that run’s numbers, kept as an example; your run will show what Blinkit showed at your pin code on your day. The script prints each reading’s time exactly as the API sends it; below, those times are shown in IST.

Example run, 1 November 2026: python blinkit_tracker.py 560001 7 Dove
page 1: 100 records, 10 credits
page 2: 76 records, 8 credits
stored 176 new readings for pin code 560001
PRICE  Dove Intense Repair Hair Conditioner: Rs 235.00 to Rs 220.00 (read 1 Nov 2026, 2:38 AM IST)
PRICE  Dove Daily Shine Hair Conditioner: Rs 214.00 to Rs 200.00 (read 1 Nov 2026, 2:38 AM IST)
PRICE  Dove Body Love Supple Bounce Body Lotion (400 ml): Rs 416.00 to Rs 384.00 (read 29 Oct 2026, 7:17 AM IST)
PRICE  Dove 3% Vitamin C Brightening Body Wash: Rs 340.00 to Rs 320.00 (read 1 Nov 2026, 1:52 AM IST)
PRICE  Dove 5% Niaciamide Serum Body Wash: Rs 340.00 to Rs 320.00 (read 29 Oct 2026, 7:19 AM IST)
PRICE  Dove Exfoliating Body Wash: Rs 465.00 to Rs 434.00 (read 29 Oct 2026, 7:19 AM IST)
PRICE  Dove Peptide Bond Strength Leave in Conditioner: Rs 315.00 to Rs 337.00 (read 30 Oct 2026, 12:09 AM IST)
PRICE  Dove Original Deodorant Roll on (for Women): Rs 182.00 to Rs 156.00 (read 1 Nov 2026, 2:02 AM IST)
PRICE  Dove Beautiful Curls 10-In-1 Hair Mask: Rs 247.00 to Rs 232.00 (read 1 Nov 2026, 1:31 AM IST)
PRICE  Dove 10 in 1 Peptide Bond Strength Hair Mask: Rs 234.00 to Rs 220.00 (read 1 Nov 2026, 1:30 AM IST)
PRICE  Dove Hair Fall Rescue Conditioner: Rs 235.00 to Rs 220.00 (read 1 Nov 2026, 2:38 AM IST)

The same command run again two minutes later stored nothing new and was charged nothing, because every record had already been read within seven days:

Second run, 1 November 2026
page 1: 100 records, 0 credits
page 2: 76 records, 0 credits
stored 0 new readings for pin code 560001

Step 6: run it daily

Blinkit is read every day, so a daily run is enough. Keep the key in a file only you can read, such as .env with the line export REWALTO_API_KEY="...", and let cron start the script each morning. Ask for one day back, so each run reads only what is new.

crontab line
30 7 * * * cd $HOME/blinkit-tracker && . ./.env && venv/bin/python blinkit_tracker.py 560001 1 Dove >> tracker.log 2>&1

Send the output to a log file, as the line above does, and read it once a week at first. A run that stops early prints the reason on its last line: out of credits, a key problem or a page the API could not answer after a few tries. Nothing is lost when a run fails, because the next run asks for the same window again and the database ignores what it already has. If you miss a few days, run the script once by hand with more days back and it fills the gap.

The cost follows from the rate. In the example run one brand at one pin code came to 176 records over seven days, so a daily run for the same brand would read about a seventh of that, a few credits a day. Arithmetic from the published rate: 1,000 free credits a month cover 10,000 records, so a few brands at a few pin codes fit inside the free credits. A whole pin code with no brand filter can hold far more, which is what MAX_PAGES is for.

Make it better

  • Several pin codes in one read: send location with a city, area or dark store id from the free location lookup, plus confirmPins with the number of pin codes it resolves to. The API refuses a different number, so you always agree to the size of the read first.
  • The same product across apps: filter by productId instead of brand, and drop the retailer filter, to set a product’s Blinkit readings beside its readings on other apps.
  • One product at one place: filter by retailerSku together with the retailer, since a retailer’s product id is unique only within that retailer.
  • A quick check by hand: the free pin-code availability tool checks one brand at one pin code with no key.
  • From an AI agent: the MCP server (preview) has a list_observations tool that reads the same records at the same rates; see the MCP guide (preview).

What this tracker cannot tell you

The readings describe what Blinkit showed shoppers at the pin codes and times read. They are not sales and not demand, and they say nothing about how fast a product moves. A missing reading is unknown, not out of stock. A price is what a shopper saw at that pin code and time, before coupons, bank offers, membership prices and delivery fees, so it is not a checkout total.

Rewalto reads Blinkit’s public search results the way a shopper sees them, and keeps each reading with its source address, its time and an evidence hash of the response read; the response itself is not kept. Rewalto is not affiliated with or endorsed by Blinkit, and is not a partner of Blinkit. Blinkit is a trademark of its owner. Rewalto’s API serves what Blinkit shows shoppers, read from its public pages with the pin code and time of each reading. It is not Blinkit’s own API or feed.

If you are still weighing whether to build your own collection instead, the Blinkit scraper alternative guide sets out the work a scraper keeps asking for.

Troubleshooting

  • 401: the key is missing, wrong, expired or revoked. Run the identity check from step 1.
  • 403: the key lacks the data:read scope. Create one that has it.
  • 402: the credits left cannot cover the next page, so the API sends no data and the script stops. Credits reset each month.
  • 429: too many requests. Wait for the reset in the Retry-After header and try the same page again.
  • An empty list: nothing matched your filters in that window. It costs nothing. Check the brand’s exact spelling and widen the days.
  • 400 on a later page: the cursor was sent with different filters. Start the loop again without a cursor.
  • 500 or 503 that keeps coming back: quote the x-request-id header of the response when you report it.

See everything Rewalto reads, and start free, at rewalto.com.

Common questions

How do I build a Blinkit price tracker in Python?

Call GET /v1/data/observations on the Rewalto API with retailer=blinkit and a six-digit pin code, store each reading with its time in a database, and compare each product's two newest readings. The tutorial on this page has the full script, and the output of a dated run.

Is there a Blinkit API I can use for prices?

Rewalto's API gives you Blinkit prices by pin code. It serves what Blinkit shows shoppers, read from its public pages and kept with the pin code and time of each reading. It is not Blinkit's own feed.

How much does it cost to track Blinkit prices with the API?

Reads cost 1 credit per 10 records delivered, and every account gets 1,000 free credits a month, which is 10,000 records at that rate. Re-reading the same records within 7 days is free, and an empty page costs nothing. Rupee prices on the site are excluding GST.

Can I track Blinkit stock as well as price?

Yes. Every reading carries an in-stock flag, which is true, false or null when the page had no signal. A missing reading means unknown, not out of stock.

Which Blinkit pin codes can I track?

The pin codes Rewalto holds for Blinkit are listed in the catalogue and on the Blinkit data page, and a fresh read can be requested at any pin code. The rate is shown before a read runs.

Can an AI agent do this instead of a script?

Rewalto's MCP server is in preview at mcp.rewalto.com/mcp, and its list_observations tool reads the same records at the same rates. A script is the safer choice for a daily job today.

Does this scrape Blinkit?

No. The script reads Rewalto's API only. Rewalto reads Blinkit's public search results the way a shopper sees them and keeps the records; you never touch Blinkit.

Start with the question you need to answer

Check the current data catalogue, then review the coverage and dates against your question. The research in an older guide does not establish that a service is available today.

Related guides

See it in real data.

Ask about a city, a product or a dataset. The answer is free, and any fresh run shows its cost first.