# Uber Eats Scraper — Restaurants, Menus, Prices & Grocery (`yugenox/ubereats-scraper`) Actor

Scrape Uber Eats restaurants and stores by address, postal code, city or store link: full menus with prices, hours, phone, address, coordinates, ratings, reviews, delivery fees and promotions — plus grocery, pharmacy and convenience aisle prices with deals. Canada, US, UK and more.

- **URL**: https://apify.com/yugenox/ubereats-scraper.md
- **Developed by:** [Yugenox Corp](https://apify.com/yugenox) (community)
- **Categories:** E-commerce, Lead generation, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $5.00 / 1,000 store (menu, hours & reviews included)s

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Uber Eats Scraper — Restaurants, Menus, Prices & Grocery

Scrape **Uber Eats** restaurants and stores for any address, postal code, neighbourhood or city — or straight from store links — and get **complete menus with prices**, opening hours, phone numbers, full addresses with coordinates, ratings, customer reviews, delivery fees, ETAs and promotions.

It goes beyond restaurants: turn on the **aisle crawl** to collect the full product catalogue and shelf prices of **grocery, pharmacy, convenience, alcohol and retail stores** on Uber Eats (Walmart, Shoppers Drug Mart, T\&T, 7-Eleven, Rexall, Dollarama, local grocers…).

Works in **Canada, the United States, the United Kingdom** and other Uber Eats markets, with prices in local currency. No Uber Eats account needed.

### What you get

| For every store | For every menu item / product |
|---|---|
| Name, store link, chain | Name, description, photo |
| Store type (restaurant, grocery, pharmacy, convenience, alcohol, retail…) | Price (number + formatted), currency |
| Rating, exact rating, number of ratings | Regular price when on sale + deal tags ("52% off", "2 for $7", "BOGO") |
| Cuisines, price range ($–$$$$) | Category / aisle, pack size (groceries) |
| Phone number | Calories |
| Street, city, region, postal code, country, neighbourhood | Sold-out / available flags |
| Latitude / longitude | Has options (sizes, add-ons) |
| Opening hours (per menu, e.g. breakfast / dinner) | Optional: every option group with extra prices, nutrition |
| Open now, ETA, distance, delivery fee text | |
| Promotions ("Buy 1, get 1"…), badges ("Great value", new, exclusive) | |
| Menu categories with item counts | |
| Recent reviews: text, date, reviewer first name + initial | |

### How to use

**All stores near an address or postal code** — the simplest run:

```json
{ "locations": ["M5V 3L9"], "maxStoresPerSearch": 100 }
```

**Keyword search** in several cities:

```json
{ "locations": ["Toronto, ON", "Vancouver, BC", "Brooklyn, NY"], "searchTerms": ["sushi", "ramen"], "maxStoresPerSearch": 80 }
```

**Every store in a city** — a single address shows at most ~500 stores, so city-wide coverage searches a grid of points (about 3 km apart) and merges the results without duplicates:

```json
{ "locations": ["Toronto City Hall"], "coverage": "cityWide", "radiusKm": 10, "maxStoresPerSearch": 0 }
```

**Specific stores** by link:

```json
{ "storeUrls": ["https://www.ubereats.com/ca/store/papa-johns-pizza-200-dundas-st-e/AWUBSjLNT6yLE-wVBC63qA"] }
```

**Grocery / pharmacy shelf prices** as a flat price list:

```json
{
  "locations": ["M5V 3L9"],
  "storeTypes": ["grocery", "pharmacy", "convenience"],
  "includeGroceryAisles": true,
  "maxItemsPerStore": 2000,
  "outputFormat": "menuItems"
}
```

#### Input options

- **Locations** — address, postal/ZIP code, neighbourhood, city, landmark or `"lat,lng"`. Use **Country hint** for ambiguous inputs (bare 5-digit codes are treated as US ZIP codes; Canadian and UK postcodes are recognised automatically).
- **Search terms** — optional keywords; empty = every store delivering to the location.
- **Store links** — scrape specific stores directly. Uber Eats city pages (e.g. `ubereats.com/ca/city/toronto-on`) are accepted too and searched as a location.
- **Coverage** — `nearby` (one point) or `cityWide` (grid within `radiusKm`).
- **Store types** — keep only restaurants, grocery, pharmacy, convenience, alcohol, retail, specialty food, pet supply or florists.
- **Dining mode** — delivery or pickup.
- **Include menu / reviews / item options**, **Crawl grocery aisles** with a per-store product cap.
- **Output format** — one row per store (menu nested inside) or one row per menu item (store name, address and coordinates on every row — ready for spreadsheets).
- **Max results**, **Max concurrency**, **Proxy** (datacenter by default; switches to residential automatically if needed).

### Output example (one row per store, shortened)

```json
{
  "dataType": "store",
  "storeUuid": "3c718ac9-75de-4477-9a4e-188d98a0823d",
  "name": "McDonald's (Queen & Spadina)",
  "url": "https://www.ubereats.com/ca/store/mcdonalds-queen-%26-spadina/PHGKyXXeRHeaThiNmKCCPQ",
  "storeType": "restaurant",
  "chain": { "uuid": "d8fb9d71-d641-43e1-901c-5f36a182c2d9", "name": "McDonald's" },
  "cuisines": ["Burgers", "Fast Food", "Chicken", "Canadian"],
  "priceRange": "$",
  "rating": 4.5,
  "ratingExact": 4.4852,
  "reviewCount": 20000,
  "reviewCountText": "20,000+",
  "isOpen": true,
  "hoursText": "Open until 3:49 a.m.",
  "hours": [{ "days": "Every Day", "periods": [
    { "open": "04:00", "close": "10:49", "label": "Breakfast Menu" },
    { "open": "11:00", "close": "23:49", "label": "Lunch & Dinner Menu" }
  ] }],
  "phone": "+14167037401",
  "address": { "street": "160 Spadina Ave", "city": "Toronto", "region": "ON", "postalCode": "M5T", "country": "CA", "full": "160 Spadina Ave, Toronto, ON M5T" },
  "neighborhood": "Fashion District",
  "latitude": 43.6487706,
  "longitude": -79.3966784,
  "currency": "CAD",
  "etaText": "12–24 Min",
  "etaMinMinutes": 12,
  "etaMaxMinutes": 24,
  "distanceText": "1 km",
  "deliveryFeeText": "$0 delivery fee (new users)",
  "promotions": [],
  "menuItemCount": 169,
  "menuCategories": [{ "name": "Featured items", "itemCount": 9 }, { "name": "Most Popular", "itemCount": 9 }],
  "menu": [
    {
      "itemUuid": "27f17e03-8e76-5a0f-bec2-7f1add570cbd",
      "name": "Big Mac [560.0 Cals]",
      "description": null,
      "price": 11.19,
      "priceCents": 1119,
      "priceText": "$11.19",
      "calories": "560",
      "imageUrl": "https://tb-static.uber.com/prod/image-proc/processed_images/47a2af73e7fc83efe6c3b394bfea438d/a19bb09692310dfd41e49a96c424b3a6.jpeg",
      "isSoldOut": false,
      "hasOptions": true,
      "category": "Individual Items",
      "categories": ["Featured items", "Individual Items"]
    }
  ],
  "reviews": [
    { "text": "Hamburgers typically have 2 buns (1 on the top and one on the bottom). Would be great to have both next time!", "author": "Daniel K.", "date": "2026-08-16", "timeAgo": "1 month ago", "isFeatured": true }
  ],
  "searchLocation": { "query": "M5V 3L9", "latitude": 43.6425558, "longitude": -79.3871029 },
  "scrapedAt": "2026-09-24T05:36:05.078Z"
}
```

With **one row per menu item**, each row is an item (`name`, `price`, `originalPrice`, `dealTags`, `currency`, `category`, `aisle`, `size`, `calories`, `description`, `isSoldOut`, `imageUrl`) plus `storeName`, `storeUrl`, `storeType`, `storeAddress`, `storeCity`, `storeLatitude`, `storeLongitude` and `storeRating`.

### Use cases

- **Menu & price monitoring** — track competitors' menu prices, new items and promotions by city or chain.
- **Grocery & CPG price intelligence** — shelf prices and pack sizes of the same product across stores and banners; see which stores carry a product.
- **Lead generation** — restaurants and local shops with phone number, full address, cuisine, rating and popularity.
- **Market research** — restaurant density, cuisine mix, price ranges and ratings by neighbourhood; delivery coverage maps from coordinates.
- **Review analysis** — recent customer reviews for sentiment and quality tracking.
- **Menu data for apps** — nutrition, calories, options and photos.

### Tips

- One location returns up to **~500 stores** (the most Uber Eats lists for a single address). For more, use **city-wide** coverage.
- ETA, distance and delivery fee are relative to the location you search from. Store-link runs without a location leave them empty.
- Grocery and retail storefronts only show a first page of products; enable **Crawl grocery aisles** for the full catalogue.
- Reviews: Uber Eats shows up to ~180 recent reviews per store; reviewer names are first name + initial as shown on the site.

### FAQ

**Do I need an Uber Eats account or API key?** No.

**Which countries work?** Canada, the US and the UK are tested; other Uber Eats markets (e.g. Australia, Mexico, Japan) work the same way with local currency.

**How fresh is the data?** Everything is fetched live when you run the scraper.

**Why is a field sometimes empty?** Not every store publishes everything (e.g. some have no phone number or price range). Fees and ETAs depend on the location and time of day.

**Do I need residential proxies?** No. Apify's datacenter proxies, which every plan includes, work most of the time. When Uber Eats starts blocking datacenter IPs, the actor switches to residential proxies by itself, if your plan has them. If it doesn't, the run keeps going on datacenter IPs, and when many requests were blocked the status message starts its hint with **\[NO\_RESIDENTIAL]**: results may be partial, and enabling residential proxies in Apify Console → Proxy fixes it.

**How fast is it?** About 5 stores per second with full menus and reviews at default concurrency — e.g. 360 stores across Toronto, Vancouver and New York in about 75 seconds.

**How much does it cost?** Pay only for results — see the **Pricing** tab. You pay per store saved (its menu, hours and reviews are included); flat menu-item rows, extra grocery products from the aisle crawl and item options are optional add-ons. Stores that fail to load are never charged, and a run that finds nothing costs nothing.

**Is it legal to scrape Uber Eats?** This scraper collects only publicly available data — the same store listings, menus, prices, hours and reviews that anyone can see on ubereats.com without logging in. Reviews show the reviewer's first name and last initial, which can count as personal data in some places, so if you store or use it, have a legitimate reason and follow data protection laws such as GDPR, PIPEDA and CCPA, as well as Uber Eats' terms. If you're unsure about your use case, check with a lawyer. More background: [Is web scraping legal?](https://blog.apify.com/is-web-scraping-legal/)

**Does it access any private data?** No. It never logs in and uses no Uber Eats account, cookies or personal session. It only reads what the public Uber Eats website shows every visitor for an address or store link: stores, menus, prices, hours, business phone numbers and public reviews (first name + initial, as displayed). No orders, customer accounts, email addresses or payment details are ever accessed. Turn off **Include reviews** if you don't need reviewer names at all.

Location lookup uses OpenStreetMap data © OpenStreetMap contributors.

# Actor input Schema

## `locations` (type: `array`):

Where to look for stores: a street address, postal/ZIP code, neighbourhood, city or "latitude,longitude". Each location is searched separately. Examples: "M5V 3L9", "100 Queen St W, Toronto", "Shoreditch, London", "10001", "49.2856,-123.1115".

## `searchTerms` (type: `array`):

Keywords to search for near each location, e.g. "sushi", "pizza", "pharmacy", "Shoppers Drug Mart". Leave empty to get every store that delivers to the location.

## `storeUrls` (type: `array`):

Uber Eats store pages to scrape directly, e.g. https://www.ubereats.com/ca/store/papa-johns-pizza-200-dundas-st-e/AWUBSjLNT6yLE-wVBC63qA. City pages (…/city/toronto-on) are searched as a location.

## `maxStoresPerSearch` (type: `integer`):

How many stores to collect for each location (and each search term). One point returns up to ~500 stores; use city-wide coverage for more. 0 = as many as available.

## `coverage` (type: `string`):

"Nearby" searches the one point you give (up to ~500 stores — the most Uber Eats shows for a single address). "City-wide" searches a grid of points around it and merges the results without duplicates, for thousands of stores in a large city.

## `radiusKm` (type: `integer`):

Only for city-wide coverage: how far from the location to search. Points are ~3 km apart (a 10 km radius ≈ 40 points).

## `storeTypes` (type: `array`):

Keep only these kinds of stores. Leave empty for all.

## `countryCode` (type: `string`):

Two-letter country code (CA, US, GB/UK, AU…) to help place ambiguous locations. Five-digit codes are treated as US ZIP codes unless you set this; Canadian and UK postcodes are recognised automatically.

## `diningMode` (type: `string`):

Delivery or pickup — affects ETAs, fees and availability.

## `includeMenu` (type: `boolean`):

Every menu item with price, description, calories, photo, category and sold-out flag.

## `includeReviews` (type: `boolean`):

Recent customer reviews (text, date, reviewer first name and initial).

## `maxReviewsPerStore` (type: `integer`):

Uber Eats shows up to ~180 recent reviews per store.

## `includeGroceryAisles` (type: `boolean`):

For grocery, pharmacy, convenience, alcohol and retail stores: go through every aisle to collect the full product catalogue with shelf prices and pack sizes (otherwise you get the storefront's first page only). Aisles are sampled evenly up to the per-store limit.

## `maxItemsPerStore` (type: `integer`):

Cap for the aisle crawl (up to 5,000 per store in store output, 20,000 in menu-item output).

## `includeItemOptions` (type: `boolean`):

For each menu item: its option groups (sizes, add-ons, choices) with extra prices, and nutrition. One extra request per item — slower.

## `maxItemOptionsPerStore` (type: `integer`):

How many menu items per store get their options and nutrition (one extra request each).

## `outputFormat` (type: `string`):

"One row per store" nests the menu inside each store. "One row per menu item" gives a flat price list with the store's name, address and location on every row.

## `maxItems` (type: `integer`):

Stop after this many rows in total (stores or menu items, depending on the output format). 0 = no limit.

## `maxConcurrency` (type: `integer`):

Parallel requests.

## `proxyConfiguration` (type: `object`):

Apify datacenter proxies work for most runs and are the cheapest; the scraper switches to residential proxies automatically if it starts getting blocked.

## `debug` (type: `boolean`):

Log every request (for troubleshooting).

## `_noUnblocker` (type: `boolean`):

Internal (canaries): behave exactly like an account without the UNBLOCKER proxy group.

## `_noResidential` (type: `boolean`):

Internal (canaries): behave exactly like an account without the RESIDENTIAL proxy group.

## Actor input object example

```json
{
  "locations": [
    "M5V 3L9"
  ],
  "maxStoresPerSearch": 10,
  "coverage": "nearby",
  "radiusKm": 8,
  "diningMode": "DELIVERY",
  "includeMenu": true,
  "includeReviews": true,
  "maxReviewsPerStore": 50,
  "includeGroceryAisles": false,
  "maxItemsPerStore": 500,
  "includeItemOptions": false,
  "maxItemOptionsPerStore": 25,
  "outputFormat": "stores",
  "maxItems": 0,
  "maxConcurrency": 20,
  "proxyConfiguration": {
    "useApifyProxy": true
  },
  "debug": false,
  "_noUnblocker": false,
  "_noResidential": false
}
```

# Actor output Schema

## `results` (type: `string`):

Every row this run saved, as JSON.

## `resultsCsv` (type: `string`):

The same rows as CSV, ready for a spreadsheet.

## `resultsTable` (type: `string`):

The same rows narrowed to the key columns (the "overview" view).

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "locations": [
        "M5V 3L9"
    ],
    "maxStoresPerSearch": 10,
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("yugenox/ubereats-scraper").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "locations": ["M5V 3L9"],
    "maxStoresPerSearch": 10,
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("yugenox/ubereats-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "locations": [
    "M5V 3L9"
  ],
  "maxStoresPerSearch": 10,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call yugenox/ubereats-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,yugenox/ubereats-scraper"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/RdS2nvC5Zq6cHWaQK/builds/l4CHUgP4ke65tQCHa/openapi.json
