Piotr VassevPiotr Vassev

How to Collect Instacart Grocery Prices for a Small Basket

Milk prices are only comparable after you match the product type, package size, retailer, and market. A search that mixes a gallon of dairy milk with small plant-based cartons cannot answer which offer is cheaper.

The Grocery Product Scraper for Instacart collects product-page data and limited discovery results from storefronts or cross-retailer searches. I maintain the Actor. This guide starts with milk, then turns suitable results into a repeatable product basket.

How to Collect Instacart Grocery Prices for a Small Basket

Understand the location limitation before running

The current build records postalCode but does not inject it into requests. Instacart defaults to the San Francisco market. Entering a New York ZIP will label the output with that value; it does not establish New York prices or availability. This Actor is therefore unsuitable for a verified ZIP-by-ZIP price comparison in its current form.

Search captures only the first server-rendered results page, usually around fourteen products. Storefront discovery supplies featured items, roughly thirty-two per retailer, rather than a full grocery catalog. Use discovery to find candidates and direct product URLs for the basket you want to revisit.

Discover a small milk sample

An Actor is a tool run on Apify. Open its Input with your Apify account, choose JSON, and enter:

{
  "searchQueries": ["milk"],
  "postalCode": "94105",
  "maxItems": 20,
  "seedFromHome": false
}

maxItems caps products across all input sources; zero removes the cap. Twenty leaves room for the first search page without requesting a broad home-page sweep. seedFromHome: false prevents discovery from expanding to retailer links found on the home page.

Click Start, then open the dataset. Check source and retailerSlug before assuming every row came from the same retailer. Raising maxItems will not create search pagination beyond the first page the Actor captures.

Read size and retailer alongside price

The historical README contains this shortened product-page record:

{
  "productId": "20630136",
  "retailerSlug": "walmart",
  "name": "Great Value 2% Reduced Fat Milk",
  "size": "128 oz",
  "price": 3.48,
  "priceCurrency": "USD",
  "availability": "InStock",
  "source": "pdp",
  "postalCode": "94105"
}

For that historical observation, $3.48 divided by 128 ounces is approximately $0.0272 per ounce. This calculation helps compare another clearly identified 2% dairy-milk package. It does not make organic, lactose-free, or plant-based products interchangeable, and it is not a current offer.

Instacart product dataset with retailers, prices, and sizes

Historical Instacart results show the package and retailer context needed beside each price.

Save a basket you can revisit

Export CSV with productId, retailerSlug, url, name, brand, size, price, priceCurrency, availability, source, and scrapedAt. Preserve priceString and fullPriceString when you need the displayed sale-price context.

Separate milk types, then parse package size into a numeric quantity and unit. Leave unit price blank for ambiguous values such as each; read the product title or page before assuming a quantity. Normalize availability capitalization for filtering while keeping the original, since samples use both InStock and inStock.

Keep product ID and retailer together when deduplicating. A product offered by two retailers is two price observations. Select a few confirmed matches and save their full url values as startUrls objects for the next run. Alternatively, use productIds with defaultRetailerSlug for one named retailer; that retailer setting applies to direct IDs, not a blanket rewrite of every supplied URL.

The saved basket should list the expected products before each run. Report missing products separately instead of silently dropping them from a basket total. Add delivery and other checkout fees only if you verify them separately; the product prices alone are not a delivered-order total.

Cost and missing products

Pricing as of September 6, 2026: $0.005 per returned product, plus a $0.00005 Actor-start event per GB of allocated memory, minimum one event. Twenty products would cost $0.10 in product fees; a fourteen-result search would cost $0.07. Check live pricing when expanding the basket.

Unsupported URL families are skipped. For an empty result, confirm that the input is a /products/... page, a retailer /store/{retailer} page, or /store/s?k=... search. A missing price is not zero, and a missing item is not proof of local out-of-stock status, particularly given the location limitation.

For direct retailer research, the Walmart product guide covers another source. Keep observations from the two sources labeled separately.

The Node.js example shows how to run this Actor from code and retrieve its dataset.

Frequently asked questions

Does postalCode set the live Instacart market?

No. The current build records postalCode but does not inject it into requests. Instacart defaults to the San Francisco market, so the recorded ZIP is not proof of pricing elsewhere.

Can a higher maxItems collect all search results?

No. Cross-retailer search captures only its first server-rendered page, usually about fourteen items. Use known product URLs or product IDs for a repeatable basket.

Piotr Vassev

Piotr Vassev

Founder of FalconScrape. Building production-grade web scraping systems and data automation pipelines for businesses worldwide.

Connect on LinkedIn