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

21

Total users

3

Monthly active users

a day 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
}

Supported URL shapes (URL mode). Leaving urls untouched scrapes five distinct examples (a venue, two city listings, a category and a brand); the remaining rows below are alternate forms that resolve to the same targets, so they are shown in the prefill but not run by default. Clear the field to use only your own links.

ShapeExampleBehaviour
Venuehttps://wolt.com/en/aut/graz/restaurant/kfc-grazOne venue.
City listinghttps://wolt.com/en/aut/graz/restaurantsVenues of that city.
City listing, other countryhttps://wolt.com/en/fin/helsinki/restaurantsVenues of that city.
City homehttps://wolt.com/en/aut/grazSame as the city listing.
Categoryhttps://wolt.com/en/aut/graz/category/pizzaCity venues filtered to that category.
Brandhttps://wolt.com/en/aut/graz/brand/kfcCity venues of that brand.
Legacy venuehttps://wolt.com/en/aut/graz/venue/kfc-grazMapped to the venue slug.
Other languagehttps://wolt.com/de/aut/graz/restaurant/kfc-grazAny prefix such as de or de-at works.
Other-language city pagehttps://wolt.com/fi/fin/helsinki/restaurantsSame as the English city page, in another language.
Sorted cityhttps://wolt.com/en/aut/graz/restaurants?sorting=ratingsorting= is applied as the sort order unless sortBy is set.
Venue with queryhttps://wolt.com/en/aut/graz/restaurant/kfc-graz?lang=deQuery string ignored.
Discoveryhttps://wolt.com/en/discoveryHas no city; skipped with a warning in the run log.

URLs without a language prefix (for example https://wolt.com/aut/graz/restaurant/kfc-graz) are not valid on wolt.com and are skipped with a warning.

Dataset views

The dataset has four tabs in the Apify Console: Restaurants (overview of every venue), Venue details (hours, fees, tipping, merchant block), Menu items (the menu per venue) and Changes (incremental) (changeType, changedFields and first/last seen dates, for scheduled runs).

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.

What counts as a change. A venue is UPDATED when any of its output fields changes (details, opening hours, delivery fees, menu items, prices and discounts); changedFields lists them. Excluded by default, while still present in the output: scrapedAt, deliveryEstimateMinutes, deliveryTimeRangeMin, deliveryTimeRangeMax, serpSortable, estimateMinutes, estimateRange, online and delivers (live counters that change on every scrape). Use ignoreFieldsForChanges to exclude more, with a dot for nested fields that applies to every list element (for example menuItems.blurhash). Changing the ignore list never produces a one-time wave of UPDATED rows.

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 stringsfive distinct example URLs (see below)Wolt venue, city, category or brand 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.
maxItemsintegernoneAlias of maxVenues; when set it takes precedence.
latitudenumbernoneSearch around an exact point (use with longitude), added to any cities. Leave cities empty to search only that point.
longitudenumbernoneLongitude of the exact point; see latitude.
categoryFilterstringnoneFree-text cuisine or tag filter (for example burger, pizza, sushi); keeps venues whose category or tag name contains it.
includeDetailsbooleantrueTurn off for basic listing rows without the menu fetch.
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.
ignoreFieldsForChangesstring[]noneIncremental mode only. Fields (dotted paths for nested) that never count as a change; they stay in the output.
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. The default Apify proxy is tried first; if a request is refused, the actor retries it over Residential geo-targeted at the searched city's own country, or over a backup connection when your plan has no residential access. See "Plan Requirement".
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

A paid Apify plan is recommended. Venue pages, menus and most city listings load over the default proxy setting. Wolt's city listing endpoint refuses some datacenter exits, so the actor starts on the proxy you configure and, when a request is refused, retries it over Residential geo-targeted at the searched city's own country. Selecting Residential in proxyConfiguration up front avoids the wasted first attempt. Free Apify plans include no residential proxies, so on a free plan some city listings can fail to load.

What you will see in the run log:

  • Warning when the selected connection is unavailable: "The selected connection is unavailable to this run. Apify free plans do not include residential proxies. Continuing on a backup connection; some pages may still be unavailable."
  • Info once pages are served that way: "Served over the backup connection (the default connection was unavailable)."
  • The run fails (instead of returning a silent empty dataset) when no page could be loaded at all. The message says either that the proxy connection was refused for this account and a paid plan is required, that residential proxies are unavailable and the backup connection could not load the requested Wolt pages, or that the requests failed and this is a connection problem, not an empty search. That connection message appears only when a request really failed. When nothing loaded because the input matched nothing, the run also fails, with a specific message instead: a city name that matches no Wolt city, a URL city that Wolt does not have, URLs that are not scrapable Wolt pages (discovery or language-less), URL mode with no URLs, or venues Wolt reports as not found.

You can also supply your own proxy URLs in proxyConfiguration.

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. When at least one other page loaded, a city that cannot be resolved, a city listing that Wolt refuses or fails to return, or an unrecognized URL is skipped with a warning in the run log rather than failing the run, so a short dataset can come from these too; check the log. If nothing at all loaded, the run fails with a message naming the unmatched city, the unusable URL or the venue that was not found. 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 e-commerce data?

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

πŸ›’ GrabFood Restaurant Scraper
Scrape GrabFood restaurants across Southeast Asia, including SG, MY, TH, VN, PH, ID, KH...
πŸ›’ DoorDash Scraper
Extract structured doordash.com data at scale. Search by keyword or paste store URLs to...
✈️ Naver Map Scraper
Scrape Naver Map places by keyword or URL: names, categories, ratings, phones, addresses...
πŸ›’ Zomato Scraper
Scrape restaurants and reviews from zomato.com. Get names, cuisines, ratings and votes...
πŸ₯¦ ResQ Club Scraper
Scrape ResQ Club surplus food offers in Finland, Sweden and Estonia: name, price, current...
🧩 OpenTable Reviews Scraper
Scrape full OpenTable.com restaurant reviews by keyword, area, or restaurant profile...

πŸ‘‰ 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.