Too Good To Go Scraper: Stores, Surprise Bags & Availability
Pricing
from $1.80 / 1,000 bag or store records
Too Good To Go Scraper: Stores, Surprise Bags & Availability
Scrape Too Good To Go (TGTG) stores and surprise bags by location or item: price, value, savings, quantity, pickup windows, ratings, favorites and store details. Availability monitoring (NEW, UPDATED, REAPPEARED, EXPIRED), detail enrichment, incremental runs, MCP export.
Pricing
from $1.80 / 1,000 bag or store records
Rating
5.0
(1)
Developer
Abot API
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
2
Monthly active users
2 days ago
Last modified
Categories
Share
Too Good To Go Scraper - Stores & Surprise Bags
Scrape Too Good To Go (toogoodtogo.com), the app-first food-waste marketplace, directly from the same mobile service the official app uses. This actor returns surprise-bag listings and store details around any location: price, value, savings, quantity available, pickup windows, ratings, favorite counts, categories, addresses and geo coordinates. It also monitors availability across runs (NEW, UPDATED, REAPPEARED, EXPIRED), enriches each item from its detail endpoint, and pipes results into your apps through MCP connectors.
Why This Scraper?
- Real mobile-service data: bag listings with exact quantity available, pickup window, price and value in one record, not a scraped map screenshot.
- Location search around one or many points, with a per-location share of the item budget so multi-city runs stay balanced.
- Item mode: paste item links or numeric ids for fully enriched single-item reads.
- Availability monitoring: scheduled runs classify every record as NEW, UPDATED, UNCHANGED, REAPPEARED or EXPIRED, with per-campaign state you can name or share.
- Detail enrichment toggle: fuller description and tab data per item, billed as a separate per-item event only when the fetch succeeds.
- MCP connector export: send results to Notion and other connectors without changing the dataset.
- Structured failures: a blocked or unauthorized run fails loudly with a clear message instead of returning an empty dataset.
Data You Get
Sample shape: values are illustrative placeholders, not from a live listing.
| Field | Example value |
|---|---|
| kind | bag |
| itemId | 00000001 |
| url | https://www.toogoodtogo.com/en-us/item/00000001 |
| title | Espresso House - Dom Aquarée (Überraschungstüte) |
| itemName | Überraschungstüte |
| category | Baked goods |
| storeName | Sample Store |
| branch | Mitte |
| price | 3.99 |
| currency | EUR |
| value | 12.0 |
| savingsPercent | 66.7 |
| quantityAvailable | 3 |
| pickupStart | 2026-01-01T16:30:00Z |
| pickupEnd | 2026-01-01T18:00:00Z |
| soldOutAt | null |
| favoriteCount | 214 |
| ratingAverage | 4.7 |
| ratingCount | 96 |
| itemTags | 3 left |
| dietTags | vegetarian |
| street | Sample Street 12 |
| city | Berlin |
| postalCode | 10115 |
| country | Germany |
| countryCode | DE |
| latitude | 52.5305 |
| longitude | 13.3902 |
| distanceKm | 1.24 |
| storeWebsite | https://sample-store.example |
| inSalesWindow | true |
| changeType | NEW |
| firstSeenAt / lastSeenAt | 2026-01-01T00:00:00.000Z |
Every record also carries the full upstream item object (raw) and the full store block (storeRaw), so no upstream field is ever dropped.
How to Use
Zero setup: the source requires a free app account for every data route, and the actor handles that account for you: on first use it self-registers one free app account (the signup is confirmed automatically), stores that session encrypted, and reuses it in every later run. Nothing to provide, nothing to configure.
Input Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
| mode | select | search | search (locations) or url (item links or ids) |
| locations | list | Berlin | Where to search — city or place names (Berlin, 10115 Berlin, Paris), or exact coordinates as lat,lng |
| radiusKm | integer | 5 | Search radius in km, 0.5 to 100 |
| dietCategories | multi-select | empty | vegan, vegetarian, halal, kosher, pescatarian, gluten-free |
| searchPhrase | string | empty | Only stores matching this text (search mode) |
| withStockOnly | boolean | false | Hide sold-out listings (search mode) |
| weCareOnly | boolean | false | Only We Care labeled stores (search mode) |
| favoritesOnly | boolean | false | Only the account's favorite stores (search mode) |
| itemInputs | array | empty | Item links or numeric ids (url mode) |
| allowAutoSignup | boolean | true | Automatic account self-registration (hidden; managed by the actor) |
| fetchDetails | boolean | false | Fetch each item's detail endpoint; billed as detail-enrichment |
| maxItems | integer | 20 | Stop after this many records (0 = no limit) |
| maxPages | integer | 100 | Page walk bound per location; the run stops at maxItems first |
| resumeFromRunId | string | empty | Continue one interrupted run, skipping collected ids |
| incrementalMode | boolean | false | Recurring monitoring with change detection |
| stateKey | string | empty | Name a monitoring campaign (incremental mode) |
| emitUnchanged | boolean | false | Also return UNCHANGED rows (returns and bills extra rows) |
| emitExpired | boolean | false | Also return EXPIRED rows after a complete scan |
| mcpConnectors | array | empty | Optional MCP connector export |
| notionParentPageUrl | string | empty | Notion parent page for the Notion connector |
| maxNotifyListings | integer | 50 | Cap per connector per run |
| proxyConfiguration | object | proxy on | Standard Apify proxy settings |
Filters apply to search mode only; url mode ignores them because each item is read directly.
Output Example
Sample shape: values are illustrative placeholders, not from a live listing.
{"kind": "bag","itemId": 00000001,"url": "https://www.toogoodtogo.com/en-us/item/00000001","title": "Surprise Bag","description": "Assorted baked goods, contents revealed at pickup.","itemType": "MAGIC_BAG","price": 3.99,"currency": "EUR","value": 12.0,"savingsPercent": 66.7,"quantityAvailable": 3,"pickupStart": "2026-01-01T16:30:00Z","pickupEnd": "2026-01-01T18:00:00Z","soldOutAt": null,"favoriteCount": 214,"favorite": false,"ratingAverage": 4.7,"ratingCount": 96,"itemTags": ["3 left"],"dietTags": ["vegetarian"],"imageUrl": "https://images.example/cover.jpg","inSalesWindow": true,"storeId": "00001","storeName": "Sample Store","branch": "Mitte","street": "Sample Street 12","city": "Berlin","postalCode": "10115","country": "Germany","countryCode": "DE","latitude": 52.5305,"longitude": 13.3902,"distanceKm": 1.24,"storeWebsite": "https://sample-store.example","storeTimeZone": "Europe/Berlin","storeFavoriteCount": 1893,"storeRaw": { "full upstream store object" },"raw": { "full upstream item object" },"changeType": "NEW","changedFields": [],"firstSeenAt": "2026-01-01T00:00:00.000Z","lastSeenAt": "2026-01-01T00:00:00.000Z"}
Plan Requirement
The source requires a free account session (see How to Use). The actor uses the Apify proxy with automatic exit rotation and session refresh; run it on any plan that includes proxy access. Detail enrichment adds a per-item request and is billed through the separate detail-enrichment event only for records where the detail read succeeded.