Instacart Scraper - Grocery Prices by Retailer
Pricing
from $1.00 / 1,000 run start fees
Instacart Scraper - Grocery Prices by Retailer
Scrape Instacart storefronts for any retailer: product name, price, unit price per lb or oz, pack size and image. Flags weight-estimated prices separately so loose produce is never read as a fixed price.
Pricing
from $1.00 / 1,000 run start fees
Rating
0.0
(0)
Developer
SR
Maintained by CommunityActor stats
0
Bookmarked
1
Total users
1
Monthly active users
4 days ago
Last modified
Categories
Share
Instacart Scraper
Scrape Instacart storefronts for any retailer: product name, price, unit
price per pound or ounce, pack size and image. Give it a retailer slug like
wegmans, costco or publix and it returns the storefront's products.
Why other Instacart scrapers struggle
Instacart serves an unrendered stub to most clients: about 133 KB with no products in it. It renders the full storefront for link previews on purpose, so that a pasted Instacart link shows a product card in a chat app, and this Actor reads that same rendered page.
Nothing underhand, and no browser or solver needed on your side. Ten consecutive fetches came back usable ten times out of ten.
Prices come from the accessibility text
Worth explaining because it is the difference between correct prices and plausible-looking wrong ones.
The visible price is split across three separate spans — $, then 1, then
98 — which a scraper has to glue back together, and which produce nonsense the
moment the markup shifts. Every card also carries a screen-reader line:
Current price: $1.98 each (estimated)
One string, in plain language, and it states the unit as well. This Actor reads that. It is both more robust and more honest than reassembling spans.
Estimated prices are marked, never hidden
Loose produce is sold by weight, and Instacart quotes it against an assumed
weight. Bananas come back as $1.78 with is_estimated: true,
unit_price: 0.89unit_measure: "lb" and size: "About 2.0 lb each".
That flag matters. If you are comparing basket prices or tracking inflation, treating an estimated banana price as a fixed one quietly corrupts the number, and nothing in the raw page forces you to notice. The run summary counts how many rows are estimates.
Fields
| Field | What it is |
|---|---|
product_id | Instacart's own id. Stable, use it to join runs |
name | Product name |
price | Current price |
is_estimated | True when priced against an assumed weight |
price_unit | What the price is per, e.g. each (estimated) |
unit_price, unit_measure | Price per lb, oz, ct and so on |
size | Pack size or approximate weight as printed |
image | Product image |
retailer | Which retailer's storefront the row came from |
url | Instacart product page |
Input reference
| Field | Type | Default |
|---|---|---|
retailer | retailer slug | wegmans |
store_urls | list of full Instacart URLs, overrides retailer | — |
limit | 1-2000 | 100 |
retries | 1-8 | 4 |
Passing several store_urls scrapes several retailers in one run, and every row
carries its retailer, so a cross-retailer price comparison comes out of a
single run. A non-Instacart URL is rejected with a message rather than fetched.
Typical uses
- Grocery price comparison across retailers. Run two or three storefronts in
one go and group by
nameorproduct_idper retailer. Mindis_estimatedwhen comparing fresh produce. - Unit-price analysis.
unit_priceandunit_measureare the fields that make a 12-pack comparable with a 24-pack. - Assortment tracking. Which products a retailer carries on Instacart, and how that changes week to week.
- Inflation and basket tracking. Schedule it and join snapshots on
product_id.
Notes on behaviour
A page that comes back short is the unrendered stub, and it is retried and then
reported as an error rather than returned as an empty store. A storefront that
renders but carries no product cards is reported as no_products. Both cases
are made loud on purpose: a successful-looking run with zero rows is the worst
possible outcome for price data.
Pages are paced with a short randomised gap.
Storefront pages show a slice of a retailer's catalogue, not the entire
inventory. For deeper coverage pass specific aisle or category URLs in
store_urls rather than expecting one storefront to return everything.
Prices are US dollars, and they are Instacart's prices, which frequently differ from the retailer's in-store shelf price.
Finding a retailer slug
The slug is the part of the Instacart URL after /store/. Browse to a retailer
on Instacart and read it off the address bar:
instacart.com/store/wegmans/storefront gives wegmans. Common ones include
costco, publix, kroger, safeway, aldi, sprouts and wegmans.
Availability is regional. Instacart serves different retailers in different
parts of the United States, so a slug that works in one metro may return nothing
useful in another. When that happens the run reports no_products for that
storefront rather than returning an empty dataset with no explanation.
What this Actor does not do
No search. Instacart's search results behave differently from storefront pages and did not render for link-preview agents in testing. Pass aisle or category URLs instead.
No delivery fees, tips or service charges. Those are calculated at checkout
against an address and a basket, and nothing in the storefront page carries
them. The price field is the item price as shown on the storefront.
No stock levels. Instacart does not publish a count. A product that appears on the storefront is being offered; whether the shopper finds it on the shelf is decided at pick time.