Flashfood Scraper - Discounted Groceries, Prices & Availability avatar

Flashfood Scraper - Discounted Groceries, Prices & Availability

Pricing

from $1.80 / 1,000 deal or store records

Go to Apify Store
Flashfood Scraper - Discounted Groceries, Prices & Availability

Flashfood Scraper - Discounted Groceries, Prices & Availability

Scrape Flashfood discounted groceries and stores by location or store. Extract current and original prices, savings, quantity, best-before date, department, and store details. Track NEW, UPDATED, REAPPEARED, and EXPIRED items with incremental runs, resume, and MCP export.

Pricing

from $1.80 / 1,000 deal or store records

Rating

0.0

(0)

Developer

Abot API

Abot API

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

0

Monthly active users

2 days ago

Last modified

Categories

Share

Flashfood Scraper: Grocery Deals, Prices & Store Info

Flashfood Scraper reads the discounted grocery items and the stores behind them, directly from the same service the official Flashfood app uses, for any location in the US or Canada. Search around one or more points and get every store in range plus its surplus deals (price, original price, discount percent, quantity available, best-before date), or paste store links or ids for a direct per-store read. It also tracks availability across runs (NEW, UPDATED, REAPPEARED, EXPIRED), can resume an interrupted pull, and can pipe results into your apps through MCP connectors.

Why This Scraper?

  • Two ways to find deals. Search by location (city, postal code, or exact coordinates) or paste store links or ids directly. No need to guess store urls.
  • Full deal detail per item. Price, original price, discount percent, quantity available, best-before date and department in one record, with the parent store flattened in for convenience.
  • Multi-location coverage. Give several locations in one run and each gets a fair share of the record budget, so a wide area does not starve any single city.
  • Store records on demand. Turn on store output to also get name, banner, address, hours and pickup instructions for every store you touch.
  • Availability monitoring. Recurring runs classify every record as NEW, UPDATED, UNCHANGED, REAPPEARED or EXPIRED, with state you can name or share across campaigns.
  • MCP connector export. Send results into Notion or other connectors as an extra delivery step, without changing the dataset.
  • Structured failures. A blocked or broken run fails loudly with a clear message instead of quietly returning an empty dataset.

Use Cases

  • Deal-alert apps and bots: monitor one or more cities on a schedule and notify users only about NEW and UPDATED discounted items.
  • Budget grocery shopping and meal planning: pull current deals near you to plan a shop around the biggest discounts and soonest best-before dates.
  • Food-waste and sustainability research: track how much surplus food is listed, at what discount, and how quickly it disappears (EXPIRED) across regions.
  • Grocery banner and pricing intelligence: compare which store banners list the most deals, at what markdown, in a given metro area.
  • Community and food-assistance programs: find EBT-eligible discounted items near a neighborhood to route people to available low-cost food.

Data You Get

Sample shape: values are illustrative placeholders, not from a live listing.

FieldExample
kind"item" (also "store" when store output is on)
recordId / itemId"6198765432abcdef0fedcba9"
urlFlashfood link to the store the deal belongs to
title"Sample Brand Multigrain Bread"
price2.49
originalPrice4.99
discountPercent50.1
currency"USD" (also "CAD")
quantityAvailable5
bestBefore"2026-11-05T00:00:00+00:00"
department"Bakery"
legacyDepartment"Bakery"
imageUrlproduct photo link
listedAt"2026-10-30T09:15:00.000Z"
isSnapEligiblefalse
storageTreatment"NONE"
storeId / storeName"6123456789abcdef01234567" / "Sample Grocery Market"
banner"Sample Banner Co."
street / city"100 Example Ave" / "Sample City"
stateCode / countryCode"MI" / "US"
latitude / longitude42.33 / -83.05
imageGallerylist of extra product photo links (may be empty)
changeType / changedFields"NEW" / [] (incremental mode only)
firstSeenAt / lastSeenAt"2026-01-01T00:00:00+00:00" (incremental mode only)
rawthe complete source object

Store records (kind=store, when store output is turned on) carry the store's own name, banner, address, coordinates, hours, EBT support, and localized pickup and checkout instructions, plus their own raw source object.

How to Use

  1. Pick a mode: search (locations) or url (store links or ids).
  2. In search mode, list one or more locations (a city, postal code, or lat,lng) and a radius; in url mode, list store links or ids.
  3. Turn on store output if you also want one record per store, and set Max items to control run size and cost.
  4. Click Start, then download the dataset as JSON, CSV or Excel, or read it through the API.

Search one city (defaults):

{
"mode": "search",
"locations": ["Detroit, Michigan"],
"maxItems": 20
}

Several locations, wider net:

{
"mode": "search",
"locations": ["Toronto, Ontario", "42.33,-83.05"],
"radiusKm": 25,
"maxItems": 100
}

A specific store by id or link:

{
"mode": "url",
"storeInputs": ["0123456789abcdef01234567"]
}

Recurring deal monitoring:

{
"mode": "search",
"locations": ["Detroit, Michigan"],
"incrementalMode": true,
"stateKey": "detroit-daily",
"emitExpired": true,
"maxItems": 200
}

Run it from your code

Python:

from apify_client import ApifyClient
client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("abotapi/flashfood-grocery-deals-scraper").call(run_input={"mode": "search", "locations": ["Detroit, Michigan"]})
for deal in client.dataset(run["defaultDatasetId"]).iterate_items():
print(deal["title"], deal["price"], deal["originalPrice"])

JavaScript:

import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: '<YOUR_APIFY_TOKEN>' });
const run = await client.actor('abotapi/flashfood-grocery-deals-scraper').call({ mode: 'search', locations: ['Detroit, Michigan'] });
const { items } = await client.dataset(run.defaultDatasetId).listItems();

Or connect it to Make, Zapier, n8n, Google Sheets or webhooks from the Integrations tab.

Locations, radius and the 100-store cap

A single search query returns at most 100 stores around a point, nearest first, and the source ignores paging. For a small town this is normally everything nearby; for a dense metro area, cover it with several nearby locations (or a smaller radius) rather than one huge radius. Place names are resolved to coordinates automatically; lat,lng pairs skip that step.

Tip: with store output on, each location emits its store records first and they count toward that location's share of Max items. In a busy area the store records alone can use up the whole budget before any deal is returned (for example, 30 stores in range with Max items 20 returns 20 store records and no deals). Raise Max items, or leave store output off when you only want deals. Store records are also not de-duplicated across locations, so two overlapping locations return the same store twice.

Tip: if a place name cannot be resolved to coordinates (a typo, or the geocoding provider is briefly unreachable), that location is skipped for the run and a warning is logged, but the run still continues and succeeds with the locations that did resolve. This means a run can look like a complete, healthy scan (no failure, no empty dataset) even though one location's stores were never read at all. On a monitoring run with Emit expired records turned on, when at least one other location did resolve, the skipped location's previously-tracked deals are returned (and billed) as EXPIRED, because the skip is not counted as an unfinished location and the run is treated as a complete scan. If you rely on EXPIRED for billing or inventory decisions, check the run log for "could not be resolved to coordinates" warnings before trusting an EXPIRED result, and prefer lat,lng coordinates for locations that must always be scanned.

Resume and recurring updates

  • Resume (resumeFromRunId) continues one interrupted run: paste its run or dataset ID and the actor skips every deal already collected there, so you don't pay twice for the same deals. Store records (store output on) are the exception: they are returned again on the resumed run. If the previous run or dataset cannot be read, a warning is logged and the run starts from scratch.
  • Incremental mode (incrementalMode) is for running this same search again and again (for example daily) and getting only what changed. Each record is classified NEW, UPDATED (with changedFields), UNCHANGED (suppressed and not billed unless emitUnchanged is on), REAPPEARED or EXPIRED (only after a run that scanned the whole tracked scope, and only with emitExpired). stateKey names or shares the stored state. With incremental mode off, output is exactly as before.

Tip: resumeFromRunId and incrementalMode can be combined, but a record that is skipped because resume already has it is not re-checked against the live source that run: its stored fingerprint and last-seen time stay exactly as they were when it was last actually scraped, even if its price or quantity has since changed. That real change only surfaces on a later run of the same monitoring campaign that does not use resumeFromRunId. Reserve resumeFromRunId for finishing one interrupted pull, and let the next plain scheduled run refresh the campaign's state.

Tip: Emit expired records pushes every record the current run determines is gone from a fully-scanned scope, and that batch is not capped by Max items; Max items governs how many NEW/UPDATED/UNCHANGED/REAPPEARED records the scan itself collects. If a monitoring campaign accumulates a large tracked baseline (many stores, many deals, over weeks), a run where most of that baseline has genuinely disappeared can push far more EXPIRED rows than Max items in one go. Budget for that when sizing a long-running campaign, or split a large area into several smaller stateKey campaigns.

Tip: with several locations, each location stops at its share of Max items (Max items divided by the number of locations). If a location stops at its share but the run as a whole stays under Max items, the run still counts as a complete scan, so that location's live deals that were not reached are returned as EXPIRED. On monitoring runs with Emit expired records, use one location per stateKey campaign or set Max items to 0.

Send results into your apps (MCP connectors)

Optionally pipe the scraped results into the apps you already use, via Model Context Protocol (MCP) connectors. This is an extra delivery step after the scrape: the Apify dataset is never changed.

What gets written to the connector: a condensed, human-readable summary of each record, not the full JSON. Each item becomes one entry with a title and its key fields flattened to plain text. The complete record always stays in the Apify dataset.

  1. Authorize a connector once under Apify → Settings → Integrations (Notion, Linear, Airtable, or Apify).
  2. Select it in the "Pipe results into your apps" input field. (If the picker is empty, you haven't authorized a connector yet.)
  3. For Notion, also set notionParentPageUrl to the page where items should be created.

The connection is mediated by Apify's MCP proxy, so this actor never sees your third-party credentials. Leave the field empty to skip.

Input Parameters

ParameterTypeDefaultDescription
modestringsearchsearch (locations) or url (store links or ids).
locationsarray["Detroit, Michigan"]Search mode: city or place names, or lat,lng coordinates.
radiusKminteger40Search mode: how far from each point to look, 1 to 160 km.
storeInputsarray["629cec56061cc242985326fd"]Url mode: store ids, or any link carrying one.
urlsarray(none)Alias for storeInputs, accepted under the name other Apify actors use for url mode.
maxItemsinteger20Stop after this many records (0 = no limit).
includeStoresbooleanfalseAlso emit one record per store, kind=store.
countryHintstring(none)CAD or USD. When set, every item's currency uses it instead of the value derived from the store's country.
resumeFromRunIdstring(none)Continue one interrupted run, skipping already-collected record ids.
incrementalModebooleanfalseReturn only new and changed records on recurring runs.
stateKeystring(none)Name or share an incremental-mode monitoring campaign.
emitUnchangedbooleanfalseAlso return (and bill) unchanged records.
emitExpiredbooleanfalseAlso return (and bill) expired records, after a complete scan.
mcpConnectorsarray(none)Optional: send a summary of each record to apps you authorized under Integrations.
notionParentPageUrlstring(none)Notion connector only: page under which records are created.
maxNotifyListingsinteger50Cap on items written to each connector per run.
proxyConfigurationobjectApify ProxyConnection settings.

Output Example

Sample shape: values are illustrative placeholders, not from a live listing.

{
"kind": "item",
"recordId": "6198765432abcdef0fedcba9",
"itemId": "6198765432abcdef0fedcba9",
"url": "https://www.flashfood.com/en/stores/6123456789abcdef01234567",
"title": "Sample Brand Multigrain Bread",
"price": 2.49,
"originalPrice": 4.99,
"discountPercent": 50.1,
"currency": "USD",
"quantityAvailable": 5,
"bestBefore": "2026-11-05T00:00:00+00:00",
"department": "Bakery",
"legacyDepartment": "Bakery",
"imageUrl": "https://img.example.com/sample-product.jpg",
"listedAt": "2026-10-30T09:15:00.000Z",
"isSnapEligible": false,
"storageTreatment": "NONE",
"storeId": "6123456789abcdef01234567",
"storeName": "Sample Grocery Market",
"banner": "Sample Banner Co.",
"street": "100 Example Ave",
"city": "Sample City",
"stateCode": "MI",
"countryCode": "US",
"latitude": 42.33,
"longitude": -83.05,
"raw": {},
"changeType": "NEW",
"changedFields": [],
"firstSeenAt": "2026-01-01T00:00:00+00:00",
"lastSeenAt": "2026-01-01T00:00:00+00:00"
}

Plan Requirement

The default proxy setting works out of the box, and the actor rotates connections automatically when one is refused. Run it on any plan that includes proxy access; no special tier is required for the catalogue this actor reads.

FAQ

How much does it cost?

You pay per record returned (deal or store), plus a per-run start charge. The Pricing tab shows the current rates. Use Max items to cap the cost of a search-mode run.

This actor reads only the publicly served catalogue the official app itself reads, with no account or login required. You are responsible for how you use it: follow Flashfood's terms and the laws that apply to you, and get legal advice if you plan commercial redistribution. Keep run volumes reasonable.

Can I get only new or changed deals on a schedule?

Yes. Schedule the actor from the Schedules tab and turn on Incremental mode. Each run then returns only new, updated and reappeared records, and unchanged ones are not billed unless you turn that on too.

Why did my run only cover part of a city?

One search query returns at most 100 stores around a point, nearest first, and the source ignores paging. Add more locations, or shrink the radius and add locations around the gap, to cover a large metro area completely.

A location returned nothing. Did I get an empty area, or did something fail?

Both are possible and they look different. A location with genuinely no stores in range returns cleanly with zero records for it. A location whose name could not be resolved to coordinates is skipped with a warning in the run log ("could not be resolved to coordinates"); the run still finishes successfully using the locations that did resolve. Check the log if a normally-active area came back empty, and prefer lat,lng for locations that must always be read.

Why did my run fail instead of returning an empty dataset?

If every request to the source is refused or unreadable, the run stops with a clear message so "no deals right now" is never confused with "nothing could be read". Run it again in a few minutes. If only some stores or batches could be read, you still get what was found.

Can I use it with AI agents or MCP?

Yes. Call it from any Apify integration or MCP client, and use the connector field to push results into Notion, Linear or Airtable.

🔗 Want more grocery data?

Pair this actor with these related scrapers from the same team:

🥦 FoodHero Scraper
Scrape FoodHero surplus grocery deals across Canada by area, store or offer ID. Extract...
🥦 Instacart Scraper
Scrape Instacart grocery catalogs with per-store prices. Run keywords across several...
🥦 ResQ Club Scraper
Scrape ResQ Club surplus food offers in Finland, Sweden and Estonia: name, price, current...
🥦 Coles AU Scraper
Scrape Coles.com.au grocery products and customer reviews. Search by keyword, browse...
🥦 ALDI AU Scraper
Scrape ALDI Australia (aldi.com.au) products: name, brand, price, was-price, savings...
🧩 Too Good To Go Scraper
Scrape Too Good To Go (TGTG) stores and surprise bags by location or item: price, value...

👉 Browse all abotapi scrapers

💬 Support

  • 🐞 Found a bug or a missing field? Open a ticket on the Issues tab. We usually reply within hours.
  • 🛠️ Need another site, extra fields or a private build? Email contact@abotapi.com.
  • ⭐ Enjoying it? A quick review on the actor page helps other users find it.