How to Scrape Instacart Grocery Prices and Product Data
Instacart aggregates grocery catalogs from many retailers, which makes it a rich public source of grocery price and availability data, priced by store and delivery location. This guide covers what a product listing holds, where the data lives, why every price is location and retailer specific, and how to turn it into a clean price feed without babysitting a scraper. The worked example uses real Instacart products.
What data an Instacart listing holds
Each product carries a name, a price, a size or unit, an availability state, and the retailer it belongs to, all scoped to a delivery location. On a real store at ZIP 92374, listings read like Banana at 0.33 dollars each, Pepsi Soda in a pack at 4.99 dollars, and Werther's Original Hard Caramel Candy at 3.49 dollars. The name, price, size, and retailer are the fields that matter for price intelligence, and the retailer plus location context is what makes each number meaningful.
Where the data actually lives
Instacart runs on a GraphQL backend, so the product data comes from GraphQL operations, for example the ones that load a category or discovery feed, which return items with a name and a formatted price string tied to a store id and a postal code. There is no clean price without that context: the same product carries a different price at a different retailer or a different ZIP. Reading the GraphQL responses is the direct path, but every query has to carry the location and store you actually want.
Skip the build, get the feed
Send us your Instacart target and we will scrape a real sample and send it back, no signup.
Get a free sampleWhy prices are location and retailer specific
Instacart is a marketplace over many grocers, and each grocer sets its own prices per region, so one national number for a product is misleading. A gallon of milk can read differently at two retailers a mile apart, and differently again in another city. That means useful monitoring queries each store and each delivery ZIP you care about separately, rather than pulling one blended figure, which is the single most common mistake people make with grocery data.
Turning it into a price feed
For price monitoring you want one row per product per store, keyed on the product id with the retailer and ZIP captured, refreshed on a schedule that matches how fast the category moves. Keep each run with a date so you can track how a retailer's prices drift, and hold the retailer and location on every row so the feed stays honest and comparable rather than collapsing into a meaningless average.
Build it yourself or have it delivered
For one store and a short list, a careful script against the GraphQL endpoint can get you a sample. The work grows fast once you need many stores and ZIPs, with the location handling, the query variables, and the anti-bot layer to maintain. Past a couple of stores, a done-for-you feed is usually cheaper than the upkeep. You tell us the retailers, locations, and products, and we deliver a clean price feed keyed on product and store and keep it running.
Where each field lives in the GraphQL response
Instacart is a GraphQL app, so the products do not sit in the page HTML, they come back in the responses to named operations, for example the ones that load a category or a discovery feed. Each item in those responses carries a name and a viewSection with a formatted priceString, and the whole response is scoped to a store, identified by a shopId, and a delivery location, passed as a postalCode. The retailer context, which grocer a store belongs to, comes from a separate ShopTags response that maps stores to retailers. The single most important thing to hold onto is that there is no price without the store and ZIP: the same product returns a different priceString at another shopId or another postalCode, so a feed that drops the location is not just incomplete, it is wrong.
Step by step: reading Instacart products
Instacart serves its catalog from a GraphQL backend, and every product is tied to a store and a delivery ZIP. Here it is on a real store at ZIP 92374, where the category feed returned named products with prices. The point to hold onto is that the same product reads a different price at another store or ZIP, so the location is part of the data, not a detail.
| Product | Pepsi Soda (Pack) |
|---|---|
| Price | $4.99 |
| Another product | Banana, $0.33 each |
| Another product | Werther's Original Hard Caramel Candy, $3.49 |
| Store location | ZIP 92374 |
| Source | Instacart GraphQL |
A sample of the clean data we deliver for one product.
The values are clean once you have the response, but reaching it means sending the right GraphQL query with the store and postal code you want, and Instacart gates and rate-limits that access. Getting complete, correct data means querying each store and ZIP you care about, holding the retailer and location on every row so nothing collapses into a meaningless average, and keeping the queries working as the schema changes. We run that for you and deliver a clean price feed keyed on product and store.
Fields worth capturing from Instacart
- Product name
- Price
- Size / unit
- Price per unit
- Availability
- Retailer / store
- Store ZIP / location
- Product ID
- Image URL
Frequently asked questions
Related service: Competitor Price Monitoring
Want a Instacart feed without the build?
Send us the products or pages you need, and we will deliver a clean feed and maintain it. Start with a free sample.
Get a Free Sample