Tony Wang5 min readHow to Scrape Uber Eats Restaurant & Menu Data in 2026 (API & Python)
Scrape Uber Eats restaurant search, menus, and reviews in 2026 — DIY, no-code, or a structured API for credential-free public data — with the legal basics.
The fastest way to scrape Uber Eats restaurant and menu data in 2026 is to call a structured API that returns normalized JSON — restaurant search, the location browse feed, full store menus, and a reviews snapshot — instead of reverse-engineering Uber Eats' internal API yourself. This guide covers all three approaches, what each returns, where each breaks, and the legal basics.
Why scrape Uber Eats?
Uber Eats is one of the largest food-delivery marketplaces globally, which makes it useful for:
- Restaurant & menu intelligence — track menu items, prices, and availability across a market.
- Delivery-market research — cuisine coverage and restaurant density by area, alongside DoorDash for a full delivery-market view.
- Review & reputation monitoring — track a restaurant's rating and review sentiment over time.
- Competitive pricing — compare dish prices for the same cuisine across nearby stores.
Is it legal to scrape Uber Eats?
Option 1: DIY in Python (and why it breaks)
Uber Eats renders restaurant search and store pages from an internal API, so a DIY scraper is really reverse-engineering that flow:
import requests
# Uber Eats' consumer site calls an internal API, not a documented public endpoint
resp = requests.get("https://www.ubereats.com/feed?pl=...")
It demos and then breaks:
- No official public API. Uber Eats doesn't publish a developer API for third-party search, menu, or review access, so there's no documented endpoint or key — you're replicating the consumer app's private calls.
- UUID-addressed stores. Stores are identified by a UUID, not a human-readable id, so every workflow has to resolve it first via search or the feed before it can fetch a menu or reviews.
- Location-gated responses. The feed and search results are scoped to a delivery coordinate, so a scraper needs a real lat/lng per request rather than one cached response.
- Drifting internal schema. The private app-backend response shape changes without notice and breaks replicated queries.
Option 2: No-code tools
Marketplace "Uber Eats scraper" actors export CSV/JSON and suit one-off pulls, but they're awkward in a scheduled pipeline and inherit the same internal-API fragility.
Option 3: A structured Uber Eats API
For repeatable workflows, an Uber Eats scraping API returns normalized JSON as credential-free public data — no login, key, or cookie from Uber Eats required. Search restaurants near a location:
curl "https://api.crawlora.net/api/v1/ubereats/search?query=pizza&latitude=37.7749&longitude=-122.4194" \
-H "x-api-key: $CRAWLORA_API_KEY"
Then resolve a store UUID and pull its menu and reviews snapshot in Python:
import requests
h = {"x-api-key": "YOUR_API_KEY"}
base = "https://api.crawlora.net/api/v1/ubereats"
results = requests.get(f"{base}/search", headers=h,
params={"query": "pizza", "latitude": 37.7749, "longitude": -122.4194}).json()["data"]["restaurants"]
store_uuid = results[0]["storeUuid"]
store = requests.get(f"{base}/store/{store_uuid}", headers=h).json()["data"]
menu = requests.get(f"{base}/store/{store_uuid}/menu", headers=h).json()["data"]["sections"]
reviews = requests.get(f"{base}/store/{store_uuid}/reviews", headers=h).json()["data"]["reviews"]
A search response is normalized JSON you can store directly (real fields):
{
"code": 200,
"msg": "OK",
"data": {
"restaurants": [
{ "storeUuid": "259fe6e9-9e3a-429d-ae24-be5eda54ba64", "name": "Udupi Palace", "slug": "udupi-palace-mission", "rating": 4.5, "reviewCount": 2000, "deliveryEtaText": "20-30 min", "cuisineTags": ["Indian"], "currencyCode": "USD" }
]
}
}
Store detail returns the full profile — address, phone, hours tagline, and price bucket — and the menu preserves per-item pricing (real fields, dollars not cents):
{ "storeUuid": "259fe6e9-...", "storeTitle": "Udupi Palace", "sections": [{ "title": "Appetizers", "items": [{ "title": "Samosa", "description": "Crispy pastry with spiced potato filling", "price": 6.99, "isSoldOut": false }] }] }
Reviews come back as a snapshot — the aggregate rating plus a sample of recent written reviews, not a full paginated history:
{ "storeUuid": "259fe6e9-...", "rating": 4.5, "reviewCount": 2000, "reviews": [{ "eaterName": "Jamie L.", "text": "Great food, quick delivery.", "formattedDate": "01/01/26" }] }
Omit the query parameter on /ubereats/search (or use /ubereats/feed) to browse the general location feed instead of keyword search. Store one row per restaurant and re-pull on a schedule.
What you can collect
Public fields: restaurant search results and location feed (storeUuid, name, url, rating, review count, delivery ETA, cuisine tags, sponsored flag, currency); store profile (address, phone, rating, price bucket, hours tagline, open/orderable status); full menus (sections, items, descriptions, prices, sold-out status); and a reviews snapshot (aggregate rating, count, sample review text).
Limitations and common challenges
- No official API for arbitrary restaurant data. Third-party search, menu, and review access means scraping Uber Eats' internal app backend, which a structured API handles behind one key.
- Reviews are a snapshot, not a full feed. The reviews endpoint returns the same sample the store page shows, not every review ever left — for exhaustive review coverage, treat it as a recurring pull rather than a one-time export.
- Everything is location-scoped. Menus, pricing, and availability change by delivery coordinate — pass a real location per request.
- Reviews are personal data. Reviewer names and review text are personal under GDPR/CCPA — collect public, factual fields with a lawful basis.
Where this gets used
- Restaurant & menu intelligence — track pricing and assortment across a delivery market. See the ecommerce product intelligence use case.
- Review & reputation monitoring — track a restaurant's rating and sentiment over time. See the review & reputation monitoring use case.
- Delivery-market research — cuisine density and restaurant coverage by area, alongside DoorDash for the full delivery-market picture.
Sources
Start collecting
Try it first, free: run any public URL through the Free Web Scraper, or check whether a site blocks bots with the Anti-Bot Checker — no signup.
Test the search endpoint in the Playground, check the schema in the API docs, and review pricing. See also how to scrape DoorDash for the other side of the delivery market, how to scrape Yelp for local business ratings, mobile app APIs explained for how this data actually flows, and is web scraping legal.
Part of our how-to-scrape guide series — every platform we cover, in one index.
Frequently asked questions
Does Uber Eats have an official API?
No public developer API for third-party search, menu, or review access. Collecting Uber Eats' restaurant data means scraping its internal API, which a structured API handles behind one key, returning credential-free public data with no login required.
How do I address an Uber Eats store?
Stores are addressed by a UUID (storeUuid), not a numeric id — returned by /ubereats/search or /ubereats/feed. Resolve it first, then use it with the store, menu, and reviews endpoints.
How do I browse without a search term?
Omit the query parameter on /ubereats/search, or call /ubereats/feed directly, to browse the general restaurant feed for a location instead of keyword search.
What Uber Eats data can I collect?
Public fields: restaurant search results and the location feed (rating, review count, delivery ETA, cuisine tags, currency); store profile (address, phone, price bucket, hours, status); full menus (sections, items, prices, sold-out status); and a reviews snapshot (aggregate rating, count, sample review text).
Is the reviews endpoint a complete review history?
No. It returns the same on-page snapshot the store page shows — the aggregate rating plus a sample of recent reviews, not a fully paginated feed of every review ever left.
Are Uber Eats reviews personal data?
Yes. Reviewer (eater) names and review text are personal data under GDPR/CCPA — collect only public, factual fields with a lawful basis and don't republish reviewer identities.