# OpenTable Scraper — Ratings, Reviews & Cuisine (`khadinakbar/opentable-scraper`) Actor

Scrape OpenTable restaurants by city, cuisine, or name. Returns rating, review count, price band, address, phone, coordinates, and top review. HTTP-only, MCP-ready.

- **URL**: https://apify.com/khadinakbar/opentable-scraper.md
- **Developed by:** [Khadin Akbar](https://apify.com/khadinakbar) (community)
- **Categories:** Lead generation, Travel, MCP servers
- **Stats:** 1 total users, 0 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $5.00 / 1,000 restaurant scrapeds

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#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 Scraper — Ratings, Reviews & Cuisine

Scrape **OpenTable restaurants** by city, cuisine, neighborhood, or restaurant name and export a clean, structured dataset: rating, review count, price band, cuisine, full address, phone, coordinates, neighborhood, top review, photos, and dining features. HTTP-only, no login, no cookies — built to be called by AI agents (MCP-ready) and by data teams alike.

### What it does

Give it a search term like `Miami`, `Italian, Chicago`, or a restaurant name like `Carbone`, and the actor returns every matching restaurant with the fields you need for lead generation, market research, competitor tracking, or review analysis. One page = 50 restaurants; the actor auto-paginates to your `maxRestaurants` cap (a large metro can exceed 800 restaurants).

### When to use it

- **Local lead generation** — build restaurant contact lists (name, phone, address, neighborhood) for a city or cuisine.
- **Market & competitor research** — pull an entire metro's dining scene with ratings, review counts, and price tiers.
- **Review & sentiment monitoring** — track rating and review-count movement plus a highlighted top-review snippet per restaurant.
- **Geo / mapping datasets** — every record ships with latitude/longitude and a full postal address.
- **AI agents** — a single natural tool call: search term in, structured JSON out.

**When NOT to use it:** this actor does not scrape individual restaurant reservation-availability time slots or full review threads (those pages are bot-protected). Search individual restaurants by **name** to get their profile record.

### Output

One record per restaurant. Example:

| Field | Example |
|---|---|
| `name` | Saltie Girl |
| `primaryCuisine` | Seafood |
| `priceBand` / `priceRange` | `$31 to $50` / `3` |
| `overallRating` / `reviewCount` | `4.6` / `2271` |
| `neighborhood` | Back Bay |
| `addressLine1`, `city`, `state`, `postCode` | 279 Dartmouth Street, Boston, MA, 02116 |
| `latitude`, `longitude` | 42.3512, -71.0776 |
| `phone` | +16172670691 |
| `topReview` | "Fabulous, as always! Great food and service…" |
| `recentReservationCount` | 230 |
| `profileUrl` | https://www.opentable.com/r/saltie-girl-back-bay-boston |

Also included per record: `diningStyle`, `currency`, `hasBar`, `hasOutdoorSeating`, `hasCounter`, `hasHighTop`, `maxPartySize`, `hasTakeout`, `inPremiumMarketplace`, `awards[]`, `offers[]`, `photoUrls[]`, `description`, `searchTerm`, `resultPosition`, `scrapedAt`.

```json
{
  "restaurantId": 52135,
  "name": "Saltie Girl",
  "primaryCuisine": "Seafood",
  "priceBand": "$31 to $50",
  "overallRating": 4.6,
  "reviewCount": 2271,
  "neighborhood": "Back Bay",
  "city": "Boston",
  "state": "MA",
  "latitude": 42.3511566,
  "longitude": -71.0775679,
  "phone": "+16172670691",
  "topReview": "Fabulous, as always! Great food and service…",
  "profileUrl": "https://www.opentable.com/r/saltie-girl-back-bay-boston"
}
```

### Pricing

**Pay-per-event.**

| Event | Price |
|---|---|
| Actor start | $0.00005 |
| Restaurant scraped | **$0.005** per unique restaurant |

A 500-restaurant city pull costs roughly **$2.50**. You are charged only for unique restaurants actually returned. Pay-per-usage (compute + proxy) is also available for very large jobs — pick whichever billing suits you at run time.

### Input

| Field | Type | Default | Notes |
|---|---|---|---|
| `searchTerms` | string\[] | `["New York"]` | City, cuisine, neighborhood, or restaurant name — one per line. |
| `startUrls` | array | — | OpenTable search/listing URLs (e.g. `/s/?term=miami`). Not `/r/` detail pages. |
| `maxRestaurants` | integer | `50` | Cap **per term / URL**. Auto-paginates (50/page). |
| `partySize` | integer | `2` | Covers, 1–20. |
| `reservationDate` | string | — | Optional `YYYY-MM-DD` to bias toward availability. |
| `reservationTime` | string | `19:00` | Optional `HH:mm`; only used with a date. |
| `proxyConfiguration` | object | Residential US | Recommended — OpenTable blocks datacenter IPs. |

#### Example input

```json
{
  "searchTerms": ["Italian, Chicago", "Steakhouse, Austin"],
  "maxRestaurants": 200,
  "partySize": 2,
  "proxyConfiguration": { "useApifyProxy": true, "apifyProxyGroups": ["RESIDENTIAL"], "apifyProxyCountry": "US" }
}
```

### Using it via API

```bash
curl -X POST "https://api.apify.com/v2/acts/khadinakbar~opentable-scraper/runs?token=$APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "searchTerms": ["Miami"], "maxRestaurants": 100 }'
```

```javascript
import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('khadinakbar/opentable-scraper').call({
    searchTerms: ['San Francisco'],
    maxRestaurants: 150,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items);
```

### AI agents & MCP

This actor is MCP-ready. In AI frameworks, expose it through the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp) as `apify--opentable-scraper`. Input is a single search term; output is structured JSON per restaurant — ideal for restaurant-discovery, lead-enrichment, and local-market agents.

### Reliability

OpenTable resets datacenter and non-browser TLS connections at the edge. This actor impersonates a real Chrome TLS/HTTP-2 fingerprint (impit) and runs over Apify Residential proxies, parsing OpenTable's own embedded page state — no brittle HTML selectors. If OpenTable blocks a request, the actor retires the session and retries; if everything is blocked, the run fails honestly rather than returning an empty dataset silently.

### FAQ

**Can I get email addresses?** OpenTable does not publish restaurant emails; you get phone, address, and website-derived profile URL. Pair with a contact-enrichment actor for emails.

**Can I scrape one specific restaurant?** Yes — put its name (and city) in `searchTerms`; it will be returned as a record. Direct `/r/` profile URLs are bot-protected and not supported.

**Does party size / date filter results?** They contextualize OpenTable's availability-aware ranking; they do not hard-filter restaurants out.

**Which countries?** Any OpenTable market — search by the local city name. Proxy country defaults to US; change it for other regions.

### Legal

This actor collects only publicly available information from OpenTable search result pages. Use the data in compliance with OpenTable's Terms of Service, applicable laws (including GDPR/CCPA where relevant), and only for legitimate purposes. You are responsible for how you use scraped data. This actor is not affiliated with or endorsed by OpenTable.

# Actor input Schema

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

Free-text OpenTable searches, one per line. Use this to find restaurants by city ('Miami'), cuisine + city ('Italian, Chicago'), neighborhood ('SoHo, New York'), or restaurant name ('Carbone'). Each term is run separately and paginated up to Max restaurants. NOT an OpenTable URL — for a pre-built search/listing URL use Start URLs instead.

## `startUrls` (type: `array`):

OpenTable search or metro/cuisine listing URLs to scrape directly (e.g. 'https://www.opentable.com/s/?term=miami'). Use this when you already have an OpenTable results URL with filters applied. Each URL is paginated up to Max restaurants. NOT an individual restaurant page ('/r/...') — those are bot-protected and not supported; search by name via Search terms instead.

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

Maximum number of unique restaurants to return for EACH search term or start URL. OpenTable serves 50 restaurants per page; the actor auto-paginates until this cap or the result set is exhausted. Defaults to 50. Raise for full-market pulls (a large metro can exceed 800 restaurants).

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

Number of diners used to contextualize OpenTable's availability-aware results. Accepts 1 to 20. Defaults to 2. This influences which restaurants surface as available but does not filter out restaurants; it mirrors the 'covers' selector on opentable.com.

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

Optional target reservation date in YYYY-MM-DD format (e.g. '2026-07-15'). Use this to bias results toward restaurants with availability on that date. Leave empty for the default 'anytime' search. Must be today or a future date; past dates are ignored by OpenTable.

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

Optional target time in 24-hour HH:mm format (e.g. '19:30'). Only applied when Reservation date is set. Defaults to '19:00' (7 PM). Ignored when Reservation date is empty.

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

Proxy settings. OpenTable resets datacenter and non-browser TLS at the edge, so Apify Residential (US) is enabled by default and strongly recommended. Only change this if you know your IPs clear OpenTable. The actor impersonates Chrome TLS regardless of proxy choice.

## Actor input object example

```json
{
  "searchTerms": [
    "Miami",
    "Italian, Chicago",
    "Steakhouse, Austin"
  ],
  "startUrls": [
    {
      "url": "https://www.opentable.com/s/?term=san+francisco&covers=2"
    }
  ],
  "maxRestaurants": 50,
  "partySize": 2,
  "reservationDate": "2026-07-15",
  "reservationTime": "19:30",
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "US"
  }
}
```

# Actor output Schema

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

Scraped OpenTable restaurant records.

## `summary` (type: `string`):

End-of-run totals and warnings.

# 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 = {
    "searchTerms": [
        "New York"
    ],
    "maxRestaurants": 50
};

// Run the Actor and wait for it to finish
const run = await client.actor("khadinakbar/opentable-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 = {
    "searchTerms": ["New York"],
    "maxRestaurants": 50,
}

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

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

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

```

## CLI example

```bash
echo '{
  "searchTerms": [
    "New York"
  ],
  "maxRestaurants": 50
}' |
apify call khadinakbar/opentable-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=khadinakbar/opentable-scraper",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/acts/l53u6LQGsfK075iSe/builds/jZSAainw5bfiODpkN/openapi.json
