# OpenTable Restaurant Scraper (`axlymxp/opentable-restaurant-scraper`) Actor

Scrape OpenTable restaurants by city, neighborhood or ZIP — including the phone numbers, websites and opening hours listing scrapers miss. Plus cuisines, price bands, GPS, full rating breakdowns, reviews and live reservation times as JSON. Pay only for the results you get.

- **URL**: https://apify.com/axlymxp/opentable-restaurant-scraper.md
- **Developed by:** [axly](https://apify.com/axlymxp) (community)
- **Categories:** Travel, Lead generation, E-commerce
- **Stats:** 2 total users, 1 monthly users, 50.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $3.00 / 1,000 dataset items

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?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## OpenTable Restaurant Scraper

Turn any city, neighborhood or ZIP code into a clean, structured list of
OpenTable restaurants — **with the phone numbers, websites and opening hours that
listing scrapers leave out.**

Give it a location, get back one row per restaurant: contact details, address and
GPS, cuisines, price band, the full rating breakdown, current promotions, and
optionally diner reviews and live reservation times. No browser and no login
required.

### Who it's for

| You are                                          | You get                                                                                                                                                             |
| ------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **A lead-gen or sales agency**                   | Phone number and website for every restaurant in a market — a lead list you can dial or import into a CRM the same day.                                             |
| **A hospitality or market analyst**              | Cuisine mix, price bands, sub-ratings (food/service/ambience/value/noise), review distributions and reservations booked in the last 24 hours, across a whole metro. |
| **A PropTech / location-intelligence developer** | A stable JSON schema with coordinates and OpenTable metro and neighborhood ids, ready to join against your own data.                                                |
| **A restaurant operator**                        | Your competitive set's ratings, prices, promotions and how much availability they still have tonight.                                                               |

### What you get — output fields

| Field                                                                             | Type                      | Description                                                     |
| --------------------------------------------------------------------------------- | ------------------------- | --------------------------------------------------------------- |
| `restaurantId`                                                                    | string                    | OpenTable restaurant id                                         |
| `name`                                                                            | string                    | Restaurant name                                                 |
| `url`                                                                             | string                    | OpenTable profile URL                                           |
| `description`                                                                     | string                    | Restaurant's own description                                    |
| `phone` / `phoneFormatted`                                                        | string                    | Phone number, raw and as displayed                              |
| `website`                                                                         | string                    | Restaurant's own website                                        |
| `address`, `crossStreet`, `city`, `state`, `postalCode`, `country`, `countryCode` | string                    | Full address                                                    |
| `latitude` / `longitude`                                                          | number                    | GPS coordinates                                                 |
| `neighborhood`, `neighborhoodId`, `metroId`                                       | string                    | OpenTable area ids                                              |
| `cuisines` / `primaryCuisine`                                                     | array / string            | Cuisine tags                                                    |
| `priceBand` / `priceBandId`                                                       | string                    | Price band, e.g. `$31 to $50`                                   |
| `diningStyle`, `dressCode`, `executiveChef`                                       | string                    | Venue profile                                                   |
| `hours`                                                                           | string                    | Opening hours                                                   |
| `parkingInfo`, `publicTransit`, `paymentOptions`, `accessibility`                 | string / array            | Practical details                                               |
| `rating`, `reviewCount`                                                           | number / integer          | Overall score and rating volume                                 |
| `ratingFood`, `ratingService`, `ratingAmbience`, `ratingValue`, `ratingNoise`     | number                    | Sub-ratings                                                     |
| `ratingDistribution`                                                              | object                    | Number of ratings per star value                                |
| `recommendPercent`                                                                | integer                   | Share of diners who recommend it                                |
| `reviewSummary`                                                                   | string                    | OpenTable's summary of recent reviews                           |
| `reservationsLastDay`                                                             | integer                   | Reservations booked in the last 24 hours — a live demand signal |
| `popularDishes`                                                                   | array                     | Most-reviewed dishes                                            |
| `offers`                                                                          | array                     | Current promotions and prix-fixe menus                          |
| `photoUrl`, `photosCount`                                                         | string / integer          | Profile photo and photo count                                   |
| `hasMenu`, `isTakeoutEnabled`                                                     | boolean                   | Feature flags                                                   |
| `maxPartySize`, `maxAdvanceDays`                                                  | integer                   | Booking limits                                                  |
| `availableTimes`, `availableSlotCount`, `isAvailable`                             | array / integer / boolean | Bookable reservation times                                      |
| `reviews`                                                                         | array                     | Diner reviews: text, sub-ratings, dined and posted dates        |
| `searchLocation`, `scrapedAt`                                                     | string                    | Provenance                                                      |

Contact fields (`phone`, `website`, `hours`, `dressCode`, `diningStyle`,
`executiveChef`, `parkingInfo`, `paymentOptions`, `accessibility`,
`popularDishes`, `offers`) come from the full profile — keep **Include full
profile** enabled to receive them.

### High-value use cases

1. **Build a restaurant lead list for a whole city.** Search a metro, keep full
   profiles on, export to CSV — every row has a phone number and website ready
   for outreach.
2. **Benchmark a competitive set.** Pull every Italian restaurant in the `$31 to
   $50` band in your neighborhood and compare ratings, sub-ratings and price.
3. **Track demand over time.** Schedule a daily run and log `reservationsLastDay`
   and `availableSlotCount` to see which venues are filling up.
4. **Mine review sentiment.** Set reviews per restaurant and feed the text plus
   sub-ratings into your own sentiment or topic model.
5. **Enrich a POI dataset.** Join on coordinates or postal code to add cuisine,
   price band and ratings to your own venue database.

### Input parameters

| Parameter                | Type    | Default        | Description                                                        |
| ------------------------ | ------- | -------------- | ------------------------------------------------------------------ |
| `location`               | string  | —              | City, neighborhood or ZIP, e.g. `Chicago`, `Soho, London`, `94110` |
| `searchTerm`             | string  | —              | Optional keyword, e.g. `sushi`                                     |
| `maxItems`               | integer | `50`           | Maximum restaurants to return                                      |
| `includeDetails`         | boolean | `true`         | Fetch full profiles — required for phone, website and hours        |
| `reviewsPerRestaurant`   | integer | `0`            | Reviews to attach per restaurant                                   |
| `reviewsSortBy`          | enum    | `newestReview` | `newestReview`, `highestRating`, `lowestRating`                    |
| `includeAvailability`    | boolean | `false`        | Attach bookable reservation times                                  |
| `fullDayAvailability`    | boolean | `false`        | Whole service day instead of times near the reservation time       |
| `reservationDate`        | string  | today          | `YYYY-MM-DD`                                                       |
| `reservationTime`        | string  | `19:00`        | 24-hour `HH:MM`                                                    |
| `partySize`              | integer | `2`            | Diners, used for the availability check                            |
| `cuisines`               | array   | —              | Cuisine names, e.g. `["Italian", "Steakhouse"]`                    |
| `priceBands`             | array   | —              | `2` ($30 and under), `3` ($31 to $50), `4` ($50 and over)          |
| `sort`                   | enum    | `best`         | `best`, `distance`, `rating`                                       |
| `latitude` / `longitude` | string  | —              | Exact search centre; skips location lookup                         |
| `proxyConfiguration`     | object  | Apify Proxy on | Leave enabled — see the FAQ                                        |

#### Example input

```json
{
    "location": "Chicago",
    "searchTerm": "italian",
    "maxItems": 100,
    "includeDetails": true,
    "priceBands": ["3", "4"],
    "sort": "rating",
    "reviewsPerRestaurant": 5
}
```

#### Example output

```json
{
    "restaurantId": "1161631",
    "name": "Rose Mary",
    "url": "https://www.opentable.com/restaurant/profile/1161631",
    "phone": "8722603921",
    "phoneFormatted": "(872) 260-3921",
    "website": "https://www.rosemarychicago.com/",
    "address": "932 W Fulton Market",
    "city": "Chicago",
    "state": "IL",
    "postalCode": "60607",
    "country": "United States",
    "latitude": 41.8865,
    "longitude": -87.6512,
    "neighborhood": "West Loop",
    "cuisines": ["Italian", "Croatian", "Mediterranean"],
    "primaryCuisine": "Italian",
    "priceBand": "$31 to $50",
    "diningStyle": "Casual Elegant",
    "dressCode": "Casual Dress",
    "hours": "Daily 5:00 pm–10:00 pm",
    "rating": 4.8,
    "reviewCount": 4131,
    "ratingFood": 4.8,
    "ratingService": 4.8,
    "ratingAmbience": 4.7,
    "reservationsLastDay": 61,
    "availableTimes": ["2026-09-12T18:45", "2026-09-12T19:00"],
    "isAvailable": true,
    "scrapedAt": "2026-09-02T12:00:00Z"
}
```

### Scheduling, webhooks and integrations

- **Schedule** a run daily or hourly from the Apify Console to build a time
  series of ratings, promotions and availability.
- **Webhooks** fire on `ACTOR.RUN.SUCCEEDED` so your system can pull the new
  dataset immediately.
- **Export** to JSON, CSV, Excel, XML or RSS, or push straight into Google
  Sheets, Zapier, Make, Airbyte, S3 or your own API via the Apify API.
- **Resume-safe:** progress is checkpointed after every row, so an interrupted
  run continues where it stopped instead of re-charging you for duplicates.

### Use it from an AI assistant (MCP)

This Actor can be called by Claude, ChatGPT or any MCP-compatible agent through
the [Apify MCP server](https://mcp.apify.com), so an assistant can answer
questions like *"find the ten highest-rated Italian restaurants in Chicago with
their phone numbers"* by running it directly. You can also call it from code:

```python
from apify_client import ApifyClient

client = ApifyClient("<YOUR_API_TOKEN>")
run = client.actor("axlymxp/opentable-restaurant-scraper").call(
    run_input={"location": "Chicago", "maxItems": 25, "includeDetails": True}
)
for row in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(row["name"], row["phoneFormatted"], row["website"])
```

### FAQ

**Do I get phone numbers for every restaurant?**
Almost always, as long as **Include full profile** is on. A small number of
venues do not publish a phone number or website on OpenTable; those fields come
back empty rather than guessed.

**How many restaurants can I get for one location?**
As many as OpenTable lists there — typically several hundred per metro. Set
`maxItems` to the number you want; the Actor paginates automatically.

**Does it work outside the US?**
Yes. Locations, currencies and price bands are returned as OpenTable serves them
locally (for example `£25 and under` for London).

**How fresh is the data?**
Every run is live. Ratings, promotions and availability reflect OpenTable at the
moment the run executes.

**Do I need a proxy?**
Yes, and it is on by default — nothing to configure. OpenTable silently drops
requests for the full restaurant profile coming from datacenter IP ranges, so
turning the proxy off means empty `phone`, `website` and `hours` fields.

**What happens if a single restaurant fails?**
It is logged and skipped — the run continues and still returns every other row.

**Is this legal?**
The Actor collects publicly available information only. You are responsible for
using the output in line with OpenTable's terms and applicable law, including
data-protection rules where personal data (such as reviewer names in review text)
is involved.

**Something looks wrong — how fast do you respond?**
Open an issue on the Actor's Issues tab. Bug reports are typically answered
within a day.

# Actor input Schema

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

City, neighborhood or ZIP code to search around — for example 'Chicago', 'Soho, London' or '94110'. Use a plain form; over-qualified strings like 'Chicago, Illinois, USA' resolve less reliably. Ignored when latitude and longitude are set.

## `searchTerm` (type: `string`):

Narrow the search to restaurants matching a keyword, e.g. 'sushi', 'steakhouse' or a restaurant name. Leave empty to return everything in the area.

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

Stop after this many restaurants. Each restaurant is one dataset row.

## `includeDetails` (type: `boolean`):

Fetch each restaurant's full profile. Required for phone number, website, opening hours, dress code, dining style, executive chef, parking, payment options and accessibility. Turning this off makes runs faster but drops those fields.

## `reviewsPerRestaurant` (type: `integer`):

Attach up to this many diner reviews to each row (text, sub-ratings, dined date). Set 0 to skip reviews.

## `reviewsSortBy` (type: `string`):

Order in which reviews are collected.

## `includeAvailability` (type: `boolean`):

Attach bookable timeslots for the reservation date, time and party size below.

## `fullDayAvailability` (type: `boolean`):

When live reservation times are enabled, return every slot of the service day instead of only those near the reservation time.

## `reservationDate` (type: `string`):

Date used for the availability check, in YYYY-MM-DD format. Defaults to today.

## `reservationTime` (type: `string`):

Time used for the availability check, in 24-hour HH:MM format.

## `partySize` (type: `integer`):

Number of diners used for the availability check.

## `cuisines` (type: `array`):

Only return restaurants of these cuisines, by name (e.g. 'Italian', 'Steakhouse', 'Japanese'). Names are matched against the cuisines OpenTable actually lists for the searched area; an unknown name fails the run with the list of valid options.

## `priceBands` (type: `array`):

Only return restaurants in these price bands.

## `sort` (type: `string`):

Result ordering returned by OpenTable.

## `latitude` (type: `string`):

Exact search centre latitude, e.g. 41.9014. Set together with longitude to skip location lookup entirely.

## `longitude` (type: `string`):

Exact search centre longitude, e.g. -87.6503. Set together with latitude to skip location lookup entirely.

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

Leave enabled. OpenTable silently drops requests for the full restaurant profile from datacenter IP ranges, so a proxy is required for phone numbers, websites and opening hours.

## Actor input object example

```json
{
  "location": "New York",
  "searchTerm": "sushi",
  "maxItems": 50,
  "includeDetails": true,
  "reviewsPerRestaurant": 0,
  "reviewsSortBy": "newestReview",
  "includeAvailability": false,
  "fullDayAvailability": false,
  "reservationDate": "2026-09-12",
  "reservationTime": "19:30",
  "partySize": 2,
  "cuisines": [
    "Italian",
    "Steakhouse"
  ],
  "priceBands": [
    "3",
    "4"
  ],
  "sort": "best",
  "latitude": "41.9014",
  "longitude": "-87.6503",
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `dataset` (type: `string`):

Every scraped restaurant as a structured JSON row, including phone, website and opening hours.

# 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 = {
    "location": "Chicago"
};

// Run the Actor and wait for it to finish
const run = await client.actor("axlymxp/opentable-restaurant-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 = { "location": "Chicago" }

# Run the Actor and wait for it to finish
run = client.actor("axlymxp/opentable-restaurant-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 '{
  "location": "Chicago"
}' |
apify call axlymxp/opentable-restaurant-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,axlymxp/opentable-restaurant-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/DA2cg97E0K0XJjRIa/builds/10xNT3l0LBYvQEXWB/openapi.json
