Uber Eats Menu Scraper · Items, Prices & Categories
Pricing
from $3.00 / 1,000 menu item extracteds
Uber Eats Menu Scraper · Items, Prices & Categories
Export every Uber Eats menu item with section, price, and description — one row per dish for pricing benchmarks. Search by city, territory, or paste store URLs. No login or API key
Pricing
from $3.00 / 1,000 menu item extracteds
Rating
0.0
(0)
Developer
Corentin Robert
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
3 days ago
Last modified
Categories
Share
Uber Eats Menu Scraper
Built for pricing teams, F&B brands, dark kitchens, and market researchers — export every Uber Eats dish with section, price, and description in one flat spreadsheet.
No login. No API key. No Uber Eats account.
Item names, prices, menu sections, and store context ship on every row. Search by city, territory, or paste store URLs — same discovery as the Pro Scraper, but each dataset row is a menu item, not a CRM lead.
Who is this for?
| You are… | Typical goal | Suggested setup |
|---|---|---|
| Pricing / revenue ops | Benchmark competitor menu prices in a city | City or URLs |
| F&B brand / supplier | Map categories and price bands across a market | Territory + cuisine filter |
| Dark kitchen / franchise | Compare menus across locations of the same brand | URLs — bulk paste store links |
| Consultant / agency | Deliverable: full menu export for a client market | City + raise maxResults |
| Market research | Price distribution and category mix by geo | Territory with maxResults cap |
| Data / ops | Scheduled refresh on a known restaurant list | URLs mode |
By default you get itemName, section, price, currency, storeName, and city — one row per dish (outputMode: flat). Descriptions and store ratings are included when Uber Eats publishes them on the store page.
Use deduplicateItems: true (default) when the same burger appears in “Featured” and “Burgers”. Turn it off only if you need every section occurrence for audit trails. Use outputMode: nested when you want one JSON object per restaurant with an items[] array (API workflows).
What you get out of it
| Benefit | Why it matters |
|---|---|
| Spreadsheet-ready pricing | Flat export — filter by sectionTop, pivot on itemName, compare price across storeName |
| Same discovery as Pro | City, territory, and URL modes — no second tool to list restaurants |
| Honest menu depth | Full item list from public store pages — not just min/max price bands |
| Geo context on every row | city, country, storeId — join runs or dedupe across exports |
| Transparent runs | Logs show progress %, ETA, and a downloadable RUN_LOG |
How much does it cost to scrape Uber Eats menus?
Pricing is pay-per-event (plus light HTTP compute — no proxy required for menus):
| Event | Price | When charged |
|---|---|---|
apify-actor-start | $0 | Every run (no run fee) |
uber-eats-menu-item | $0.003 | Each menu row (flat mode) |
uber-eats-store-with-menu | $0.03 | One row per store (nested mode) |
uber-eats-store-no-menu | $0.005 | Store page returned no usable menu |
apify-default-dataset-item | $0 | Guard — avoids double-charging |
| Scenario | Listed PPE (items only) | Typical total |
|---|---|---|
| Try: 3 stores, ~300 items | ~$0.90 | ~$0.95–1.05 with compute |
| 15 stores, ~1 400 items (City Annecy) | ~$4.20 | ~$4.50–5.50 |
| 1 000 menu items | ~$3.00 | ~$3.50–4.50 |
| 10 000 menu items | ~$30.00 | ~$32–40 |
HTTP-only runs keep compute low. There is no residential proxy on this Actor — menus are read from public store HTML.
Console setup (Monetization): set apify-actor-start and apify-default-dataset-item to $0; add uber-eats-menu-item ($0.003), uber-eats-store-with-menu ($0.03), uber-eats-store-no-menu ($0.005).
Is scraping Uber Eats free?
Apify charges for Actor runs (PPE + compute). A 3-store Try (~300 menu rows) is usually about $1 all-in (items + light compute). There is no separate Uber Eats API fee — this Actor uses public store pages only.
Is it legal to scrape Uber Eats?
This Actor only reads public restaurant and menu pages that Uber Eats shows to consumers. You are responsible for using the data in line with GDPR, local marketing laws, and Uber Eats' terms. Do not use scraped data for unlawful competitive practices or misrepresentation.
Quick start
- Open Input → leave Search mode on City (default)
- Enter a city name (e.g.
Annecy) — country is inferred automatically - Max restaurants defaults to 15; clear Cuisine filter to include all restaurants in the city
- Leave Include descriptions on; keep Deduplicate items on for cleaner spreadsheets
- Click Run → open Dataset → export CSV, JSON, or Excel
For a single competitor, switch to URLs mode and paste one store link.
Search modes
City — One or more cities (default)
Best for local price benchmarks. Items from each restaurant appear as that store is scraped.
{"mode": "city","cityNames": ["Annecy", "Paris"],"maxResults": 15,"categories": [],"includeDescriptions": true,"deduplicateItems": true,"outputMode": "flat"}
Prefix a country to disambiguate: fr:Annecy, us:New York.
Territory — Country or region
Best for large market slices. Set a Max restaurants cap unless you need a full-country sweep.
{"mode": "territory","country": "fr","region": "fr:ara","categories": ["burger"],"maxResults": 500,"outputMode": "flat"}
Set maxResults: 0 for no restaurant ceiling (use a long Run timeout in Run options).
URLs — Specific restaurants
Best for head-to-head competitor menus.
{"mode": "urls","startUrls": [{ "url": "https://www.ubereats.com/fr/store/mcdonalds-epagny/b4043WTlR_iSrNu0-Y2DYQ" },{ "url": "https://www.ubereats.com/fr/store/burger-king-epagny/ZOjYdsqgQcqPQ5q40GJoXQ" }],"includeDescriptions": true,"outputMode": "flat"}
Input parameters
| Field | Default | Description |
|---|---|---|
mode | city | city, territory, or urls |
cityNames | ["Annecy"] | Cities for City mode |
country / region | — | Territory mode |
startUrls | — | Store URLs for URL mode |
maxResults | 15 | Max restaurants per city or territory (0 = no cap) |
categories | ["fast-food"] | Cuisine filter; empty array = all cuisines |
includeDescriptions | true | Item description text |
deduplicateItems | true | Merge duplicate items across sections |
outputMode | flat | flat = one row per item; nested = one row per store |
sectionFilter | — | API-only: regex or string list to keep matching sections |
Output fields (flat mode)
| Group | Fields |
|---|---|
| Store | storeName, storeUrl, storeId, storeSlug, city, country |
| Menu | section, sectionTop, itemName, description, price, currency |
| Context | rating, reviewCount, itemIndex, scrapedAt |
| Errors | error (only on failed stores in edge cases) |
CSV uses semicolon separators when exported locally for Excel-friendly import.
Typical coverage (reference runs)
Based on HTTP smoke runs on French store pages:
| Field | Coverage |
|---|---|
itemName | ~100% of extracted items |
price / currency | ~100% |
description | ~95% (chains sometimes omit on promos) |
section / sectionTop | ~100% |
| Item images | Not exported in v1 (planned v1.1) |
| Modifiers / sizes / add-ons | Not in public JSON-LD — not exported |
maxResults limits restaurants, not menu rows. One McDonald's location can yield 150–200+ items.
Pricing & research workflows
| Goal | Filter / columns | Suggested input |
|---|---|---|
| City price map | Group by storeName, compare price on itemName | City mode, categories: [] |
| Category benchmark | Filter sectionTop = Burgers or Menus | City or URLs |
| Chain vs indie | Compare storeName across URLs | URLs mode, 5–10 stores |
| Deduped master menu | deduplicateItems: true | Default |
| Refresh cadence | Key on storeId + itemName + price | URLs list from Pro Scraper export |
Spreadsheet tip: pivot on sectionTop and storeName; use price as values. Filter currency when mixing US and EU stores.
How it works
- Discover restaurants (city / territory listing, or your URLs)
- Fetch each public store page (HTTP, browser-like headers)
- Parse menu from structured page data (
hasMenu→ sections → items) - Normalize rows — optional dedupe and section filter
- Export to Dataset (and local CSV on
apify run)
Output example
One menu item from a City · Annecy · 3 restaurants run:
{"storeUrl": "https://www.ubereats.com/fr/store/mcdonalds-epagny/b4043WTlR_iSrNu0-Y2DYQ","storeId": "b4043WTlR_iSrNu0-Y2DYQ","storeSlug": "mcdonalds-epagny","storeName": "McDonald's® (Epagny)","city": "EPAGNY","country": "FR","section": "NOUVEAUTÉS","sectionTop": "NOUVEAUTÉS","itemName": "BEEF MOZZA CHEDDAR","description": "Pain spécial, fromage fondu, steak haché, préparation panée à base de mozzarella et de cheddar, tomate, salade, oignons, sauce.","price": 14.7,"currency": "EUR","rating": 3.9,"reviewCount": 4000,"itemIndex": 12,"scrapedAt": "2026-06-08T08:00:00.000Z"}
Limitations
- Modifiers, sizes, and add-ons are not exposed in public menu JSON — not exported in v1.
- Item images are only partially present in page HTML — full image pass planned for v1.1.
- Large territory runs without
maxResultscan take hours and produce hundreds of thousands of menu rows — set caps and timeout accordingly. - Uber Eats may show promotional sections (e.g. “buy one get one”) — items can appear in multiple sections unless dedupe is on.
Also available
- Uber Eats Pro Scraper — CRM-ready restaurant leads: phones, emails, company IDs, SIRET, territory search. Use Pro to list restaurants, then paste
urlvalues into this Actor's URLs mode for full menus. - Uber Eats Reviews Scraper — monitor store ratings and latest public customer comments for the same store URLs (reputation snapshot, not full review history).
Local development
npm installnpm run build:schemanpm run buildnpm testmkdir -p storage/key_value_stores/defaultcp input.json storage/key_value_stores/default/INPUT.jsonapify run
apify run validates storage/key_value_stores/default/INPUT.json against the input schema — include every field you need, or use apify run --input-file=./input.json.
Local runs write output.csv (UTF-8 BOM, semicolon-separated) next to the project root.
Support
Contact corentin@outreacher.fr for custom Uber Eats pipelines, menu monitoring, or hub Actor integrations.