# Grocery Deals & Flyer Scraper for Flipp (US & Canada) (`haketa/flipp-scraper`) Actor

Scrape grocery flyer and online deals from Flipp by search term and location: item name, current & original price, discount, sale story, merchant, validity and image. For price tracking, deal research and comparison. Independent tool, not affiliated with Flipp.

- **URL**: https://apify.com/haketa/flipp-scraper.md
- **Developed by:** [Haketa](https://apify.com/haketa) (community)
- **Categories:** E-commerce, Business
- **Features:** Limited permissions
- **Stats:** 10 total users, 3 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.00 / 1,000 results

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

## Grocery Deals & Flyer Scraper for Flipp — Weekly Ads, Online Deals, Prices & Discounts

[![Apify Actor](https://img.shields.io/badge/Apify-Actor-blue)](https://apify.com/haketa/flipp-scraper)
[![Deals](https://img.shields.io/badge/Coverage-US%20%26%20Canada%20Flyers-e01a2b)]()
[![Price & Discount](https://img.shields.io/badge/Data-Price%20%2B%20Discount%20%2B%20Merchant-2da44e)]()
[![Scale](https://img.shields.io/badge/Pagination-1%2C000%2B%20Deals-purple)]()
[![Export](https://img.shields.io/badge/Export-JSON%20%7C%20CSV%20%7C%20Excel%20%7C%20API-fb8500)]()

> **A fast, no-code grocery deals & weekly flyer scraper for [Flipp](https://flipp.com) that turns any product search into a clean retail pricing dataset.** Extract weekly-flyer circulars and online deals across thousands of US and Canadian supermarkets, pharmacies, and big-box retailers — including item **name, current sale price, original "was" price, computed discount %, sale story promo text, merchant name & ID, validity dates, brand IDs, weight/size, and product images** — localized to any US ZIP code or Canadian postal code. **No login, no coding, and no browser overhead.**

Export every deal to **JSON, CSV, Excel, or API** in seconds.

> Built for retail and CPG competitive-intelligence teams, grocery price-tracking apps, coupon and deal-aggregation websites, inflation researchers, and smart-cart tools that need structured **Flipp data** on demand.

> ℹ️ **Disclaimer:** This Actor is an independent tool and is **not affiliated with, endorsed by, or sponsored by Flipp Operations Inc.** or any retailer featured in weekly circulars. "Flipp" and all related brand names and logos are trademarks of their respective owners and are used here strictly to describe the publicly available data source. Please use this Actor in compliance with Flipp's Terms of Service and applicable laws.

***

### ⚡ At a glance

| Feature | Details |
|---|---|
| **Data source** | Public weekly-flyer & online deal listings on [Flipp](https://flipp.com) (`en-us` United States & `en-ca` Canada) |
| **Deal types extracted** | Printed weekly-ad flyer deals (`type: "flyer"`) and e-commerce offers (`type: "online"`), interleaved for balanced sampling |
| **Core fields** | `name`, `currentPrice`, `originalPrice`, `discountPercent`, `saleStory`, `merchant`, `merchantId`, `validFrom`, `validTo`, `itemWeight`, `imageUrl` |
| **Online-only fields** | `description`, `sku`, `averageRating`, `totalReviews`, `shippingInfo` |
| **1,000+ results scale** | Automatic grocery staple & category expansion when `maxItems > 150` — delivers **1,000+ unique deals** with 0 duplicates |
| **Authentication** | None required — no account, login, or API key needed |
| **Proxy requirement** | Standard Apify Proxy (Datacenter enabled by default — fast and low-cost) |
| **Export formats** | JSON, CSV, Excel (XLSX), HTML, XML, RSS, Key-Value Store `OUTPUT`, and REST API |

***

### 🔎 Why scrape Flipp grocery & flyer deals?

[**Flipp**](https://flipp.com) is North America's largest digital weekly-flyer and circular platform, aggregating weekly promotions and online deals from **thousands of grocery chains, pharmacies, hardware stores, and big-box retailers** across every US ZIP code and Canadian postal code. That makes it one of the richest public sources of localized retail pricing intelligence — showing current promotional prices, pre-sale "was" prices, loyalty-card requirements, multi-buy offers, and exact validity dates by store.

However, the web interface is designed for browsing one circular or one item at a time. There is no bulk CSV export, no way to compare the price of **milk, eggs, coffee, chicken, and detergent** across 40 local retailers simultaneously, and no historical archive once a weekly flyer expires.

This **Flipp scraper** automates the entire extraction pipeline. Supply your **search terms** and a **postal/ZIP code**, and the actor returns every matching named flyer item and online deal as a normalized, de-duplicated dataset ready for Excel, SQL, Power BI, or your application backend. Request `maxItems: 1000`+ and the scraper automatically expands across 40+ high-volume grocery and household staples to deliver **1,000+ unique deals** in under a minute.

**Common reasons teams use this Flipp data extractor:**

- **Retail & CPG competitive price monitoring** — track weekly promotional pricing, discount depth, and feature frequency across competing supermarket chains by ZIP code.
- **Consumer grocery price-comparison apps** — power mobile or web apps that show shoppers the lowest local price for their weekly shopping list.
- **Deal-aggregation, coupon & savings portals** — populate localized deal feeds and email digests with verified weekly circular promotions and validity windows.
- **Promotional & trade-spend intelligence** — analyze `saleStory`, `prePriceText`, and `postPriceText` to measure loyalty-club discounts, BOGO offers, and digital coupons by brand (`brandIds`).
- **Macroeconomic & food-inflation tracking** — schedule weekly runs across representative US and Canadian postal codes to build longitudinal CPI and staple food price indices.

***

### ✨ What this Flipp scraper does

- ✅ **Search by product, brand, or category** — pass any list of `searchTerms` (`milk`, `eggs`, `coffee`, `chicken breast`, `diapers`, `laundry detergent`, `laptop`, etc.). Leave `searchTerms` empty and the actor automatically runs a curated grocery staples sample so empty runs always succeed.
- ✅ **Unlocked 1,000+ deals automatic expansion** — because a single search term returns roughly 50–180 local deals, setting `maxItems` above `150` (e.g. `500` or `1,000+`) automatically expands your query list across 40+ core grocery, produce, meat, dairy, beverage, and household categories until your target count is reached.
- ✅ **Weekly flyer + online e-commerce deals** — extracts both printed circular promotions (`type: "flyer"`) and online retailer deals (`type: "online"`). Both streams are **interleaved** per search term so capped runs always include a balanced mix of local flyers and online offers.
- ✅ **Image-only clipping filter** — raw weekly circulars often contain unnamed visual clippings; the actor automatically filters out unnamed graphic slices so **100% of returned records have a clean product `name`**.
- ✅ **Computed discount percentages & sale stories** — automatically calculates `discountPercent` whenever both `currentPrice` and `originalPrice` are available, while preserving promotional copy in `saleStory` (e.g. `"SAVE 46%"`, `"- $1.00 Digital Savings"`), `prePriceText`, and `postPriceText`.
- ✅ **Full merchant & circular provenance** — includes `merchant`, `merchantId`, `merchantLogo`, `flyerId`, `validFrom`, and `validTo` ISO timestamps on every flyer deal.
- ✅ **Zero duplicates** — every deal is de-duplicated across search terms using a composite `type:itemId` key (resolving `item_id`, `global_id`, and `sku` for online listings).
- ✅ **Bulk export JSON, CSV, Excel & sync API** — writes records to the default Apify Dataset and mirrors `{ count, deals }` to the Key-Value Store `OUTPUT` key for instant `run-sync` API consumers.

***

### 🎯 Use cases

| Industry / Team | How they leverage Flipp deal data |
|---|---|
| **CPG Brand & Revenue Management** | Monitor how regional grocers promote your SKUs (`brandIds`) versus rival brands across US & Canadian metro areas every week. |
| **Supermarket & Retail Pricing Teams** | Benchmark weekly circular loss-leaders (milk, eggs, meat, coffee, produce) against local competitors in specific ZIP codes. |
| **Savings Apps & FinTech** | Build automated "cheapest basket near you" calculators by matching user grocery lists against live `currentPrice` and `merchant` records. |
| **Affiliate & Deal Publishers** | Filter deals with `discountPercent >= 30` and valid `validTo` dates to publish daily localized deal roundups. |
| **Economic & Academic Researchers** | Schedule weekly Monday runs across 50 US ZIP codes and Canadian forward sortation areas (FSAs) to track regional food price dispersion. |

***

### 📥 Input

All parameters are optional and prefilled with sensible defaults (`milk`, `eggs`, `coffee` in New York `10001`).

| Field | Type | Default / Prefill | Description |
|---|---|---|---|
| `searchTerms` | array\<string> | Prefill: `["milk", "eggs", "coffee"]` | Products, brands, or categories to search. Leave empty for a built-in grocery sample, or set `maxItems: 1000`+ to auto-expand across 40+ grocery staples. |
| `postalCode` | string | `"10001"` | 5-digit US ZIP code (e.g. `10001`, `90210`, `60601`) or 6-character Canadian postal code (e.g. `M5V2T6`, `H2X1Y4`). |
| `locale` | string (select) | `"en-us"` | `en-us` (United States) or `en-ca` (Canada). Match this to your `postalCode` country. |
| `includeEcom` | boolean | `true` | Include online/e-commerce deals (`type: "online"` with SKU, ratings, reviews, and shipping) alongside weekly flyer deals. |
| `maxItems` | integer | Default: `0` (Prefill: `100`) | Maximum total deals to collect across all search terms (`0` = unlimited). Setting `> 150` enables automatic grocery category expansion. |
| `proxyConfiguration` | object | `{ "useApifyProxy": true }` | Apify Proxy configuration. Standard Datacenter proxy is enabled by default and works at full speed. |

#### Example input — local US grocery price check

```json
{
  "searchTerms": ["milk", "eggs", "coffee", "chicken", "cheese"],
  "postalCode": "10001",
  "locale": "en-us",
  "includeEcom": true,
  "maxItems": 250,
  "proxyConfiguration": { "useApifyProxy": true }
}
```

#### Example input — Canadian flyer sweep (1,000+ deals)

```json
{
  "searchTerms": ["milk", "bread", "butter", "salmon", "apples"],
  "postalCode": "M5V2T6",
  "locale": "en-ca",
  "includeEcom": true,
  "maxItems": 1000,
  "proxyConfiguration": { "useApifyProxy": true }
}
```

***

### 📤 Output

Each deal is saved as one structured JSON object in the dataset. Below are two real records from a verified run — one printed weekly **flyer** deal and one **online** e-commerce deal:

#### Sample `flyer` deal record

```json
{
  "type": "flyer",
  "itemId": "1050023770",
  "name": "Horizon Organic Milk",
  "currentPrice": 4.49,
  "originalPrice": 5.49,
  "prePriceText": "",
  "postPriceText": "with weis preferred SHOPPERS CLUB",
  "saleStory": "- $1.00 Digital Savings",
  "discountPercent": 18,
  "brandIds": ["3645"],
  "itemWeight": "0.729",
  "merchant": "Weis Markets",
  "merchantId": "2455",
  "merchantLogo": "http://images.wishabi.net/merchants/2455/1528840420/storefront_logo",
  "flyerId": "8195063",
  "validFrom": "2026-10-29T05:00:00+00:00",
  "validTo": "2026-11-27T04:59:59+00:00",
  "imageUrl": "https://f.wishabi.net/page_items/438671201/1792748190/extra_large.jpg",
  "searchTerm": "milk",
  "postalCode": "10001",
  "scrapedAt": "2026-11-01T23:47:21.385Z"
}
```

#### Sample `online` deal record

```json
{
  "type": "online",
  "itemId": "712127",
  "name": "Well Market Milk Choc Waffle Cones",
  "currentPrice": 3.99,
  "originalPrice": 5.99,
  "discountPercent": 33,
  "description": "Well Market Milk Choc Waffle Cones",
  "merchant": "CVS Pharmacy",
  "merchantId": "2264",
  "merchantLogo": "https://images.wishabi.net/merchants/2264/1507308958/2264.jpg",
  "sku": "712127",
  "averageRating": 4.61,
  "totalReviews": 128,
  "shippingInfo": "Free shipping",
  "imageUrl": "https://flipp-image-retrieval.flipp.com/api/...",
  "searchTerm": "milk",
  "postalCode": "10001",
  "scrapedAt": "2026-11-01T23:47:22.779Z"
}
```

***

### 📋 Output fields & coverage reference

#### 🏷️ Deal Identity & Pricing

| Field | Type | Coverage | Description |
|---|---|---|---|
| `type` | string | 🟢 High (100%) | Deal channel: `"flyer"` (weekly store circular) or `"online"` (e-commerce listing). |
| `itemId` | string | 🟢 High (100%) | Unique deal or item identifier (used with `type` for strict de-duplication). |
| `name` | string | 🟢 High (100%) | Clean product or deal headline (unnamed flyer image clippings are automatically filtered out). |
| `currentPrice` | number / null | 🟢 High (~92%) | Active promotional or sale price in local currency (USD for `en-us`, CAD for `en-ca`). |
| `originalPrice` | number / null | 🟡 Conditional (~25%) | Pre-sale "was" price when advertised by the merchant. |
| `discountPercent` | integer / null | 🟡 Conditional (~25%) | Computed percentage off (`Math.round((1 - currentPrice / originalPrice) * 100)`) when both prices exist. |
| `saleStory` | string | 🟡 Conditional (~35%) | Promotional callout on flyer items (e.g. `"SAVE 46%"`, `"Digital Coupon"`, `"Buy 1 Get 1 Free"`). |
| `prePriceText` | string | 🟡 Conditional (~20%) | Qualifier printed before the price on the flyer. |
| `postPriceText` | string | 🟡 Conditional (~42%) | Unit, limit, or loyalty-card requirement printed after the price (e.g. `"lb. Limit 2"`, `"with Club Card"`). |
| `itemWeight` | string | 🟢 High (~99% flyer) | Package weight, volume, or unit size reported on flyer deals. |
| `brandIds` | array\<string> | 🟡 Conditional (~60% flyer) | Brand identifier codes associated with the flyer item. |

#### 🏪 Merchant, Validity & Provenance

| Field | Type | Coverage | Description |
|---|---|---|---|
| `merchant` | string | 🟢 High (100%) | Store or retailer name (e.g. `Walmart`, `Kroger`, `Target`, `Shoppers Drug Mart`, `Loblaws`). |
| `merchantId` | string | 🟢 High (100%) | Unique merchant identifier. |
| `merchantLogo` | string | 🟢 High (100%) | URL to the retailer's storefront logo image. |
| `flyerId` | string | 🟢 High (100% flyer) | Circular / flyer identifier (`""` on online-only deals). |
| `validFrom` | string | 🟢 High (~99% flyer) | ISO 8601 start timestamp of the flyer promotion window. |
| `validTo` | string | 🟢 High (~99% flyer) | ISO 8601 expiration timestamp of the flyer promotion window. |
| `imageUrl` | string | 🟢 High (100%) | Direct URL to the product or flyer clipping image. |
| `searchTerm` | string | 🟢 High (100%) | The search query that matched this deal. |
| `postalCode` | string | 🟢 High (100%) | The US ZIP or Canadian postal code queried. |
| `scrapedAt` | string | 🟢 High (100%) | ISO 8601 timestamp when the record was collected. |

#### 🛒 Online / E-Commerce Enrichment (`type: "online"`)

| Field | Type | Coverage | Description |
|---|---|---|---|
| `description` | string | 🟢 High (99% online) | Product description snippet (up to 300 chars) on online deals. |
| `sku` | string | 🟢 High (99% online) | Retailer SKU identifier on online deals. |
| `averageRating` | number / null | 🟡 Conditional (~85% online) | Average customer star rating (1–5) on online deals. |
| `totalReviews` | integer / null | 🟡 Conditional (~85% online) | Total customer review count on online deals. |
| `shippingInfo` | string | 🟡 Conditional (~50% online) | Shipping badge text (e.g. `"Free shipping"`) when provided by the retailer. |

***

### 🔁 Pagination & 1,000+ deals scale

Unlike traditional paginated web catalogs, Flipp returns the **entire localized result set for a search term in a single response** (typically 40–100+ named flyer deals plus up to ~85 online deals per term). To make scaling effortless:

1. **Multi-term iteration & interleaving:** The scraper iterates through every query in `searchTerms`, interleaves `flyer` and `online` deals 1-for-1 so neither type starves under a cap, and de-duplicates across all terms using `type:itemId`.
2. **Automatic 1,000+ grocery category expansion:** When you set `maxItems > 150` (for example `maxItems: 1000`), you do not have to manually type 25 search terms. After processing your custom `searchTerms`, the actor automatically appends up to 40 high-volume grocery and household staples (`milk`, `eggs`, `coffee`, `chicken`, `beef`, `salmon`, `bread`, `butter`, `cheese`, `yogurt`, `cereal`, `rice`, `pasta`, `apple`, `banana`, `orange`, `potato`, `tomato`, `juice`, `soda`, `water`, `chips`, `pizza`, `olive oil`, `laundry detergent`, `paper towels`, etc.) until `maxItems` unique deals have been saved.
3. **Sub-minute execution:** Because each term requires only one lightweight HTTP request over Datacenter proxy, collecting 500–1,000+ de-duplicated deals typically finishes in **15–45 seconds** at a fraction of a cent in platform usage.

***

### ⚙️ How to use

1. **Open the actor** in Apify Console and enter your **Search terms** (or leave the defaults).
2. **Set your location:** Enter a US **Postal / ZIP code** (e.g. `10001`) with `locale: "en-us"`, or a Canadian postal code (e.g. `M5V2T6`) with `locale: "en-ca"`.
3. **Set your target volume:** Use `maxItems: 100` for a quick test, `maxItems: 1000` for a broad supermarket sweep, or `0` for all deals matching your terms.
4. **Click Start** and watch flyer and online deals stream into the dataset.
5. **Export or automate:** Download **JSON, CSV, Excel, or HTML**, or schedule weekly runs and connect to **Google Sheets, Make, Zapier, n8n, Snowflake, BigQuery, or webhooks**.

#### Calling via Python SDK

```python
from apify_client import ApifyClient

client = ApifyClient("YOUR_APIFY_TOKEN")

run_input = {
    "searchTerms": ["milk", "eggs", "coffee", "chicken", "butter"],
    "postalCode": "60601",
    "locale": "en-us",
    "includeEcom": True,
    "maxItems": 500,
    "proxyConfiguration": {"useApifyProxy": True},
}

run = client.actor("haketa/flipp-scraper").call(run_input=run_input)

for deal in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(f"[{deal['type']}] {deal['name']} — ${deal['currentPrice']} at {deal['merchant']} ({deal.get('saleStory', '')})")
```

#### Finding the lowest local price per item (Python)

```python
run = client.actor("haketa/flipp-scraper").call(run_input={
    "searchTerms": ["milk", "eggs", "ground beef"],
    "postalCode": "10001",
    "locale": "en-us",
    "maxItems": 300,
})

cheapest = {}
for d in client.dataset(run["defaultDatasetId"]).iterate_items():
    price = d.get("currentPrice")
    term = d.get("searchTerm")
    if price is not None and term:
        if term not in cheapest or price < cheapest[term]["currentPrice"]:
            cheapest[term] = d

for term, d in cheapest.items():
    print(f"Lowest '{term}': ${d['currentPrice']} at {d['merchant']} — {d['name']}")
```

#### Calling via JavaScript / Node.js SDK

```javascript
import { ApifyClient } from 'apify-client';

const client = new ApifyClient({ token: 'YOUR_APIFY_TOKEN' });

const run = await client.actor('haketa/flipp-scraper').call({
    searchTerms: ['milk', 'eggs', 'coffee', 'chicken', 'bread'],
    postalCode: '10001',
    locale: 'en-us',
    includeEcom: true,
    maxItems: 400,
});

const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(`Collected ${items.length} localized Flipp deals.`);
```

#### Calling via cURL (REST API)

```bash
curl -X POST "https://api.apify.com/v2/acts/haketa~flipp-scraper/runs?token=YOUR_APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "searchTerms": ["milk", "eggs", "coffee"],
    "postalCode": "M5V2T6",
    "locale": "en-ca",
    "includeEcom": true,
    "maxItems": 200
  }'
```

***

### 🗺️ Supported regions & sample postal codes

| Country | `locale` setting | Sample `postalCode` | Metro Area | Currency |
|---|---|---|---|---|
| **United States** | `"en-us"` | `10001` | New York, NY | USD (`$`) |
| **United States** | `"en-us"` | `90001` | Los Angeles, CA | USD (`$`) |
| **United States** | `"en-us"` | `60601` | Chicago, IL | USD (`$`) |
| **United States** | `"en-us"` | `77001` | Houston, TX | USD (`$`) |
| **United States** | `"en-us"` | `33101` | Miami, FL | USD (`$`) |
| **Canada** | `"en-ca"` | `M5V2T6` | Toronto, ON | CAD (`$`) |
| **Canada** | `"en-ca"` | `H2X1Y4` | Montreal, QC | CAD (`$`) |
| **Canada** | `"en-ca"` | `V6B1A1` | Vancouver, BC | CAD (`$`) |
| **Canada** | `"en-ca"` | `T2P1J9` | Calgary, AB | CAD (`$`) |

***

### 💡 Pro tips for best results

- **Always pair `postalCode` and `locale`:** Use `en-us` with 5-digit US ZIP codes (`10001`, `90001`, `77001`) and `en-ca` with 6-character Canadian postal codes (`M5V2T6`, `V6B1A1`, `T2P1J9`).
- **Flyer-only competitive intelligence:** Set `includeEcom: false` when you only want printed weekly store circulars (`type: "flyer"`) with `flyerId`, `validFrom`, and `validTo` windows.
- **Schedule weekly snapshots:** Most North American grocers publish new weekly flyers between Wednesday and Friday; schedule a weekly run to build a time-series database of promotional pricing.
- **Keep Datacenter proxy enabled:** Flipp works smoothly with standard Apify Datacenter proxies (`useApifyProxy: true`), keeping run costs ultra-low (~$0.01–$0.02 per 1,000 deals).

***

### ⚠️ Honest limitations

- **Printed flyers often omit "was" prices:** Roughly 75–90% of weekly grocery circular items advertise a promotional `currentPrice` or multi-buy `saleStory` without stating a pre-sale `originalPrice`; for those items, `originalPrice` and `discountPercent` are `null`.
- **Percentage-off / BOGO callouts:** A small fraction (~5–10%) of flyer items advertise `"Buy 1 Get 1 Free"` or `"25% Off Entire Line"` in `saleStory` without a single numeric `currentPrice`.
- **Single-location per run:** Each run queries one `postalCode`. To compare 10 different cities or ZIP codes, trigger parallel runs via the API or an Apify task schedule.

***

### ❓ FAQ

**Do I need a Flipp account or API key?**
No. The actor requires no login, no cookies, and no API key.

**How do I collect 1,000+ deals if one search term only returns ~150 items?**
Simply set `maxItems: 1000` (or higher). Whenever `maxItems > 150`, the actor automatically expands your search list across 40+ staple grocery and household terms, de-duplicating every item so you receive 1,000+ unique deals in a single run.

**What happens if I run the actor with empty `searchTerms`?**
It automatically falls back to a curated list of popular grocery staples (`milk`, `eggs`, `coffee`, `chicken`, `beef`, `pork`) and returns a 100-deal sample so empty runs never fail.

**Does this support Canadian grocery stores like Loblaws, No Frills, Metro, and Sobeys?**
Yes. Set `locale: "en-ca"` and provide a Canadian postal code (e.g. `"M5V2T6"` for Toronto or `"V6B1A1"` for Vancouver) to pull Canadian weekly flyers in CAD.

**Can I fetch the output synchronously via a single HTTP call?**
Yes. In addition to pushing every item to the default Dataset, the actor writes `{ count, deals }` to the `OUTPUT` record in the default Key-Value Store so `run-sync` API calls receive the full payload immediately.

***

### 🔗 Related e-commerce & retail pricing scrapers

Explore our other marketplace and retail intelligence actors:

- [Shopify Store Scraper — Products, Variants & Prices](https://apify.com/haketa/shopify-store-scraper)
- [Tokopedia Scraper — Product Search, Prices & Sold Counts](https://apify.com/haketa/tokopedia-scraper)
- [Rakuten Ichiba Scraper — Japan #1 Marketplace Prices & Reviews](https://apify.com/haketa/rakuten-scraper)
- [Tiki.vn Scraper — Vietnam Marketplace Products & Sales Volume](https://apify.com/haketa/tiki-scraper)
- [Mercari Japan Scraper — Resale Listings & Sold Comps](https://apify.com/haketa/mercari-scraper)
- [Reverb Scraper — Musical Gear Listings & Price Guide](https://apify.com/haketa/reverb-scraper)

***

### 📋 Changelog

- **v1.2 (2026-11)** — Added **automatic 40-term grocery category expansion** when `maxItems > 150` so users requesting **1,000+ deals** receive 1,000+ unique, de-duplicated records in a single run; added empty-run default grocery sample fallback; expanded README with coverage tables and SDK recipes.
- **v1.1 (2026-11)** — Fixed online deal ID resolution (`item_id` / `global_id` / `sku`) for 100% accurate online de-duplication; added 1-for-1 flyer/online interleaving and `brandIds` extraction.
- **v1.0 (2026-09)** — Initial release with US (`en-us`) and Canada (`en-ca`) weekly flyer + e-commerce deal extraction and Key-Value Store `OUTPUT` mirroring.

***

<p align="center"><i>This Actor is an independent tool and is not affiliated with, endorsed by, or sponsored by Flipp Operations Inc. or any retailer. All trademarks belong to their respective owners and are used only to describe the publicly available data source.</i></p>

# Changelog

This Actor's version history is a separate document: https://apify.com/haketa/flipp-scraper/changelog.md

# Actor input Schema

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

Products or categories to search (e.g. milk, eggs, coffee, chicken, cereal). Leave empty for a popular grocery staple sample, or request 1,000+ maxItems to automatically expand across grocery categories.

## `postalCode` (type: `string`):

US ZIP (e.g. 10001) or Canadian postal code (e.g. M5V2T6) for local flyers.

## `locale` (type: `string`):

en-us (United States) or en-ca (Canada).

## `includeEcom` (type: `boolean`):

Also include online/e-commerce deals (with rating, SKU, shipping) alongside printed flyer deals.

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

Maximum deals across all search terms. 0 = no limit.

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

Apify Proxy. Datacenter is enough for Flipp and is enabled by default.

## Actor input object example

```json
{
  "searchTerms": [
    "milk",
    "eggs",
    "coffee"
  ],
  "postalCode": "10001",
  "locale": "en-us",
  "includeEcom": true,
  "maxItems": 100,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

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

flyer | online

## `itemId` (type: `string`):

Deal item ID

## `name` (type: `string`):

Item name

## `currentPrice` (type: `string`):

Sale/current price

## `originalPrice` (type: `string`):

Original price

## `discountPercent` (type: `string`):

Discount percent

## `saleStory` (type: `string`):

Deal text (e.g. SAVE 46%)

## `brandIds` (type: `string`):

Flipp brand IDs for the item (flyer deals)

## `prePriceText` (type: `string`):

Text before price

## `postPriceText` (type: `string`):

Text after price

## `itemWeight` (type: `string`):

Item weight/size

## `merchant` (type: `string`):

Store/merchant

## `merchantLogo` (type: `string`):

Merchant logo URL

## `flyerId` (type: `string`):

Flyer ID

## `validFrom` (type: `string`):

Deal start date

## `validTo` (type: `string`):

Deal end date

## `description` (type: `string`):

Item description (online)

## `sku` (type: `string`):

SKU (online)

## `averageRating` (type: `string`):

Average rating (online)

## `totalReviews` (type: `string`):

Review count (online)

## `shippingInfo` (type: `string`):

Shipping info (online)

## `imageUrl` (type: `string`):

Item image URL

## `searchTerm` (type: `string`):

Search term

## `postalCode` (type: `string`):

Postal/ZIP searched

## `scrapedAt` (type: `string`):

ISO timestamp

# 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",
        "eggs",
        "coffee"
    ],
    "postalCode": "10001",
    "locale": "en-us",
    "includeEcom": true,
    "maxItems": 100,
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("haketa/flipp-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",
        "eggs",
        "coffee",
    ],
    "postalCode": "10001",
    "locale": "en-us",
    "includeEcom": True,
    "maxItems": 100,
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("haketa/flipp-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",
    "eggs",
    "coffee"
  ],
  "postalCode": "10001",
  "locale": "en-us",
  "includeEcom": true,
  "maxItems": 100,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call haketa/flipp-scraper --silent --output-dataset

```

## MCP server setup

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