Flashfood Scraper at a glance
Flashfood Scraper is a ready-to-run Apify actor from abotapi for collecting web data. Its documented output includes kind, recordid, itemid, url and apiurl, which you can export as JSON, CSV or Excel or read through the Apify API. It costs $2.50 per 1,000 results on the Apify Free plan and from $1.80 on paid plans, with smaller per-run or optional feature charges listed on Apify.
- Runs on
- Apify cloud: console, API, schedules and integrations
- Data type
- Web data
- Pricing
- $2.50 per 1,000 results (Free plan), from $1.80 on paid plans
- Output
- Documented below · JSON, CSV, Excel
- Inputs
- 28 options
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.
What Flashfood Scraper can do
- 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.
Choose what to collect
These inputs let you configure Flashfood Scraper - Discounted Groceries, Prices & Availability. Open the actor on Apify to enter your values and review the current options.
| Input | What it controls |
|---|---|
modestring · required | Search finds stores and their discounted food around one or more locations. Store mode reads one or more stores by id or link. |
locationsarray | Where to search: one entry per location. A city or place name (Detroit, Toronto, M4C 1A5), or exact coordinates as lat,lng (42.3314,-83.0458). Names are resolved automatically. The source covers the US and Canada. |
radiusKminteger | Search mode: how far from each point to look, 1 to 400 km. A single query still returns at most 100 stores, nearest first. |
countriesarray | Keep only stores in these countries. Empty means both Canada and the United States. |
bannersarray | Keep only these store chains, for example Loblaws or Metro. Case and accent-insensitive, partial match. Empty means all. |
keywordsarray | Keep only items whose name has a word starting with the keyword (several words in one keyword must all match). Empty means all. |
departmentsarray | Keep only these departments, in English or French (Bakery, Boulangerie). Partial, case and accent-insensitive match. Empty means all. |
Show 21 more inputs
| Input | What it controls |
|---|---|
minDiscountPercentinteger | Keep only items discounted by at least this percent. |
maxPricestring | Keep only items priced at or below this amount, for example 5 or 4.99. |
expiringWithinDaysinteger | Keep only items whose best-before date is within this many days (0 = today or already past). |
maxStoresinteger | Read at most this many stores, nearest first. |
fullNetworkboolean | Search mode: ignore Locations and sweep a built-in list of about 45 Canadian and US metro areas, 160 km each, de-duplicating stores. Combine with Max items and the filters. Coverage is the stores within reach of those areas. |
storesOnlyboolean | Return only store records (kind=store, with item counts) and no deal items. Store records are billed like any other record. |
emitSoldOutboolean | With Emit expired on, items that disappeared from a store that was read this run are returned as SOLD_OUT. Turn off to drop those rows. |
storeInputsarray | URL mode: a store id, a store link (…/api/v1/stores/), an items link (…/api/v1/items/?storeIds=), or a stores-near-a-point link with latitude, longitude and optional maxDistance in meters. The website locations page carries no store id and is skipped with a warning. Multi-value supported. |
urlsarray | Alias for Store links or ids, accepted under the name other Apify actors use for URL mode. Same shapes and the same default examples; used only when Store links or ids is not given. |
maxItemsinteger | Stop after this many records (0 = no limit; the run then stops when stores or items run out). |
includeStoresboolean | Off by default: the dataset then carries the discounted food items only. Turn on to also emit one record per store (name, banner, address, hours, pickup instructions). |
countryHintstring | Optional. Fill the currency field of item records with CAD or USD for stores that do not state a country. Leave empty to derive the currency from each store's country automatically. |
resumeFromRunIdstring | Paste a previous run ID or dataset ID to continue a large pull without returning items already collected there. |
incrementalModeboolean | Turn this on for daily or recurring monitoring. The first run returns every matching record as NEW. Later runs normally return only NEW, UPDATED and REAPPEARED records. Turn on Emit unchanged or Emit expired only when you also want those rows returned (and billed). State is kept separately for each search, filter and lookup setup; use State key to name or deliberately share a monitoring campaign. |
stateKeystring | Optional. Name this monitoring campaign to keep its state stable, or deliberately share state across differently configured runs. Leave empty to let the actor derive a key automatically from the search and filter settings. |
emitUnchangedboolean | Off by default. Turn on to also return records that have not changed since the last run, marked UNCHANGED. This returns, and bills, extra rows you already have. |
emitExpiredboolean | Off by default. Turn on to also return records that were present in a previous run but are no longer found, marked EXPIRED. Only produced once a run has fully scanned the tracked search. |
ignoreFieldsForChangesarray | Output field names that should NOT make a record count as UPDATED. Always ignored: distanceKm, daysToExpiry, scrapedAt, queryLocation, apiUrl and the derived fields name, gtin, savings, departmentFr, address, website, itemCount and timezone (they depend on where or when you search, not on the deal). Add fields such as quantityAvailable here if changes to them are not relevant to you. Use a dotted path (for example raw.price) for a field inside a nested object. Ignored fields are still returned in the output. |
mcpConnectorsarray | Optionally send results into the apps you already use, via Model Context Protocol (MCP) connectors. Authorize one under Apify, Settings, API & Integrations, then select it here. Notion gets a rich page-per-item export; other connectors get a best-effort write or digest. Leave empty to skip; never changes the dataset output. |
notionParentPageUrlstring | URL or id of the Notion page under which item pages are created. Required to enable the Notion export; ignored by other connectors. |
maxNotifyListingsinteger | Cap on items written to each connector per run. Does not affect the dataset. |
Fields in the output
The documented dataset includes the fields below. Availability can depend on the source page and selected mode.
kindkindrecordIdrecordIditemIditemIdurlurlapiUrlapiUrltitletitlepricepriceoriginalPriceoriginalPricediscountPercentdiscountPercentcurrencycurrencyquantityAvailablequantityAvailablebestBeforebestBeforeShow 38 more fields
departmentdepartmentlegacyDepartmentlegacyDepartmentlistedAtlistedAtimageUrlimageUrlisSnapEligibleisSnapEligiblestorageTreatmentstorageTreatmentstoreIdstoreIdstoreNamestoreNamebannerbannerstreetstreetcitycitystateCodestateCodecountrycountrycountryCodecountryCodelatitudelatitudelongitudelongitudedistanceKmdistanceKmphonephonediscountPercentagediscountPercentageisEBTEnabledisEBTEnabledpickupInstructionspickupInstructionscheckoutInstructionscheckoutInstructionsstoreHoursstoreHourschangeTypechangeTypechangedFieldschangedFieldsfirstSeenAtfirstSeenAtlastSeenAtlastSeenAtnamenamegtingtindaysToExpirydaysToExpirysavingssavingsdepartmentFrdepartmentFraddressaddresswebsitewebsiteitemCountitemCountpreviousPricepreviousPricepreviousQuantitypreviousQuantityunitsSoldSinceLastRununitsSoldSinceLastRunExample output
An example from this actor’s documentation. Values are illustrative; this is not a fresh live result.
{
"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"
}Ways to use this data
- 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.
Before you run
Start with a small input and check the resulting records against your expected fields. Source content and actor options can change; the current Apify listing is the reference for availability and pricing.
Questions about this actor
What data does Flashfood Scraper return?
The documented output for Flashfood Scraper includes kind, recordid, itemid, url, apiurl, title, price and originalprice. Availability of each field depends on the source page and the selected mode.
How much does Flashfood Scraper cost?
It costs $2.50 per 1,000 results on the Apify Free plan and from $1.80 on paid plans, with smaller per-run or optional feature charges listed on Apify. The Apify listing shows the current rate for every plan.
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.
