Wolt.com $0.8๐Ÿ’ฐ URL | City Search | Restaurants and Menus avatar

Wolt.com $0.8๐Ÿ’ฐ URL | City Search | Restaurants and Menus

Pricing

from $0.80 / 1,000 results

Go to Apify Store
Wolt.com $0.8๐Ÿ’ฐ URL | City Search | Restaurants and Menus

Wolt.com $0.8๐Ÿ’ฐ URL | City Search | Restaurants and Menus

From $0.8/1K. Scrape Wolt restaurants and full menus at the city scale. Extract 60+ fields, including name, address, GPS, hours, ratings, tags, menus with images and prices, delivery zones, fees, minimum order, and merchant details. Supports city search or URL input with fast, rich output.

Pricing

from $0.80 / 1,000 results

Rating

0.0

(0)

Developer

Abot API

Abot API

Maintained by Community

Actor stats

0

Bookmarked

20

Total users

2

Monthly active users

5 days ago

Last modified

Share

Wolt Scraper: Restaurant Listings, Menus and Delivery Data

Wolt Scraper turns Wolt into a structured restaurant and menu data feed. Search by city name or paste Wolt links to collect venue details such as address, GPS coordinates, contact info, opening and delivery hours, ratings, delivery fees, order minimum and the merchant's legal block, plus, on request, the venue's full menu with categories, items, images, prices and discounts. Filter by cuisine, minimum rating or review count, then export to JSON, CSV or Excel, or read the results straight through the API.

Why This Scraper?

  • 70+ named fields per venue, covering address, GPS, contact info, opening and delivery hours, ratings, delivery fees, order minimum, tipping configuration and the merchant's legal block (registered name, business ID, registered address).
  • Full menu surface, on or off per run. Categories and items with images and blurhashes, current and original prices, discount and lowest-price fields, VAT rate, dietary tags, alcohol content and per-unit pricing for items sold by weight.
  • Brand identity fields (brand slug, brand name, brand logo image and its blurhash) so the same chain scraped across different cities can be matched up later.
  • Delivery polygon as full GeoJSON, plus opening hours and delivery hours kept as two separate weekly schedules.
  • Two ways to find venues: search by city name, with a geocoding fallback for places outside Wolt's own city directory, or paste Wolt venue and city-listing URLs directly.
  • Cuisine, minimum rating and minimum review count filters, plus a sort order, to narrow a city listing before every venue is enriched.
  • Built for schedules. Incremental mode tracks new, updated and no-longer-listed venues across recurring runs.

Use Cases

  • Food delivery market research: compare menu prices, delivery fees and order minimums for the same cuisine across several cities.
  • Franchise and chain tracking: consolidate a brand's presence and pricing across every city it operates in, using the brand slug shared by all its venues.
  • Competitive menu intelligence: track price changes, discounts and new menu items on competitor restaurants over time with incremental mode.
  • Compliance and legal research: collect the merchant legal block (registered business name, business ID, registered address) that Wolt publishes for each venue.
  • Local directories and apps: build a directory of restaurants with hours, ratings, delivery zones and contact details for a city or region.

Data You Get

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

FieldExample
venueId / slug"00000000000000000000000a" / "sample-burger-place"
name / description"Sample Burger Place" / "Best burgers in town."
brandSlug / brandName"sample-burger" / "Sample Burger"
address / city / countryCode"Sample Street 1" / "Helsinki" / "FIN"
phone / website"+35800000000" / "https://example.com"
woltUrl"https://wolt.com/en/fin/helsinki/restaurant/sample-burger-place"
latitude / longitude60.0 / 24.0
currency"EUR"
deliveryBasePrice / deliveryBasePriceFormatted199 / "โ‚ฌ1.99"
orderMinimum / orderMinimumFormatted1000 / "โ‚ฌ10.00"
serviceFeeMin / serviceFeeMax / serviceFeePercentage45 / 99 / 3
isWoltPlus / isPickupFriendlytrue / false
priceRange1 (1 to 4 wallet icons)
foodTags["burger", "fries"]
categories[{ "name": "American", "slug": "american", "primary": true }]
rating / ratingScore / ratingVolume3 / 8 / 200
workingHours7-day array of { day, formatted_times }
deliveryHours7-day array, kept separate from workingHours
deliveryGeoRangefull GeoJSON Polygon
tipping{ currency, tip_amounts, max_amount, min_amount, type }
merchant{ id, name, business_id, street_address, city, post_code, country }
digitalServicesActmerchant self-certification and reporting fields
menuCategoryCount / menuItemCount13 / 96
scrapedAt"2026-01-01T00:00:00.000Z"
changeTypeincremental mode only, see below

When "Fetch full menu" is on, the same record also carries menuCategories (each with id, slug, name, image, blurhash, itemCount, subcategoryCount) and menuItems, an array where each item carries over 40 fields: name, description, image, blurhash, currency, current and original price in cents, discount amount and percent, a lowest-price-in-the-last-30-days pair, VAT rate and VAT category, dietary preferences, tags, allowed delivery methods, alcohol content in per mille, per-unit pricing for weighed items, cutlery and visibility flags, and quantity limits. With "Fetch full menu" off, these fields are all null and the record is venue-only.

How to Use

  1. Pick a mode: search (by city name) or url (paste Wolt links).
  2. Fill in cities or urls, and optionally set a cuisine filter, a minimum rating or a minimum review count.
  3. Toggle "Fetch full menu" and "Include rating fields", set a language, and cap the run with maxVenues or maxVenuesPerCity.
  4. Click Start, then download the dataset as JSON, CSV or Excel, or read it through the API.

Find restaurants in one city:

{
"mode": "search",
"cities": ["Helsinki"],
"fetchMenu": true,
"maxVenues": 25
}

Multi-city, cuisine filter, rating floor:

{
"mode": "search",
"cities": ["Helsinki", "Stockholm", "Berlin"],
"primaryCategories": ["pizza", "italian"],
"minRating": 8,
"minRatingVolume": 50,
"fetchMenu": true,
"maxVenuesPerCity": 10,
"maxVenues": 30
}

Direct URLs, single venues:

{
"mode": "url",
"urls": [
"https://wolt.com/en/aut/graz/restaurant/kfc-graz",
"https://wolt.com/en/fin/helsinki/restaurant/sample-burger-place"
],
"fetchMenu": true
}

Direct URLs, city listing pages:

{
"mode": "url",
"urls": [
"https://wolt.com/en/aut/graz/restaurants",
"https://wolt.com/en/fin/helsinki/restaurants"
],
"fetchMenu": false,
"maxVenues": 100
}

Run it from your code

Python:

from apify_client import ApifyClient
client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("abotapi/wolt-restaurants-scraper").call(run_input={"mode": "search", "cities": ["Helsinki"]})
for venue in client.dataset(run["defaultDatasetId"]).iterate_items():
print(venue["name"], venue["address"])

JavaScript:

import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: '<YOUR_APIFY_TOKEN>' });
const run = await client.actor('abotapi/wolt-restaurants-scraper').call({ mode: 'search', cities: ['Helsinki'] });
const { items } = await client.dataset(run.defaultDatasetId).listItems();

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

Resume vs incremental mode

These are two different things.

Resume (resumeFromRunId) continues one specific interrupted run, for example { "mode": "search", "cities": ["Helsinki"], "maxVenues": 500, "resumeFromRunId": "PREVIOUS_RUN_ID" }. Paste a previous run ID or dataset ID and this run skips venues already collected there, returning only the remaining new ones.

Incremental mode (incrementalMode) is for scheduling this actor daily or weekly against the same search and getting only what changed, for example { "mode": "search", "cities": ["Helsinki"], "incrementalMode": true }. The actor remembers the previous run itself, no run ID needed. The first run returns everything as NEW. Later runs return only NEW and UPDATED venues (with changedFields); unchanged venues are suppressed and not billed unless emitUnchanged is on. EXPIRED rows are only produced when emitExpired is on and a run scans its whole tracked search completely, meaning it was not capped by maxVenues or maxVenuesPerCity, not a resumeFromRunId run, and every city or URL resolved and loaded cleanly. REAPPEARED only ever appears for a venue that an earlier run had already marked EXPIRED under that same condition; if emitExpired has never been turned on for a search, no venue can be marked gone, so REAPPEARED will never occur. stateKey names or shares the stored state; leaving it blank derives one automatically from the cities, URLs, filters and menu settings, so different searches never mix state.

Combining incrementalMode with resumeFromRunId bootstraps a fresh incremental baseline from a large resumed pull, but only on a genuinely first run for that state key. If incremental state already exists for it, the run fails rather than silently mixing the two.

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 (by city) or url (paste Wolt links).
citiesarray of stringsnone in the schema (prefill: ["Helsinki"]); falls back to ["Helsinki"] if left empty in search modeCity names or free-text places. Wolt's own city directory is matched first, anything else falls back to geocoding. Search mode only.
urlsarray of stringsnone (prefill: one example Wolt venue URL)Wolt venue or city-listing URLs. URL mode only.
primaryCategoriesarray of stringsnoneCuisine slugs (pizza, sushi, vegan, kebab, etc.). Empty means all.
minRatinginteger, 0 to 10noneMinimum venue score on the 0-10 scale. Leave empty for no minimum.
minRatingVolumeinteger0Minimum review count to include.
sortBystringdefaultOrder of venues within each city: default (Wolt's own ranking), rating, delivery-price, delivery-estimate, distance or preparation-estimate.
fetchMenubooleantrueWhen on, every venue is enriched with the full menu. Off for faster venue-only runs.
includeReviewsbooleantrueWhen on, populates rating, ratingScore and ratingVolume.
languagestringenISO language code passed to Wolt for menu and venue text.
maxVenuesinteger50Hard cap on total venues across the whole run. 0 means unlimited.
maxVenuesPerCityinteger0Per-city cap. 0 means unlimited per city.
resumeFromRunIdstringnoneContinue one specific interrupted run. See "Resume vs incremental mode" above.
incrementalModebooleanfalseCross-run change detection for recurring runs. Adds changeType to every row. See above.
stateKeystringnone, auto-derivedNames an incremental-mode monitoring campaign. Leave empty to derive one automatically from cities, URLs, filters and menu settings.
emitUnchangedbooleanfalseIncremental mode only. Also return, and bill, venues that have not changed since the last run.
emitExpiredbooleanfalseIncremental mode only. Also return, and bill, venues no longer found, once a run has fully scanned the tracked search.
proxyConfigurationobject{ "useApifyProxy": true }Proxy settings. City search needs a residential exit: if the default proxy is refused, the actor retries that request over Residential, geo-targeted at the searched city's own country.
mcpConnectorsarraynoneOptional: send a summary of each record to apps you authorized under Integrations.
notionParentPageUrlstringnoneNotion connector only: page under which item pages are created.
maxNotifyListingsinteger50Cap on items written to each connector per run. Does not affect the dataset.

Output Example

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

{
"venueId": "00000000000000000000000a",
"slug": "sample-burger-place",
"name": "Sample Burger Place",
"description": "Best burgers in town.",
"brandSlug": "sample-burger",
"brandName": "Sample Burger",
"brandLogoImage": "https://imageproxy.wolt.com/mes-image/00000000-0000-0000-0000-000000000000/00000000-0000-0000-0000-000000000000",
"brandLogoBlurhash": "LKO2?V%2Tw=w]~RBVZRi};RPxuwH",
"coverImage": "https://imageproxy.wolt.com/assets/000000000000000000000000",
"coverBlurhash": "jkSsmKKXhXhq;;KXJAKXHtlmJjKW",
"address": "Sample Street 1",
"city": "Helsinki",
"cityId": "0000000000000000000000aa",
"citySlug": "helsinki",
"postCode": "00100",
"countryCode": "FIN",
"phone": "+35800000000",
"website": "https://example.com",
"woltUrl": "https://wolt.com/en/fin/helsinki/restaurant/sample-burger-place",
"latitude": 60.0,
"longitude": 24.0,
"timezone": "Europe/Helsinki",
"currency": "EUR",
"deliveryMethods": ["homedelivery"],
"deliveryBasePrice": 199,
"deliveryBasePriceFormatted": "โ‚ฌ1.99",
"serviceFeeMin": 45,
"serviceFeeMax": 99,
"serviceFeePercentage": 3,
"orderMinimum": 1000,
"orderMinimumFormatted": "โ‚ฌ10.00",
"deliveryGeoRange": { "type": "Polygon", "coordinates": "..." },
"isPickupFriendly": false,
"isWoltPlus": true,
"ncdAllowed": true,
"groupOrderEnabled": true,
"priceRange": 1,
"foodTags": ["burger", "fries"],
"categories": [{ "name": "American", "slug": "american", "primary": true }],
"rating": 3,
"ratingScore": 8,
"ratingVolume": 200,
"workingHours": [
{ "day": "Monday", "formatted_times": "10:00-22:00" },
{ "day": "Tuesday", "formatted_times": "10:00-22:00" }
],
"deliveryHours": [
{ "day": "Monday", "formatted_times": "10:00-22:00" }
],
"tipping": {
"currency": "EUR",
"tip_amounts": [100, 200, 500],
"max_amount": 10000,
"min_amount": 50,
"type": "pre_tipping_amount"
},
"merchant": {
"id": "0000000000000000000000ab",
"name": "Sample Operator GmbH",
"business_id": "FN 000000 a",
"street_address": "Sample Address 1",
"city": "Sample City",
"post_code": "00000",
"country": "Sample Country"
},
"digitalServicesAct": {
"name": "Sample Operator GmbH",
"business_id": "FN 000000 a",
"address": "Sample Address 1, 00000 Sample City, Sample Country",
"self_certification": "...",
"report_item_url": "https://www.example.com/report"
},
"assortmentId": "00000000000000000000000b",
"primaryLanguage": "fi",
"selectedLanguage": "en",
"availableLanguages": [
{ "language": "fi", "name": "Finnish", "autotranslated": false },
{ "language": "en", "name": "English", "autotranslated": true }
],
"menuCategoryCount": 13,
"menuItemCount": 96,
"menuCategories": [
{
"id": "00000000000000000000000c",
"slug": "burgers-1",
"name": "Burgers",
"image": "https://wolt-menu-images-cdn.wolt.com/menu-images/sample.jpg",
"blurhash": "UkSFbBRj.Tx[sRjZW=WX%~odI9R+XAbIn#n$",
"itemCount": 7,
"subcategoryCount": 0
}
],
"menuItems": [
{
"id": "00000000000000000000000d",
"categoryId": "00000000000000000000000c",
"categoryName": "Burgers",
"categorySlug": "burgers-1",
"name": "Sample Burger",
"description": "Beef patty, lettuce, tomato.",
"image": "https://wolt-menu-images-cdn.wolt.com/menu-images/sample.jpg",
"blurhash": "UkSFbBRj.Tx[sRjZW=WX%~odI9R+XAbIn#n$",
"currency": "EUR",
"currentPrice": "EUR 9.90",
"currentPriceCents": 990,
"originalPriceCents": 1090,
"discounted": true,
"discountAmount": 100,
"discountPercent": 9,
"lowestPriceCents": 990,
"lowestPriceWindowDays": 30,
"dietaryPreferences": [],
"vatPercentage": 14,
"tags": [],
"allowedDeliveryMethods": ["homedelivery"],
"isAlcohol": false,
"isWoltPlusOnly": false
}
],
"scrapedAt": "2026-01-01T00:00:00.000Z"
}

Plan Requirement

The default proxy setting works out of the box for single-venue URLs and menu fetches. City search and city-listing URLs additionally need a residential exit: the actor starts on whatever proxy you configure and automatically retries a refused request over Residential, geo-targeted at the searched city's own country. Selecting Residential in the proxyConfiguration input up front avoids that wasted first attempt. Override any of this via the proxyConfiguration input field.

FAQ

How much does it cost?

You pay per venue returned; turning on "Fetch full menu" makes each venue record larger but does not add a separate charge. The Pricing tab shows the current rates. Use maxVenues or maxVenuesPerCity to cap the cost of any run.

This actor collects only publicly available restaurant and menu data. You are responsible for how you use it: follow Wolt's terms and the laws that apply to you, and get legal advice if you plan commercial redistribution. Menu names, prices and hours are generally facts, but photos and brand assets may carry separate rights.

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

Yes. Schedule the actor from the Schedules tab and turn on Incremental mode. Later runs return only NEW and UPDATED venues; unchanged ones are suppressed and not billed. REAPPEARED rows only ever occur for a venue that a previous run had already marked EXPIRED, which itself only happens when Emit expired venues was on for a run that scanned its search completely. If you never turn on Emit expired venues, you will never see REAPPEARED.

What's the difference between Resume and Incremental mode?

resumeFromRunId continues one specific interrupted run and is a one-time thing: paste a run or dataset ID and this run skips venues already collected there. incrementalMode is for running the exact same search again and again on a schedule; the actor remembers state itself, no ID needed. See "Resume vs incremental mode" above for the full behavior, including how the two combine.

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

An empty dataset with a successful run is normal when a city search or filter combination genuinely matches nothing, for example a cuisine filter, minimum rating or minimum review count that excludes every venue in a city, or a URL that doesn't resolve to any venues. A city that cannot be resolved, a city listing that Wolt refuses or fails to return, or an unrecognized URL is also skipped with a warning in the run log rather than failing the run, so a short or empty dataset can come from these too; check the log. Individual venues that come back not found, or still fail after retries, are skipped and counted in the run log; they do not fail the whole run. The run fails outright (the specific reason is in the run log) when the actor cannot load Wolt's own city directory at all (used to resolve city names and city-listing URLs), when a pasted "Resume from a previous run" ID does not match a run or dataset your account can read, when Incremental mode is combined with Resume for a state key that already has saved incremental state, or on any other unexpected error.

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 wine and drinks data?

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

๐Ÿท Vivino Wine Scraper
From $1.2/1K. Scrape Vivino.com for wine ratings, prices, taste profiles, food pairings...
๐Ÿท Wine-Searcher Scraper
Look up wines on wine-searcher.com by name, URL, or LWIN code. Returns 30+ fields...
๐Ÿท Carrefour Spain Scraper
Scrape Carrefour Spain (carrefour.es) products. Search by keyword, browse a category, or...
๐Ÿท Untappd Beer, Brewery and Check-in Scraper
Scrape Untappd beers, breweries, venues and check-ins by keyword, brewery, Top Rated...
๐Ÿท Dan Murphyโ€™s Scraper
Scrape Dan Murphyโ€™s products by category, keyword, or specials. Extract 45+ fields...
๐Ÿ›’ GrabFood Restaurant Scraper
Scrape GrabFood restaurants across Southeast Asia, including SG, MY, TH, VN, PH, ID, KH...

๐Ÿ‘‰ Browse all abotapi scrapers

๐Ÿ’ฌ Support & custom scrapers

  • ๐Ÿž 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 abotapi@proton.me or message Telegram @abotapi.
  • โญ Enjoying it? A quick review on the actor page helps other users find it.