Wolt coverage: 23 countries, every region verified
We've parsed and verified restaurants across 23 countries end-to-end —
every one of them tested with real URLs, real menus, real photos. This isn't
a list of countries "in theory supported" by scraping wolt.com —
these are markets where we've actually confirmed the parser works perfectly,
edge cases and all.
Across these markets we've hit every edge case Wolt can throw at a scraper:
right-to-left scripts (Hebrew in Israel, Arabic in mixed-Arabic restaurants),
five-language menus (Aroma Coffee in Tbilisi serves ka + en + ru + de + tr),
zero-decimal currencies (ISK, JPY-ready), de-facto integer currencies
(KZT, AMD, HUF, ALL), and machine-translation quirks like Wolt rendering
"Brownie" as "Lutin" in French — all preserved 1:1.
What we extract from every Wolt restaurant
Other Wolt scrapers give you the obvious stuff: name, price, address. We extract everything Wolt exposes, including endpoints other scrapers don't know exist.
Restaurant card (always)
- Name, slug, internal venue ID
- Full address (multi-line), coordinates (lat/lon), Google Maps link
- Phone, slogan, tags ("Burger", "Mexican", "Steak"…)
- Delivery hours per day of week
- Delivery methods + estimates (homedelivery / takeaway / eatin)
- Minimum order amount, delivery fee
- Open/closed status with next open/close timestamp
- Country, city, primary language, currency
- Breadcrumbs (helps you map the restaurant into Wolt's taxonomy)
Menu items — the meat of the data
- Item name, description, category
- Price in correct currency formatting (we handle ISK/JPY/HUF/KZT properly)
- Discount fields:
old_price,has_discount,discount_pct - Photos (primary + all extras), with content-hashed local file names
- Popular badge, Age-restricted flag, delivery-only flag
- Available-times window (some items only sold 11:30–14:00)
- Allowed delivery methods per item
- Restrictions (alcohol-age limit, etc.)
- Out-of-stock
disabled_infowhen applicable
Options & combos — the hard part nobody else does
Wolt items can be combos: Burger + Side + Drink, each with its own choice tree.
We don't flatten these into ugly strings — we keep the full structure with
option_id, prerequisites (X choice unlocks Y options), prices per choice,
and nested prodinfo per variant (a "Beef" combo option has its own allergens
from the prodinfo endpoint, not just inherited from the parent).
prodinfo — allergens, nutrition, GTIN, origin
Most Wolt scrapers ignore this endpoint or don't even know it exists.
For every menu item with has_extra_info=true (typically all packaged
goods, alcohol, and many regular dishes), we fetch
prodinfo.wolt.com/{locale}/{venue_id}/{item_id} and parse:
- Allergens as a plain list ("gluten, milk, eggs, soya")
- Ingredients full list
- Nutrition table per 100g — kcal, protein, carbs, fat, salt, sugars
- GTIN (barcode) — invaluable for retail/inventory integrations
- Unit info — "330 ml", "500 g"
- Unit price — "€8.40/litre" calculated by Wolt
- Country of origin, producer, importer
- Storage instructions, warnings, more_info text
- Alcohol permille for beer/wine/spirits
And we do this in every language the restaurant offers, not just the URL locale. If Aroma Tbilisi has menu in ka + en + ru + de + tr, you get five complete allergen lists per item.
Multilingual menus — every translation, not just one
Wolt exposes a translation API at
consumer-assortment/v1/venues/slug/{slug}/assortment?language={lang}.
Generic scrapers fetch one language (usually the URL locale, like English).
We iterate through available_languages and fetch them all.
Each menu item gets a translations.{lang} object with the item's
name, description, and allergens in that language. Plus we mark which translations
are autotranslated: true (machine) vs false (human-authored)
so your downstream system can decide whether to trust them.
Real example: a Georgian café we verified — Aroma Coffee & Tea, Batumi — serves menu in 5 languages: Georgian (ka, primary), English (en), Russian (ru), German (de), Turkish (tr). All five fully available in our response. RTL languages (Hebrew, Arabic) handled correctly as-is — your frontend sets
direction: rtland it works.
Currency edge cases — ISK/JPY/KZT/HUF formatted right
Wolt stores prices in minor units (cents). For EUR, USD, GBP — that's 100 cents per major unit. But for ISK (Iceland), öre haven't existed since the 90s. For JPY (Japan) and KRW (Korea), there's no sub-unit at all. Wolt still returns these as "minor units" but the minor unit happens to be the whole krona/yen.
Generic scrapers blindly divide by 100, so an Icelandic burger that costs 3490 ISK (kr3,490 ≈ €25) becomes "34.90 ISK" in their output — a 100× error. We auto-detect zero-decimal ISO 4217 currencies and de-facto integer currencies (KZT, HUF, AMD, ALL, MKD, MNT, UZS) and render the correct value.
Try it: search "Iceland Wolt scraper" on any marketplace, look at their output. Most are off by 100×. We aren't.
How we compare to other Wolt scrapers
We've looked at every Wolt scraper publicly listed on Apify and elsewhere. Here's an honest comparison:
| Feature | restoapi.org | Apify Wolt actors | DIY scripting | Generic scraping API |
|---|---|---|---|---|
| Restaurant name + address + hours | ✓ | ✓ | ✓ | ✓ |
| Menu items + prices (any currency) | ✓ all 16 currencies | EUR/USD only | DIY needed | N/A |
| ISK/JPY/KZT correct (no 100× bug) | ✓ | Off by 100× | Easy bug | N/A |
| All translations (every language) | ✓ all 5 | URL locale only | Hard | N/A |
| Allergens (per item, from prodinfo) | ✓ | No | Hidden endpoint | No |
| Nutrition + GTIN + unit price | ✓ | No | No | No |
| Combo items with nested variants | ✓ full tree | Flattened or skipped | No | N/A |
| Photos archived locally in ZIP | ✓ de-duplicated | URLs only | URLs only | URLs only |
| RTL languages (Hebrew, Arabic) | ✓ preserved | Untested | DIY | DIY |
| Discount fields (old_price, discount_pct) | ✓ | Often missing | DIY | N/A |
| Auto-refund on failure | ✓ | Pay anyway | N/A | N/A |
| Batch (200 URLs per request) | ✓ | ✓ | ✓ DIY | Per-request |
| Async job model (no holding connection) | ✓ poll-based | Sync, holds run | DIY | Sync |
| Full billing receipt in response | ✓ txn-ID + balance | Just charged | N/A | No |
| Per-restaurant price | $0.15 full media | $0.005–$0.05 | Free (your time) | $0.005–$0.015 / req |
Why we cost more than $0.005
Cheap Wolt actors hit Wolt's public endpoints with no extras. We do everything a "premium" scraper does — multilingual fetch, prodinfo per item, media archival, content de-duplication, currency-aware formatting, zero-decimal handling — all in one call. The work behind one $0.15 request is what a DIY engineer would spend a day building correctly.
If you need only the basics — restaurant name + price — use one of the cheap actors and save money. If you need the complete picture (allergens, translations, nutrition, photos, edge cases), the math works out in your favour at $0.15.
What people build with Wolt data
Our users use Wolt extracts for:
- Price tracking — daily snapshots of competitor restaurants in their city. A burger that costs €8.90 today, €9.50 next week, €8.50 on Sunday. The pattern tells you when to do promotions.
-
Allergen-friendly bots — a Telegram bot that filters Wolt restaurants
by "no gluten" or "vegan-friendly". With our normalised
allergens_normalizedfield (translates "qumësht" / "Milch" / "leite" all to"milk") — instant filtering. - ML training data — labelled food photos with category, allergens, and nutrition tags. We've delivered datasets of 1000+ restaurants × 15+ photos each for image classification models.
- Multilingual menus in your CRM — tourism platforms showing the same restaurant in 5 languages depending on visitor's locale. All translations come from one API call.
- Franchise monitoring — chain owners tracking their 50 locations daily, detecting when an outlet has different prices than the rest, or photos that haven't been refreshed in 6 months.
-
Catalog SEO — public-facing "best Wolt restaurants in Vienna" sites with
full schema.org markup. Our
computed.flatgives 47 scalars per restaurant ready for Google rich snippets.
Data we extract — annotated examples
Below are real excerpts from a Wolt scrape we ran on Centrum Kitchen
& Bar, Akureyri, Iceland — a 15-item, 3-language (is/en/pl) restaurant.
Every field shown is what you get in your result.json.
1. Restaurant identification (always present)
{ "name": "Centrum Kitchen & Bar", "slug": "centrum-kitchen-bar", "venue_id": "6569f2e7f947f35fcbf27951", "country": "ISL", "city": "Akureyri", "currency": "ISK", "primary_language": "is", "available_languages": [ {"language": "en", "name": "English", "autotranslated": true}, {"language": "is", "name": "Icelandic", "autotranslated": false}, {"language": "pl", "name": "Polish", "autotranslated": true} ], "translated_languages": ["en", "pl"], "phone": "+3546666078", "address": ["Hafnarstræti 102", "600 Akureyri"], "maps_url": "https://maps.google.com/?q=65.6818,-18.0905", "slogan": "Framandi & fjölbreyttur matseðill fyrir hvern sem er!", "tags": ["Burger", "Meat & fish", "Steak", "Mexican", "Salad"], "is_open": true, "open_status": "Closing at 23:45", "min_order_eur": 2500.0, "share_url": "https://wolt.com/is/isl/akureyri/restaurant/..." }
2. Delivery details (per-day hours, multiple methods)
"delivery_methods": [ { "method": "homedelivery", "label": "Standard", "estimate_label": "25-35 min", "estimate_min": 25, "estimate_max": 35 }, { "method": "takeaway", "label": "Standard", "estimate_label": "10-15 min", "estimate_min": 10, "estimate_max": 15 } ], "delivery_hours": { "monday": "11:30–21:00", "tuesday": "11:30–21:00", "wednesday": "11:30–21:00", "thursday": "11:30–21:00", "friday": "11:30–21:00", "saturday": "11:30–22:00", "sunday": "12:00–22:00" }
3. Menu item — basic data straight from Wolt
{ "platform_id": "68a3df1f97e1...", "local_id": "wlt:cent:8f3a", // stable hash — our addition "name": "Kjúklinga takkó", "description": "Mexican chicken taco with avocado, chipotle...", "category": {"name": "Mexican", "local_id": "cat:mex01"}, "pricing": { "amount": 3450, "currency": "ISK", "currency_symbol": "kr", "formatted": "kr3450" // no .00 — ISK is zero-decimal }, "photo": { "url": "https://imageproxy.wolt.com/assets/68a3df.../w=4096", "local_url": "photos/menu_photos/3fb776fbc34f.jpg" }, "image_urls": ["...primary", "...alternate1"], "image_local_urls": ["photos/menu_photos/3fb776fbc34f.jpg", "..."], "popular": true, "age_restricted": false, "old_price": null, "discount_pct": null, "delivery_only": false, "available_times": [] }
4. Multilingual translations — same item in 3 languages
"translations": { "is": { "name": "Kjúklinga takkó", "description": "Mexikóskt taco með kjúklingi, avocado..." }, "en": { "name": "Chicken taco", "description": "Mexican chicken taco with avocado, chipotle..." }, "pl": { "name": "Taco z kurczakiem", "description": "Meksykańskie taco z kurczakiem, awokado..." } }
5. prodinfo result — allergens, nutrition, GTIN
For packaged-goods items (drinks, snacks, alcohol), Wolt exposes additional info
via prodinfo.wolt.com. Example for a Coca-Cola 0.33L can in a German
Wolt market shop:
{ "name": "Coca-Cola Dose 0,33l", "gtin": "5449000000996", "barcode_gtin": "5449000000996", "unit_info": "330 ml", "unit_price": { "price": 8.79, "unit": "litre", "base": "1 l" }, "allergens": ["glutenfrei", "laktosefrei"], "ingredients": "Wasser, Zucker, Kohlensäure, Farbstoff E150d...", "additives": "E150d, E338, E330, E950, E951", "nutrition": [ ["", "per 100 ml"], ["Energy", "180 kJ / 42 kcal"], ["Fat", "0 g"], ["of which sugars", "10.6 g"], ["Salt", "0.01 g"] ], "origin": "Belgien", "producer": "Coca-Cola European Partners Deutschland...", "importer": "Coca-Cola GmbH, Bornheim", "storage": "Kühl und lichtgeschützt lagern.", "warnings": [], "alcohol_permille": null }
6. Combo item with nested variants
A combo "Burger Menu" — pick a burger, a side, a drink. Each option group has its own values, each value has its own prodinfo (allergens differ between beef and chicken combos). Generic scrapers flatten this into a single string; we keep the tree:
"options_groups": [ { "option_id": "main-burger", "name": "Choose your burger", "min": 1, "max": 1, "values": [ { "id": "v-beef", "name": "Centrum Beef Burger", "price": 0, // base price "dietary_preferences": [] }, { "id": "v-chicken", "name": "Chicken Burger", "price": -200 // 2 ISK cheaper } ] }, { "option_id": "side", "name": "Side", "prerequisite_values": [], "values": [ {"name": "Fries", "price": 0}, {"name": "Truffle fries", "price": 800} ] } ]
What WE add on top — the computed.* namespace
Wolt gives raw data. We add derived, normalised, statistical fields
that make downstream code easier. Everything we calculate goes into a clearly-marked
computed.* namespace so you always know what came from Wolt vs from us.
7. Per-item flags (boolean quick filters)
"computed": { "flags": { "has_photo": true, "has_multi_photos": false, "has_description": true, "has_allergens": true, "has_real_allergens": true, // from prodinfo, not just bracket-parse "has_ingredients": false, "has_nutrition": false, "has_producer": false, "has_warnings": false, "has_gtin": false, "has_unit_info": false, "is_alcoholic": false, "is_packaged_good": false, "is_combo": false, "is_popular": true, "has_discount": false, "delivery_only": false, "age_restricted": false, "is_available_always": true, "has_translations": true }, ... }
8. Normalised & derived per-item data
"computed": { "derived": { "food_category": "taco", // our classifier "allergens_normalized": ["milk", "wheat"], // EN words, any input lang "searchable_text": "Kjúklinga takkó | Mexican chicken taco | Chicken taco | Taco z kurczakiem | popular", "alcohol_pct": null // permille/10 if alcoholic } }
allergens_normalized is our magic — it takes whatever language
the allergen string came in ("gluten, qumësht ose produkte të tij"
in Albanian, "glutenfrei, laktosefrei" in German) and maps
them all to English keywords: ["gluten", "milk"]. Your code can
filter by allergens without caring about language.
searchable_text is one big string concatenating name+description+translations
— ready for full-text search indexing (Postgres tsvector, Elasticsearch, SQLite FTS5).
9. Per-item stats & pricing helpers
"computed": { "stats": { "price": 3450, "currency": "ISK", "old_price": null, "discount_pct": null, "unit_price_formatted": "kr8/100g", // e.g. "kr8/100g" for groceries "photo_count": 1, "languages_count": 3 } }
10. Restaurant-level menu stats
"computed": { "menu_stats": { "items_total": 15, "items_popular": 5, "items_with_photo": 15, "items_with_desc": 10, "items_alcoholic": 0, "items_combo": 0, "items_packaged": 0, "items_with_discount": 0, "price_min": 500, "price_max": 3850, "price_avg": 2433.33, "price_median": 2400, "top_cuisines": ["other", "salad", "pasta"], "top_allergens": ["milk", "wheat"], "food_categories_distribution": { "taco": 2, "burger": 2, "salad": 3, "pasta": 2, "other": 6 } } }
11. The computed.flat — 47-scalar restaurant card for catalogs
This is the killer feature for anyone building catalogs, spreadsheets, SQL tables, CSV exports. One flat object per restaurant, no nesting, ready for direct insertion into any tabular format:
{ // Identity "name": "Centrum Kitchen & Bar", "slug": "centrum-kitchen-bar", "venue_id": "6569f2e7...", "country": "ISL", "city": "Akureyri", "currency": "ISK", // Languages "primary_language": "is", "languages": ["en", "is", "pl"], "languages_count": 3, // Status "is_open": true, "phone": "+3546666078", "has_logo": false, "brand_slug": null, "slogan": "Framandi & fjölbreyttur...", "tags": ["Burger", "Meat & fish", "Steak", "Mexican", "Salad"], // Menu counts "items_count": 15, "items_with_photo": 15, "items_with_desc": 10, "items_with_allergens": 0, "items_packaged": 0, "items_alcoholic": 0, "items_combo": 0, "items_popular": 5, "items_with_discount": 0, // Price stats "price_min": 500, "price_max": 3850, "price_avg": 2433.33, "price_median": 2400, // Distributions "top_cuisines": ["other", "salad", "pasta"], "top_allergens": [], // Delivery "min_order": 2500.0, "delivery_eta_mean": 30, "delivery_methods": ["homedelivery", "takeaway"], // Media "cover_url": "https://imageproxy.wolt.com/...", "cover_local_url": "photos/venue_photos/abc.jpg", "logo_url": null, "logo_local_url": null, "photos_count": 21, // Coordinates "lat": 65.6818, "lon": -18.0905, "address_line": "Hafnarstræti 102, 600 Akureyri", "maps_url": "https://maps.google.com/?q=65.6818,-18.0905" }
Want a CSV of 1000 restaurants? Run a batch, take computed.flat from
each, write to CSV. Done. Want a SQL restaurants table? Same fields,
direct mapping.
12. Searchable text — instant full-text indexing
"Kjúklinga takkó | Mexican chicken taco with avocado, chipotle, jalapeños | Mexican | Chicken taco | Mexican chicken taco with avocado | Taco z kurczakiem | Meksykańskie taco z kurczakiem, awokado | popular"
Every menu item gets a single searchable string with name + description +
translations + flags. Drop into Postgres' tsvector, Meilisearch,
Elasticsearch — works out of the box. No tokenisation logic needed on your side.
13. Stable IDs that survive re-scrapes
Wolt's platform_id changes if they restructure their catalog.
We add a local_id calculated as sha1(platform | slug | normalized_name)[:12].
This is stable: the same item gets the same local_id across runs, even if Wolt
rotates its internal IDs. Perfect for diff/change detection.
Code example: scrape a Wolt restaurant in 10 lines
import requests, time KEY = "rk_live_xxx" H = {"Authorization": f"Bearer {KEY}"} job = requests.post("https://restoapi.org/v1/jobs", headers=H, json={ "source_url": "https://wolt.com/en/aut/wien/restaurant/foo", "platform": "wolt", "export_type": "full_media", }).json() print(f"job: {job['job_id']}, charged {job['billing']['charged_cents']}c") while True: time.sleep(10) s = requests.get(f"https://restoapi.org/v1/jobs/{job['job_id']}/status", headers=H).json() if s["status"] == "completed": url = s["downloads"]["full_export_zip"]["url"] open("wolt.zip", "wb").write(requests.get(url).content) break
That's literally it. One POST, one polling loop, one ZIP. Inside
the ZIP you get result.json (full canonical data),
restaurant.json, menu.json, computed.json,
and photos/ with all images organised by type.
Ready to try?
Sign up with email (OTP, no password), get $0.50 free credit — enough for 3+ Basic tasks. Run your first Wolt scrape in under 2 minutes.