# H-E-B Scraper: Store Prices, Deals, Aisles & Stock by ZIP (`zaiq/heb-scraper`) Actor

Scrape H-E-B (heb.com) products and prices for any Texas store by ZIP code or store number: shelf, sale, curbside and unit prices, weekly ad and digital coupon flags, aisle location, stock, UPC, size and SNAP eligibility. Search terms, categories or product URLs. Pay per product.

- **URL**: https://apify.com/zaiq/heb-scraper.md
- **Developed by:** [Zaiq](https://apify.com/zaiq) (community)
- **Categories:** E-commerce, Automation
- **Stats:** 5 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $4.80 / 1,000 products

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
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.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## 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.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## H-E-B Scraper: Store Prices, Deals, Aisles and Stock by ZIP Code

Get H-E-B products with the prices of the Texas stores you choose: the shelf price, sale price, curbside pickup price
and unit price, weekly ad, price cut and digital coupon flags (with coupon details), the aisle, stock, UPC, size,
category and SNAP eligibility. Choose stores by ZIP code or store number; H-E-B prices differ from store to store, and
every row says which store its price belongs to.

### What it does

- Finds the nearest H-E-B stores to each ZIP code you give (H-E-B, H-E-B plus!, Central Market, Joe V's Smart Shop and
  Mi Tienda), as many per ZIP code as you ask for, or uses the store numbers you give.
- Runs your search terms, category pages and product URLs at every store, 60 products a page, following pages until
  your limit.
- Returns one row per product per store: shelf price, sale price, curbside price, a precise unit price, UPC, brand,
  size, aisle location, stock status, weekly ad and price cut flags, digital coupon flag, category path, image, product
  URL, SNAP eligibility and the product description.
- With product details on, also returns the aisle number (for example "Aisle 10, A8") and each digital coupon's text
  and expiry date.
- Deals only: returns just the products on sale, in the weekly ad, with a price cut or with a digital coupon.
- The same product found twice at one store (for example by two search terms) is returned and charged once.

The data comes from what heb.com shows for each store. No login and no H-E-B account are used.

### Who uses it

- **Price monitoring and retail analysts** following H-E-B's prices, price cuts and coupons across Texas.
- **Consumer brands** checking shelf price, promotions and stock of their products store by store.
- **Shopping, budgeting and price comparison apps** that need store-level prices matched by UPC.
- **Researchers** comparing grocery prices between Texas cities.

### Example

H-E-B Reduced Fat 2% Milk, 1 gallon (UPC 041220069392), at four stores, from a run on 4 October 2026 (ZIP codes 78704,
77002, 78205 and 75201):

| Store | City | Shelf price | Curbside price | Aisle |
|---|---|---|---|---|
| SoCo H-E-B (#754) | Austin | $3.81 | $4.00 | In Dairy on the Back Wall, A25 |
| Buffalo Heights H-E-B (#744) | Houston | $3.46 | $3.63 | In Dairy on the Back Wall |
| South Flores Market H-E-B (#718) | San Antonio | $4.07 | $4.27 | In Dairy on the Back Wall |
| H-E-B Irving (#817) | Irving | $2.39 | $2.51 | In Dairy on the Back Wall |

The same gallon of milk cost 70% more in San Antonio than in Irving that day.

Other test runs on 4 October 2026:

- 350 products for the search term "cheese" at South Flores Market H-E-B, San Antonio, in 28 seconds: 22 on sale, 16
  with a digital coupon, 6 out of stock at that store.
- Five ZIP codes with two stores each: eight stores in Austin, Houston, San Antonio, Irving and Plano. The fifth ZIP
  code, in New York, came back as a free row saying there is no H-E-B store near it.
- Deals only with product details, SoCo H-E-B, Austin: cereals with coupons such as "$1 off" or "Buy this, get that
  free", each with its coupon text, expiry date and aisle number.

### Input

```json
{
  "searchTerms": ["milk", "tortillas"],
  "categoryUrls": ["https://www.heb.com/category/shop/dairy-eggs/milk/490016/490053"],
  "productUrls": ["https://www.heb.com/product-detail/h-e-b-reduced-fat-2-milk-1-gal/314125"],
  "zipCodes": ["78704", "77002"],
  "storesPerZip": 1,
  "maxItemsPerQuery": 100,
  "maxItems": 1000,
  "onSaleOnly": false,
  "includeDetails": false
}
```

| Field | What it does |
|---|---|
| `searchTerms` | Words to search for, as a shopper would type them. Each term is searched at every store. |
| `categoryUrls` | Category pages such as `https://www.heb.com/category/shop/dairy-eggs/milk/490016/490053`. |
| `productUrls` | Product pages, or H-E-B product numbers such as `314125`. Each is checked at every store. |
| `zipCodes` | Texas ZIP codes. Each gives the nearest H-E-B stores within 50 miles. |
| `storesPerZip` | How many of the nearest stores to use for each ZIP code (default 1, up to 10). |
| `storeIds` | H-E-B store numbers, for example `754` (SoCo H-E-B, Austin). Shown on every row as `storeId`. |
| `maxItemsPerQuery` | Products per search term or category at each store (default 100). |
| `maxItems` | Products in total (default 1,000; 0 means no limit, your spending limit still applies). |
| `onSaleOnly` | Only products on sale, in the weekly ad, with a price cut or with a digital coupon. |
| `includeDetails` | Open each product's page for the aisle number and coupon details (default off; one extra request per product). |
| `includeFailures` | Add a free row for each ZIP code without a store, empty search or unreadable product (default on). |
| `maxConcurrency`, `proxyConfiguration` | Jobs at once (default 4) and the proxy (US residential by default). |

### Output

One row per product per store. A row from the run above, with the description shortened:

```json
{
  "retailer": "H-E-B",
  "banner": "H-E-B",
  "storeId": "754",
  "storeName": "SoCo H-E-B",
  "storeAddress": "2400 S. Congress Ave.",
  "storeCity": "Austin",
  "storeState": "TX",
  "storeZip": "78704",
  "requestedZip": "78704",
  "storeDistanceMiles": 1.0,
  "productId": "314125",
  "upc": "041220069392",
  "sku": "4122006939",
  "name": "H-E-B Reduced Fat 2% Milk",
  "brand": "H-E-B",
  "size": "1 gal",
  "sizeQuantity": 1,
  "sizeUnit": "gal",
  "price": 3.81,
  "regularPrice": 3.81,
  "salePrice": null,
  "onSale": false,
  "currency": "USD",
  "unitPrice": 0.0298,
  "unitPriceUnit": "fl oz",
  "unitPriceComputed": true,
  "promotionText": null,
  "couponAvailable": false,
  "coupons": [],
  "inStock": true,
  "stockLevel": "IN_STOCK",
  "aisle": "In Dairy on the Back Wall, A25",
  "category": "Milk",
  "categoryPath": ["Dairy & eggs", "Milk"],
  "imageUrl": "https://images.heb.com/is/image/HEBGrocery/prd-medium/000314125.jpg",
  "productUrl": "https://www.heb.com/product-detail/h-e-b-reduced-fat-2-milk/314125",
  "snapEligible": true,
  "soldByWeight": false,
  "source": "https://www.heb.com/product-detail/h-e-b-reduced-fat-2-milk-1-gal/314125",
  "sourceType": "product",
  "scrapedAt": "2026-10-04T16:01:27Z",
  "charged": true,
  "curbsidePrice": 4.0,
  "onWeeklyAd": false,
  "ownBrand": true,
  "description": "Made in Texas by farmers who pledge no artificial growth hormones (rBST) ..."
}
```

- `price` is the store's shelf price today: the sale price when there is one, otherwise the regular price.
  `curbsidePrice` is the same product ordered for curbside pickup or delivery, which H-E-B prices slightly higher.
- `unitPrice` is worked out from the price and the size (per fluid ounce, ounce or count; `unitPriceComputed: true`).
  Where the size is unclear, heb.com's own unit price is used instead, which it rounds to the cent
  (`unitPriceComputed: false`).
- `promotionText` names the promotion: "In the weekly ad", "Price cut", or the sale and regular price.
  `couponAvailable` is true when a digital coupon applies; with product details on, `coupons` lists each one's text and
  expiry date. Coupons must be clipped in an H-E-B account to be used.
- `stockLevel` is heb.com's stock status for the store (`IN_STOCK`, `OUT_OF_STOCK`); out-of-stock products still have
  their price.
- `requestedZip` is the ZIP code you gave that led to the store, and `storeDistanceMiles` how far the store is from
  it.
- Failure rows have `error` set and `charged: false`. The key-value store record `RUN-SUMMARY` lists the stores used,
  failures, stop reason and traffic.

### Where the prices come from

Each price is the price heb.com shows for that store at the time in `scrapedAt`, for shopping in the store; curbside
prices are in `curbsidePrice`. Prices differ between stores (see the example above) and change with weekly ads, so
always use the store columns with the price. Coupon savings are not taken off `price`.

### Use it from code, automations and AI agents

- **API**: run it and get the results in one call: `POST https://api.apify.com/v2/acts/zaiq~heb-scraper/run-sync-get-dataset-items?token=YOUR_TOKEN` with the input as JSON. The API tab on this page has ready-made Python, JavaScript and cURL examples.
- **Python** (`pip install apify-client`):

```python
from apify_client import ApifyClient

client = ApifyClient("YOUR_TOKEN")
run = client.actor("zaiq/heb-scraper").call(run_input={'searchTerms': ['milk'], 'zipCodes': ['78704'], 'maxItemsPerQuery': 20})
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)
```

- **No code**: connect it to Google Sheets, Zapier, Make or n8n from the Integrations tab, schedule runs in Apify Console, and get a webhook when a run finishes.
- **AI agents (MCP)**: add it as a tool to Claude, Cursor or any MCP client through Apify's MCP server: `https://mcp.apify.com?tools=zaiq/heb-scraper`.

### Pricing

You pay only for product rows: $0.006 per product ($6 per 1,000), Apify platform usage included. Each run also has a start fee of $0.01 per GB of memory ($0.02 at the default 2 GB), which covers opening a real browser to pass H-E-B's bot check. Failure rows,
duplicates and retries are free. Your spending limit for the run is respected: the run stops cleanly before going over
it.

### Limits

- H-E-B stores are in Texas; a ZIP code with no store within 50 miles returns a free row saying so.
- heb.com is protected against bots. Each run opens heb.com once in a real browser (about 10 seconds) before reading
  any data, and again every ten minutes or when the site starts refusing an address. If heb.com refuses every address
  tried, the affected searches come back as free failure rows.
- Product details add one request per product and make runs slower; leave them off for price monitoring at scale.
- No ratings or reviews: heb.com does not show them with prices.

### FAQ

**Do I need an H-E-B account?** No. Nothing is signed in to, and coupons are reported, not clipped.

**How do I find a store number?** Run once with a ZIP code: every row has `storeId`, `storeName` and the address.

**Why do curbside and shelf prices differ?** H-E-B charges a little more for curbside pickup and delivery; both are
returned.

**Can I scrape every product in a category?** Yes: give the category URL and set the per-query and total limits high
enough. Each page holds 60 products.

# Actor input Schema

## `searchTerms` (type: `array`):

Words to search for on heb.com, as a shopper would type them (for example milk, organic eggs, sourdough bread). Each term is searched at every store.

## `zipCodes` (type: `array`):

Prices differ by store. Texas ZIP codes. Each ZIP code gives the nearest H-E-B stores (also Central Market, Joe V's and Mi Tienda) within 50 miles; set how many with Stores per ZIP code.

## `storeIds` (type: `array`):

Optional, instead of or as well as ZIP codes. H-E-B store numbers such as 754 (SoCo H-E-B, Austin) or 744 (Buffalo Heights, Houston). The store number is shown on each row as storeId.

## `storesPerZip` (type: `integer`):

How many of the nearest stores to scrape for each ZIP code (nearest first).

## `categoryUrls` (type: `array`):

Optional. Category pages from heb.com, such as https://www.heb.com/category/shop/dairy-eggs/milk/490016/490053 (the last two numbers identify the category).

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

Optional. Product pages such as https://www.heb.com/product-detail/h-e-b-reduced-fat-2-milk-1-gal/314125, or H-E-B product numbers such as 314125. Each is checked at every store.

## `maxItemsPerQuery` (type: `integer`):

Stop each search term or category after this many products at each store. Pages are followed until then.

## `maxItems` (type: `integer`):

The run stops after this many product rows. 0 means no limit (your spending limit still applies).

## `onSaleOnly` (type: `boolean`):

Only products on sale, in the weekly ad, with a price cut or with a digital coupon.

## `includeDetails` (type: `boolean`):

Also open each product's page: adds the aisle number (for example 'In Dairy on the Back Wall, A25'), digital coupon details, the full category path and nutrition-related text. One extra request per product.

## `includeFailures` (type: `boolean`):

Add a free row (with an error field) for each ZIP code without a store, search without results or product that could not be read. Switch off to keep only product rows.

## `maxConcurrency` (type: `integer`):

How many searches, categories or product lists run at the same time.

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

US residential proxies are used by default (the sites serve US visitors).

## Actor input object example

```json
{
  "searchTerms": [
    "milk"
  ],
  "zipCodes": [
    "78704"
  ],
  "storesPerZip": 1,
  "maxItemsPerQuery": 20,
  "maxItems": 20,
  "onSaleOnly": false,
  "includeDetails": false,
  "includeFailures": true,
  "maxConcurrency": 4,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "US"
  }
}
```

# Actor output Schema

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

Dataset with one row per product per store (failure rows are free and have an error field).

## `summary` (type: `string`):

Stores used, products written, failures, stop reason and approximate traffic.

# 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 = {
    "searchTerms": [
        "milk"
    ],
    "zipCodes": [
        "78704"
    ],
    "maxItemsPerQuery": 20,
    "maxItems": 20,
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ],
        "apifyProxyCountry": "US"
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("zaiq/heb-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 = {
    "searchTerms": ["milk"],
    "zipCodes": ["78704"],
    "maxItemsPerQuery": 20,
    "maxItems": 20,
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
        "apifyProxyCountry": "US",
    },
}

# Run the Actor and wait for it to finish
run = client.actor("zaiq/heb-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 '{
  "searchTerms": [
    "milk"
  ],
  "zipCodes": [
    "78704"
  ],
  "maxItemsPerQuery": 20,
  "maxItems": 20,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "US"
  }
}' |
apify call zaiq/heb-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,zaiq/heb-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/CIFh6Q1e148rFGaw6/builds/aoc7WtbwFrJBYVbgQ/openapi.json
