# Kroger Scraper: Weekly Ad Deals & Card Prices by ZIP (`vant47/kroger-scraper`) Actor

Monitor Kroger, Ralphs, Fred Meyer, King Soopers, Harris Teeter and other banners' weekly-ad deals by ZIP: advertised and card prices, conditions, original prices, images and dates for daily or weekly tracking. About $0.0035 per ad observation. No login.

- **URL**: https://apify.com/vant47/kroger-scraper.md
- **Developed by:** [fortbrand](https://apify.com/vant47) (community)
- **Categories:** E-commerce, Automation
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.80 / 1,000 deals

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

## Kroger Scraper: Weekly Ad Deals & Card Prices by ZIP

For retail analysts, brands and comparison services monitoring Kroger, Ralphs, Fred Meyer, King Soopers, Harris Teeter and the other Kroger-family banners. Collect weekly-ad deals by ZIP with advertised and card prices, purchase conditions, original prices, descriptions, images and offer dates. Use daily or weekly snapshots to track promotions across regions. About **$0.0035 per delivered ad observation**: 20 observations cost about **$0.07**, plus a minimum **$0.00005 start charge**. No retailer login, account cookie or retailer API key is required.

Choose Kroger, Ralphs, Fred Meyer, King Soopers, Harris Teeter, Fry's, Smith's, QFC, Dillons, Mariano's, Pick 'n Save, Food 4 Less, City Market, Baker's or Gerbes. Each run selects one banner and one or more ZIPs. Combine separate banner runs using the common retail field names.

### What the prices mean

`price` is the numeric amount published in the regional ad detail. Read its conditions alongside that amount. An explicit “With Card” offer in structured text fills `memberPrice` and sets `priceRequiresMembership` to true. A missing card phrase does not prove that an offer is available without membership; that flag remains null when the source does not specify it.

For a published multi-buy amount, `price` retains the advertised bundle total and `advertisedQuantity` holds an explicit quantity such as two. `priceBasis` distinguishes a bundle total from another advertised amount. The Actor does not divide a bundle to invent a single-item price. An ad covering several varieties or package sizes can remain a single observation because the source does not identify each qualifying native SKU.

`regularPrice` is supplied only when the ad detail includes an original numeric price. `onSale` compares the two supplied amounts. `promoStart` and `promoEnd` preserve the source timestamps and offsets. Future ads and expired offers are excluded from current output. A weekly-ad panel can remain an advertised offer even when no original price is supplied.

Digital-coupon wording is retained when it appears explicitly. Keep the coupon text, card requirements and purchase quantities beside the advertised amount when comparing offers. Explicit VIC, e-vic and Boost membership wording is preserved in the supplied conditions.

### What you get

Every product observation begins with a readable verdict. The family schema follows, then fields explaining the regional source and price basis.

| Field | Meaning |
| --- | --- |
| `verdict` | Readable title, advertised amount, explicit quantity/card condition and regional scope. |
| `retailer`, `country`, `currency` | Selected banner, US and USD. |
| `storeId`, `storeName` | Null; see Limits for location scope. |
| `location` | Requested five-digit ZIP used to discover regional ads. |
| `productId` | Namespaced ad identifier, such as `flyer:1048657057`. |
| `sku`, `gtin` | Publisher-supplied ad SKU when present; GTIN stays null. |
| `title`, `brand`, `size` | Published ad title and explicit brand; package size remains null. |
| `price`, `regularPrice`, `onSale` | Advertised amount, supplied original price and a comparison when both exist. |
| `promoText`, `promoType` | Published conditions and the regional weekly-ad type. |
| `promoStart`, `promoEnd` | Source offer-validity timestamps, preserving offsets. |
| `memberPrice`, `memberProgram` | Advertised card amount and a source-wording label when card eligibility is explicit. |
| `unitPrice`, `unitOfMeasure` | Amount per a clearly stated weight/volume unit; null when not explicitly supported. |
| `inStock`, `stockLevel`, `rating`, `reviewCount` | Null; an advertisement does not establish catalog stock or product review aggregates. |
| `category`, `url`, `imageUrl`, `scrapedAt` | Supplied ad category, public ad link, image and UTC observation timestamp. |

Additional fields include `banner`, `description`, `flyerId`, `flyerName`, `flyerMerchantId`, `prePriceText`, `postPriceText`, `advertisedQuantity`, `priceBasis`, `priceScope`, `storePriceVerified`, `weeklyAd`, `isDeal`, `offers`, `digitalCouponAvailable`, `digitalCouponText`, `details` and `sourceUrl`. Native `locationId`, `aisle`, `upc`, `fuelPoints` and `snapEligible` remain null.

The overview dataset view uses the same core columns as the retail family: title, price, regular price, promotion, member price, unit price, stock and store. Additional scope and quantity columns make the regional unit clear. The deals view emphasizes dates and conditions. Product observations use `recordType: "PRODUCT"`; free explanatory rows use `recordType: "NOTE"`.

Every run writes a `SUMMARY` key-value record containing delivered observations, deals found, duplicates, source outcomes, notes, free failures and spending-limit status. Its `stores` count is zero, and `resolvedStores` is empty. `regions` counts ZIP regions represented in output. The `DEALS` output contains delivered offers, or links to smaller parts when the export is large.

### Start in three steps

1. Choose one banner and supply one or more ZIP codes.
2. Enter product-name search terms, or a weekly-ad/deal landing URL to select current ads.
3. Set the global observation cap, run, and inspect SUMMARY before exporting.

The prefill uses `*` for current priced ads near ZIP 45202 with a 20-observation cap. On 3 November 2026, a cloud prefill delivered 20 observations with 20 matching charges in 32.9 seconds. The latest regional suite passed 43/43 expected outcomes across fifteen banners and sixteen ZIPs. Two separate runs each delivered 1,050 distinct ad observations across seven regions, with zero source failures. Both real reboot tests recovered exactly matching rows and charges, including the one-observation spending cap.

### Inputs and examples

| Input | Behavior |
| --- | --- |
| `banner` | One of kroger, ralphs, fredmeyer, kingsoopers, harristeeter, frys, smiths, qfc, dillons, marianos, picknsave, food4less, citymarket, bakersplus or gerbes. |
| `searchTerms` | Matches current ad titles, such as cheese, chicken or coffee; `*` selects all priced entries. This searches the ad assortment rather than the retailer catalog. |
| `startUrls` | Weekly-ad or deal landing URLs belonging to the selected banner. |
| `productIds` | Explicit `flyer:<item ID>` values from an earlier output. |
| `locations` | Five-digit ZIP codes selecting regional ads. Supply at least one. |
| `storeIds` | Compatibility input; returns a free note as explained in Limits. |
| `maxItemsPerSearch` | New observations per title term or all-ads source and ZIP; default 20, maximum 1,000. |
| `maxItems` | Global distinct observation cap; default 20, maximum 10,000. |
| `dealsOnly` | All delivered observations come from weekly ads. |
| `includeDetails` | Adds ad description, disclaimer, specifications and features inside details, with no extra event fee. |
| `proxyConfiguration` | Form prefill uses direct HTTP. Omitting this field enables datacenter-proxy and US-residential fallback after refusals; explicit choices are honored. |

```json
{
  "banner": "kroger",
  "searchTerms": ["cheese", "coffee"],
  "locations": ["45202", "30303"],
  "maxItemsPerSearch": 20,
  "maxItems": 80
}
```

To browse all current Ralphs offers, use `banner: "ralphs"`, `locations: ["90012"]` and `startUrls: ["https://www.ralphs.com/weeklyad"]`. To inspect an earlier ad item while it is still current, use `productIds: ["flyer:1048657057"]` with a ZIP where its circular remains available.

The same ad can appear for multiple ZIPs. Within one run it is delivered and charged once, preserving the first matched ZIP. Save the banner, ad ID, description and quantity together when combining feeds.

### Real source example

The following selected values were observed in the public Cincinnati Kroger ad detail on 3 November 2026. The values preserve the advertised amount and card wording:

```json
{
  "productId": "flyer:1048657057",
  "title": "Cheez-It Family Size Crackers",
  "location": "45202",
  "storeId": null,
  "price": 4.49,
  "regularPrice": 6.49,
  "memberPrice": 4.49,
  "postPriceText": "/EA* With Card",
  "promoStart": "2026-10-28T00:00:00-04:00",
  "promoEnd": "2026-11-03T23:59:59-05:00",
  "priceScope": "regional-weekly-ad",
  "storePriceVerified": false,
  "gtin": null,
  "inStock": null
}
```

### Pricing and spending limits

The primary charge is one delivered, distinct priced ad observation. Notes, empty results, failed requests, retries, overlapping inputs and summaries have no observation charge. There is no default dataset-item event and no additional details event.

| Delivered observations | Base | Bronze | Silver | Gold |
| --- | --- | --- | --- | --- |
| 20 | $0.07 | $0.0665 | $0.063 | $0.056 |
| 100 | $0.35 | $0.3325 | $0.315 | $0.28 |
| 1,000 | $3.50 | $3.325 | $3.15 | $2.80 |

Add the minimum $0.00005 start charge. Set Apify's maximum total charge as well as the item cap to bound larger jobs. Capacity is checked before saving another priced observation. A final affordable observation is retained when it fills the remaining capacity; the following observation is not delivered or charged. Check `spendingLimitReached` in SUMMARY.

### Monitor prices every day

Save a task with stable banner, ZIPs and title terms, or the selected banner's weekly-ad URL. Create a schedule in Apify Console, choose the task and timezone, and connect the completed dataset and SUMMARY to your database or workflow. No schedule is created automatically by this Actor.

Store observation timestamps with the source validity dates, conditions and quantities. Use `banner + productId` to identify an ad within a snapshot and keep each run's observation time to build promotion history. Brands can compare advertised promotions across regions; comparison services can publish dated deal feeds; analysts can track card-price and coupon wording over successive circulars. Preserve the first matched ZIP and regional scope when combining feeds.

### API and automation

Run with your Apify token and read the completed dataset:

```python
from apify_client import ApifyClient
client = ApifyClient("YOUR_APIFY_TOKEN")
run = client.actor("vant47/kroger-scraper").call(run_input={
    "banner": "kroger", "locations": ["45202"],
    "searchTerms": ["cheese"], "maxItems": 20
})
rows = list(client.dataset(run["defaultDatasetId"]).iterate_items())
```

```javascript
import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('vant47/kroger-scraper').call({
  banner: 'kroger', locations: ['45202'], searchTerms: ['cheese'], maxItems: 20
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
```

Make, Zapier, n8n, Sheets and completed-run webhooks can consume the same dataset. Filter PRODUCT and NOTE records explicitly. Read SUMMARY before accepting a snapshot and keep null values intact during export.

### Use with AI agents (MCP)

Connect to `https://mcp.apify.com`, identify the Actor and supply the banner, ZIPs, title terms and observation cap. Ask the agent to inspect SUMMARY, retain nulls and preserve card/bundle conditions. For example: collect current Kroger cheese and coffee ads near 45202, including card conditions and dates, up to 20 observations.

### Limits

These are the banner's regional weekly-ad offers for a ZIP, not every product's shelf price at one store. Exact store identity, UPCs, stock and aisle locations are not supplied. `storePriceVerified` is false. Store ID inputs return a free note without regional rows; missing ZIPs also return a free note. Native category/product links and native UPC/BPN lookups are outside coverage. A `flyer:` ID identifies an advertisement rather than a native catalog SKU.

Only structured ad text is extracted. Image-only conditions, personalized eligibility, clipped coupons, checkout totals, taxes and fees are outside coverage. Coupons are not clipped or subtracted from `price`. Ten visual checks matched all advertised amounts; two images contained card wording absent from structured details, leaving those membership fields null.

Coverage varies by ZIP, banner, circular and date. Food 4 Less returned current ads in Los Angeles and Chicago but none in the tested Bakersfield ZIP. Unpriced panels, expired offers, future offers and invalid numeric prices are excluded. Historical backfill is not supported. Ad IDs can change between circulars, and different IDs can describe overlapping varieties without a native SKU match. An advertised offer does not guarantee availability.

Caps above 1,050 have not been volume-tested. Source refusals or disappearing ads can leave incomplete output; inspect free failures in SUMMARY. Requests are serial and paced, with fresh sessions on retries and Retry-After handling. Saved rows and acknowledged charge receipts support restart recovery. Recovery checks authoritative charge counts; ambiguous billing evidence stops further charging.

### FAQ

**Can I monitor several banners?** Run each banner separately and combine their common fields.

**What does a flyer-prefixed ID mean?** It identifies the publisher's ad entry. Save it with the banner and observation time.

**Does includeDetails cost extra?** No. It adds descriptive metadata at the same observation price.

**How do multi-buy prices work?** Read `price`, `advertisedQuantity`, `priceBasis` and conditions together; 2/$5 stays a $5 bundle.

**Will overlapping searches cost twice?** The same ad entry is delivered and charged once per run, even when several inputs find it.

**How can I control recurring costs?** Set both item caps and Apify's maximum total charge, then inspect SUMMARY after each scheduled run.

# Actor input Schema

## `banner` (type: `string`):

One banner per run. This private partial build reads regional weekly ads, not exact-store catalog prices.

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

Match current regional ad titles, for example cheese, chicken or coffee. Use \* for all current priced ad entries. This is a limited ad assortment; native Kroger catalog search is unavailable.

## `startUrls` (type: `array`):

Weekly-ad or deal landing URLs of the selected banner select all current regional ad items. Native product and category URLs are unavailable in this partial build.

## `productIds` (type: `array`):

Only flyer:<item ID> identifiers from a previous output are supported. These identify ad entries, not native Kroger UPCs or catalog SKUs.

## `locations` (type: `array`):

Five-digit US ZIP codes, such as 45202. Selects regional ads. It does not verify prices at an exact store. Empty locations produce a free note.

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

Retained for family input compatibility. Exact-store pricing is unavailable; requesting store IDs returns a free note and no substituted regional prices.

## `maxItemsPerSearch` (type: `integer`):

Limit for each search term or all-ads source at a ZIP. Repeated ad IDs are delivered and charged once per run.

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

Global distinct ad-observation cap. About $0.0035 each; 20 cost about $0.07 plus the small start charge.

## `dealsOnly` (type: `boolean`):

Every supported result is a regional weekly-ad offer. Card and purchase conditions remain separate; no account coupons are clipped.

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

Add supplied ad description, disclaimer, specifications and features in details. Price conditions and dates are always included, with no extra event fee.

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

Default: direct HTTP from the run datacenter. Enable Apify proxy or supply custom proxies if needed. When this field is omitted, retries progress through direct datacenter, datacenter proxy and US residential.

## Actor input object example

```json
{
  "banner": "kroger",
  "searchTerms": [
    "*"
  ],
  "locations": [
    "45202"
  ],
  "maxItemsPerSearch": 20,
  "maxItems": 20,
  "dealsOnly": true,
  "includeDetails": false,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

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

No description

## `dealsView` (type: `string`):

No description

## `dealsOnly` (type: `string`):

No description

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

No description

# 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 = {
    "banner": "kroger",
    "searchTerms": [
        "*"
    ],
    "locations": [
        "45202"
    ],
    "maxItemsPerSearch": 20,
    "maxItems": 20
};

// Run the Actor and wait for it to finish
const run = await client.actor("vant47/kroger-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 = {
    "banner": "kroger",
    "searchTerms": ["*"],
    "locations": ["45202"],
    "maxItemsPerSearch": 20,
    "maxItems": 20,
}

# Run the Actor and wait for it to finish
run = client.actor("vant47/kroger-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 '{
  "banner": "kroger",
  "searchTerms": [
    "*"
  ],
  "locations": [
    "45202"
  ],
  "maxItemsPerSearch": 20,
  "maxItems": 20
}' |
apify call vant47/kroger-scraper --silent --output-dataset

```

## MCP server setup

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