# Uber Eats Restaurant Menu & Price Extractor (`dataspryva/uber-eats-restaurant-menu-and-price-extractor`) Actor

Pull full Uber Eats restaurant menus by store URL: rating, cuisines, delivery fee and ETA, plus every menu section and item with price, description and image.

- **URL**: https://apify.com/dataspryva/uber-eats-restaurant-menu-and-price-extractor.md
- **Developed by:** [Dataspryva](https://apify.com/dataspryva) (community)
- **Categories:** E-commerce, Automation, Lead generation
- **Features:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.49 / 1,000 results

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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 Restaurant Menu & Price Extractor

Turn Uber Eats into a structured dataset. Search restaurants by keyword, then read their menus item by item, or feed in restaurant links and pull every section and price. Everything runs without cookies, logins, or API keys.

### Three ways to scrape

| Mode | Use it for | What you get |
|---|---|---|
| `search` | Discover restaurants for a keyword and delivery area | Restaurant name, URL, rating, review count, ETA, coordinates and rank |
| `menus` | Export the full menu of restaurants you already know | Restaurant profile plus every menu section the public response exposes, with item price, currency, photo and availability |
| `searchWithMenus` | Search, then export a menu for every match | Search fields, restaurant profile and complete menu in one record per restaurant |

### Location matters

Uber Eats only serves restaurants that deliver to a specific address, so **results depend on `location`**. Pass a city, postcode, street address, or `latitude,longitude`. The actor resolves it to a real delivery point, then uses that context for both search and menu pricing. If the address cannot be resolved, it falls back to the default city for the selected `country`.

### What is in each record

- `mode`, `query`, `location`, `rank` — how the record was found
- `restaurantId`, `restaurantName`, `restaurantUrl`, `heroImageUrl`
- `rating`, `ratingCount`, `priceRange`, `cuisines`, `isOpen`
- `address`, `city`, `postalCode`, `countryCode`, `latitude`, `longitude`
- `phoneNumber`, `currencyCode`, `storeType`, `deliveryMethods`, `workingHours`
- `deliveryFee`, `estimatedDeliveryTime`
- `menu` — ordered sections, each with `sectionName` and `items`
- `menuSectionCount`, `menuItemCount`, `itemsWithImageCount`, `itemsWithDescCount`
- `scrapedAt`

Each menu item contains:

- `itemId`, `name`, `description`
- `price` in major currency units (for example `12.50`), `currency`
- `imageUrl`, `isAvailable`, `hasCustomizations`

Empty values are omitted, never returned as `null`.

### Input examples

#### Search pizza places in Brooklyn

```json
{
  "mode": "search",
  "searchQueries": ["pizza"],
  "location": "Brooklyn, NY",
  "maxRestaurants": 20
}
```

#### Export full menus for two restaurants

```json
{
  "mode": "menus",
  "restaurantUrls": [
    "https://www.ubereats.com/store/cvs-129-fulton-streets/isOmPe5EU261CcRN3X7RMw",
    "https://www.ubereats.com/store/atlantis-cafe-1049-grand-street/p1lWs-ecV5ySgxZXi1PRcw"
  ],
  "location": "Brooklyn, NY",
  "maxMenuItemsPerRestaurant": 500
}
```

#### Search, then pull every menu

```json
{
  "mode": "searchWithMenus",
  "searchQueries": ["sushi", "ramen"],
  "location": "Toronto, ON",
  "country": "ca",
  "maxRestaurants": 10,
  "maxMenuItemsPerRestaurant": 150
}
```

### How pagination works

Search results are requested page by page until `maxRestaurants` unique stores are collected or Uber Eats runs out of matches. Menus follow the same rule: the actor reads Uber Eats' own section paging and keeps requesting until the source stops returning items or `maxMenuItemsPerRestaurant` is reached. Menu item caps are applied across the whole restaurant, not per section.

### Inputs

| Field | Type | Default | Notes |
|---|---|---|---|
| `mode` | select | — | `search`, `menus`, or `searchWithMenus` (prefilled with `search`) |
| `searchQueries` | array | — | Keywords for search modes (prefilled with `["pizza"]`) |
| `location` | string | `New York, NY` | Address, city, postcode, or `lat,lng` |
| `country` | select | `us` | Fallback market and default city |
| `maxRestaurants` | integer | `20` | 1–500 unique restaurants |
| `restaurantUrls` | array | — | URLs or store IDs for menu modes |
| `maxMenuItemsPerRestaurant` | integer | — | 1–2000 items per restaurant (prefilled with `10`) |

Existing tasks that send `restaurantUrls` and `maxItemsPerRestaurant` keep working. The older key is read in code and mapped to `maxMenuItemsPerRestaurant`; it does not need to stay in the form.

### Use cases

- **Price monitoring** — snapshot competitor menus and track dish prices over time.
- **Market research** — see which cuisines and restaurants serve a neighbourhood.
- **Catalog enrichment** — add descriptions, photos, and availability to your own listings.
- **Delivery benchmarking** — compare ratings, ETAs, and fees across an area.

### FAQ

**Does this need an Uber Eats account or cookies?**
No. The actor reads public restaurant and menu data and needs no login, cookie, or API key.

**Do I need to configure a proxy?**
No. It works directly, and the actor chooses its network path automatically.

**Why do two nearby addresses return different restaurants?**
Uber Eats filters by delivery radius. Change `location` to the exact area you care about.

**Why is a menu shorter than what I see in the app?**
Some stores hide items that are unavailable at the current time, lazy-load category sections, or do not expose them in the public menu response. The actor returns everything the public menu response exposes up to your item cap.

**Are prices always in the same currency?**
No. `currencyCode` and each item's `currency` tell you the local currency, which depends on the delivery market.

**Can I use restaurant IDs instead of full URLs?**
Yes. Paste either a full Uber Eats URL or a store UUID in `restaurantUrls`.

# Actor input Schema

## `mode` (type: `string`):

Search restaurants by keyword, scrape full menus from URLs/IDs, or search and pull the menu for every match.

## `searchQueries` (type: `array`):

Restaurant, cuisine, or dish keywords. Required for search and searchWithMenus modes. Each query is paginated automatically until maxRestaurants is reached.

## `location` (type: `string`):

Address, city, postcode, or 'latitude,longitude' used to resolve Uber Eats delivery results. Uber Eats gates restaurant availability by location, so results differ by area.

## `country` (type: `string`):

Fallback market when the delivery location cannot be resolved. Also sets the default city used for menu pricing context.

## `maxRestaurants` (type: `integer`):

Stop after this many unique restaurants across all search queries.

## `restaurantUrls` (type: `array`):

Uber Eats restaurant page URLs or store IDs (for example https://www.ubereats.com/store/name/AbCdEf123 or a full UUID). Used by menus and searchWithMenus modes.

## `maxMenuItemsPerRestaurant` (type: `integer`):

Cap on menu items returned for each restaurant. Pagination stops as soon as this cap is reached.

## Actor input object example

```json
{
  "mode": "search",
  "searchQueries": [
    "pizza"
  ],
  "location": "New York, NY",
  "country": "us",
  "maxRestaurants": 3,
  "restaurantUrls": [
    "https://www.ubereats.com/store/cvs-129-fulton-streets/isOmPe5EU261CcRN3X7RMw"
  ],
  "maxMenuItemsPerRestaurant": 10
}
```

# Actor output Schema

## `restaurants` (type: `string`):

Dataset of restaurant search results and menus

# 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 = {
    "mode": "search",
    "searchQueries": [
        "pizza"
    ],
    "location": "New York, NY",
    "maxRestaurants": 3,
    "restaurantUrls": [
        "https://www.ubereats.com/store/cvs-129-fulton-streets/isOmPe5EU261CcRN3X7RMw"
    ],
    "maxMenuItemsPerRestaurant": 10
};

// Run the Actor and wait for it to finish
const run = await client.actor("dataspryva/uber-eats-restaurant-menu-and-price-extractor").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 = {
    "mode": "search",
    "searchQueries": ["pizza"],
    "location": "New York, NY",
    "maxRestaurants": 3,
    "restaurantUrls": ["https://www.ubereats.com/store/cvs-129-fulton-streets/isOmPe5EU261CcRN3X7RMw"],
    "maxMenuItemsPerRestaurant": 10,
}

# Run the Actor and wait for it to finish
run = client.actor("dataspryva/uber-eats-restaurant-menu-and-price-extractor").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 '{
  "mode": "search",
  "searchQueries": [
    "pizza"
  ],
  "location": "New York, NY",
  "maxRestaurants": 3,
  "restaurantUrls": [
    "https://www.ubereats.com/store/cvs-129-fulton-streets/isOmPe5EU261CcRN3X7RMw"
  ],
  "maxMenuItemsPerRestaurant": 10
}' |
apify call dataspryva/uber-eats-restaurant-menu-and-price-extractor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,dataspryva/uber-eats-restaurant-menu-and-price-extractor"
        }
    }
}
```

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/2utsIhZID8OJ7SMVa/builds/XEx3Cu06lzA2bQ9Zv/openapi.json
