# OpenTable Reviews Scraper (`parsebird/opentable-reviews-scraper`) Actor

Extract OpenTable restaurant reviews: ratings, review text, reviewer profiles, helpfulness votes, and restaurant replies. Scrape one restaurant or a whole metro area.

- **URL**: https://apify.com/parsebird/opentable-reviews-scraper.md
- **Developed by:** [ParseBird](https://apify.com/parsebird) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 1 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.99 / 1,000 reviews

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
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

### OpenTable Reviews Scraper

OpenTable Reviews Scraper extracts diner reviews from [OpenTable](https://www.opentable.com) restaurant pages — ratings, review text, reviewer profiles, and restaurant replies — for one restaurant or an entire metro area at once.

<table><tr>
<td style="border-left:4px solid #1C1917;padding:12px 16px;font-weight:600">
Pull star ratings, food/service/ambience/value sub-scores, noise level, helpfulness votes, and reviewer details from any OpenTable restaurant, or point it at a metro page to pull reviews from every restaurant listed there.
</td>
</tr></table>

<br>

<table>
<tr>
<td colspan="2" style="padding:10px 14px;background:#DA3743;border:none;border-radius:4px 4px 0 0">
<span style="color:#FFFFFF;font-size:14px;font-weight:700;letter-spacing:0.5px">ParseBird OpenTable Suite</span>
<span style="color:#FFD1D1;font-size:13px">&nbsp;&nbsp;&bull;&nbsp;&nbsp;Restaurant &amp; review data</span>
</td>
</tr>
<tr>
<td style="padding:10px 14px;border:1px solid #E7E5E4;border-radius:0 0 0 4px;border-right:none;border-top:none;vertical-align:top;width:50%;background:#FFECEC">
<a href="https://apify.com/parsebird/opentable-reviews-scraper" style="color:#DA3743;text-decoration:none;font-weight:700;font-size:13px">OpenTable Reviews Scraper</a><br>
<span style="color:#DA3743;font-size:11px;font-weight:600">You are here</span>
</td>
<td style="padding:10px 14px;border:1px solid #E7E5E4;border-radius:0 0 4px 0;border-top:none;vertical-align:top;width:50%;background:#FFFFFF">
<a href="https://apify.com/parsebird/opentable-restaurants-scraper" style="color:#1C1917;text-decoration:none;font-weight:700;font-size:13px">OpenTable Restaurants Scraper</a><br>
<span style="color:#78716C;font-size:11px">Metro, search &amp; profile listings</span>
</td>
</tr>
</table>

##### Copy to your AI assistant

```
Use the Apify actor "parsebird/opentable-reviews-scraper" via the ApifyClient to scrape OpenTable restaurant reviews. Example: client.actor("parsebird/opentable-reviews-scraper").call(run_input={"startUrls": [{"url": "https://www.opentable.com/r/bestia-los-angeles"}], "results_wanted": 50}). Inputs: startUrls (array of {url}, either an OpenTable restaurant profile URL like opentable.com/r/<slug> or a metro/city listing URL like opentable.com/metro/<city>-restaurants — metro URLs expand into every restaurant listed on that page), results_wanted (integer, default 20, max reviews to collect in the run across all Start URLs, split round-robin across restaurants when there's more than one), proxyConfiguration (object, defaults to Apify's Unblocker proxy group, required — OpenTable blocks Datacenter and Residential proxies). Output fields per review include reviewId, restaurantName, restaurantId, restaurantUrl, rating, text, author, date, visitDate, foodRating, serviceRating, ambienceRating, valueRating, noiseLevel, helpfulCount, helpfulUp, helpfulDown, reviewType, reviewerName, reviewerInitials, reviewerReviewCount, reviewerMetro, reviewerIsVip, publicRestaurantReply, publicRestaurantReplyDate, and photoUrls. Full API spec: https://apify.com/parsebird/opentable-reviews-scraper/api. Get an API token at https://console.apify.com/settings/integrations.
```

### What does OpenTable Reviews Scraper do?

OpenTable Reviews Scraper is a review-extraction tool for **OpenTable**, the restaurant reservation platform used by tens of thousands of restaurants across the US and beyond. Give it a restaurant page and it returns every review OpenTable shows — star rating, sub-ratings, full text, reviewer details, and any public reply from the restaurant — ready for a spreadsheet, sentiment model, or reputation dashboard.

- 🍽️ Scrape reviews from a single restaurant, several named restaurants, or a whole metro/city listing page in one run
- ⭐ Full rating breakdown: overall, food, service, ambience, value, and noise level
- 👤 Reviewer profile data: name, initials, review count, home metro, VIP status, and profile photo
- 👍 Helpfulness votes (upvotes/downvotes) and restaurant replies with reply date
- 📸 Review photo URLs when diners attach photos
- 🔁 Automatic pagination — newest reviews first, no manual page clicking
- ⚙️ Runs on Apify's infrastructure with scheduling, API access, and integrations

### Input parameters

| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| startUrls | array of `{url}` | **Yes** | Bestia (LA) example URL | OpenTable restaurant profile URLs or metro/city listing URLs. Metro/city URLs expand into every restaurant on that page. |
| results\_wanted | integer | No | `20` | Maximum number of reviews to collect in this run, across all Start URLs combined. |
| proxyConfiguration | object | No | Unblocker (US) | Proxy settings. OpenTable's Akamai bot protection blocks Datacenter and Residential proxies — Unblocker is required. |

#### Basic review extraction

```json
{
  "startUrls": [{ "url": "https://www.opentable.com/r/bestia-los-angeles" }],
  "results_wanted": 50
}
```

#### Batch scraping from a metro search

```json
{
  "startUrls": [{ "url": "https://www.opentable.com/metro/los-angeles-restaurants" }],
  "results_wanted": 100
}
```

#### Competitive monitoring across restaurants

```json
{
  "startUrls": [
    { "url": "https://www.opentable.com/r/bestia-los-angeles" },
    { "url": "https://www.opentable.com/r/71above-los-angeles" }
  ],
  "results_wanted": 200
}
```

### What data can you extract from OpenTable?

| Field | Description |
|-------|-------------|
| reviewId, restaurantName, restaurantId, restaurantUrl | Identifiers for the review and its restaurant |
| rating, foodRating, serviceRating, ambienceRating, valueRating, noiseLevel | Full rating breakdown |
| text, date, visitDate, submittedDate | Review content and timing |
| author, reviewerInitials, reviewerReviewCount, reviewerMetro, reviewerIsVip, reviewerProfileColor, reviewerPhoto | Reviewer profile |
| helpfulCount, helpfulUp, helpfulDown | Helpfulness voting |
| publicRestaurantReply, publicRestaurantReplyDate | Restaurant's public reply, if any |
| reviewType, fromPreviousConcept, photoUrls | Verification status and attached photos |

### Output example

```json
{
  "reviewId": "OT-96412-2110686937",
  "restaurantName": "Bestia",
  "restaurantId": 96412,
  "restaurantUrl": "https://www.opentable.com/r/bestia-los-angeles",
  "rating": 5,
  "text": "The food was incredible, especially the bone marrow and the cavatelli. Service was attentive and the atmosphere was lively.",
  "author": "FoodieLA",
  "date": "2026-09-20T10:45:00Z",
  "visitDate": "2026-09-18T19:30:00-07:00",
  "foodRating": 5,
  "serviceRating": 5,
  "ambienceRating": 4,
  "valueRating": 5,
  "noiseLevel": "LOUD",
  "helpfulCount": 12,
  "helpfulUp": 12,
  "helpfulDown": 0,
  "reviewType": "OPENTABLEVERIFIED",
  "reviewerReviewCount": 34,
  "reviewerMetro": "Los Angeles",
  "reviewerIsVip": true
}
```

Download results as **JSON, CSV, Excel, HTML, or XML** from the Apify Console, or pull them programmatically through the [Apify API](https://docs.apify.com/api/v2).

### How to scrape OpenTable reviews

1. Open **OpenTable Reviews Scraper** on the Apify Store and click **Try for free**.
2. Paste one or more OpenTable restaurant URLs, or a metro/city listing URL, into **Start URLs**.
3. Set **Max reviews** to the number of reviews you want.
4. Click **Start** and wait for the run to finish.
5. Open the **Dataset** tab to view, filter, and export the scraped reviews.

### How it works

1. For each Start URL, the Actor checks whether it's a restaurant profile page or a metro/city listing page.
2. Listing pages are expanded into the individual restaurant profile URLs shown on them.
3. Each restaurant's reviews are read directly from OpenTable's own server-rendered page data, newest first, paginating 10 reviews at a time.
4. When a run has more than one restaurant, review collection round-robins across them so the review budget is shared rather than spent entirely on the first restaurant.
5. Every review is written as one dataset row as soon as it's collected.

### How much does it cost to scrape OpenTable?

OpenTable Reviews Scraper uses **pay-per-event** pricing — you're charged only for reviews actually saved to your dataset.

| Plan | Price per review | Price per 1,000 |
|------|-------------------|------------------|
| Free | $0.00129 | **$1.29** |
| Bronze | $0.00119 | **$1.19** |
| Silver | $0.00109 | **$1.09** |
| Gold | $0.00099 | **$0.99** |

Collecting 500 reviews on the Free plan costs about $0.65. Apify's [monthly platform usage credits](https://apify.com/pricing) apply to this Actor like any other.

### Using the API

#### Python

```python
from apify_client import ApifyClient

client = ApifyClient("<YOUR_API_TOKEN>")

run = client.actor("parsebird/opentable-reviews-scraper").call(run_input={
    "startUrls": [{"url": "https://www.opentable.com/r/bestia-los-angeles"}],
    "results_wanted": 100,
})

for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item["author"], item["rating"], item["text"])
```

#### JavaScript

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

const client = new ApifyClient({ token: '<YOUR_API_TOKEN>' });

const run = await client.actor('parsebird/opentable-reviews-scraper').call({
    startUrls: [{ url: 'https://www.opentable.com/r/bestia-los-angeles' }],
    results_wanted: 100,
});

const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items);
```

Schedule recurring runs to track new reviews week over week, or connect it to Zapier/Make through Apify's [integrations](https://apify.com/integrations).

### Is it legal to scrape OpenTable?

Scraping publicly available data — like reviews shown on a public OpenTable restaurant page — is generally considered legal, and courts have repeatedly upheld this for public web pages. This Actor only collects review data OpenTable already displays to any visitor; it never accesses private diner accounts or reservation details. You are responsible for how you use the collected data and for complying with OpenTable's terms of service and applicable law in your jurisdiction. See Apify's [blog post on the legality of web scraping](https://blog.apify.com/is-web-scraping-legal/) for more detail.

### Related Actors

- [OpenTable Restaurants Scraper](https://apify.com/parsebird/opentable-restaurants-scraper) — restaurant listing data (cuisine, price, address, photos) from OpenTable
- [TheFork Scraper](https://apify.com/parsebird/thefork-scraper) — restaurant and review data from TheFork (formerly La Fourchette / El Tenedor)

### FAQ

**How many reviews can I collect in one run?**
As many as you set in `results_wanted`. Each restaurant page is paginated 10 reviews at a time, newest first, up to that restaurant's total review count.

**Why does the Actor need Unblocker proxies specifically?**
OpenTable's Akamai bot protection blocks Apify's Datacenter and Residential proxy groups outright. Unblocker is the only proxy group that reliably loads OpenTable pages, so it's the required default.

**What order are reviews returned in?**
Newest first — the same default order OpenTable shows on the restaurant page itself.

**Can I scrape reviews for an entire city at once?**
Yes. Pass a metro/city listing URL (e.g. `opentable.com/metro/los-angeles-restaurants`) as a Start URL and it expands into every restaurant listed on that page.

**What happens if a restaurant has fewer reviews than my `results_wanted`?**
The Actor collects everything available for that restaurant and moves on — it never fabricates or duplicates reviews.

**Can I schedule recurring runs?**
Yes. Use Apify's [Scheduler](https://docs.apify.com/platform/schedules) to run this Actor daily, weekly, or at any interval.

**Does this Actor have an API?**
Yes — every Apify Actor is automatically available as an API. See the [API tab](https://apify.com/parsebird/opentable-reviews-scraper/api) for the full spec, or use the Python/JavaScript examples above.

**Something not working?**
Report it on the Actor's **Issues** tab in Apify Console — OpenTable occasionally changes its site, and prompt reports help keep this Actor maintained.

# Changelog

This Actor's version history is a separate document: https://apify.com/parsebird/opentable-reviews-scraper/changelog.md

# Actor input Schema

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

OpenTable restaurant profile URLs (e.g. opentable.com/r/bestia-los-angeles) or metro/city listing URLs (e.g. opentable.com/metro/los-angeles-restaurants). Metro/city URLs expand into every restaurant listed on that page.

## `results_wanted` (type: `integer`):

Maximum number of reviews to collect in this run, across all Start URLs combined.

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

OpenTable is protected by Akamai bot detection. Datacenter and Residential proxies are blocked — this Actor needs Apify's Unblocker proxy group to load pages successfully.

## Actor input object example

```json
{
  "startUrls": [
    {
      "url": "https://www.opentable.com/r/bestia-los-angeles"
    }
  ],
  "results_wanted": 20,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "UNBLOCKER"
    ],
    "apifyProxyCountry": "US"
  }
}
```

# Actor output Schema

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

No description

# 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 = {
    "startUrls": [
        {
            "url": "https://www.opentable.com/r/bestia-los-angeles"
        }
    ],
    "results_wanted": 20,
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "UNBLOCKER"
        ],
        "apifyProxyCountry": "US"
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("parsebird/opentable-reviews-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 = {
    "startUrls": [{ "url": "https://www.opentable.com/r/bestia-los-angeles" }],
    "results_wanted": 20,
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["UNBLOCKER"],
        "apifyProxyCountry": "US",
    },
}

# Run the Actor and wait for it to finish
run = client.actor("parsebird/opentable-reviews-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 '{
  "startUrls": [
    {
      "url": "https://www.opentable.com/r/bestia-los-angeles"
    }
  ],
  "results_wanted": 20,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "UNBLOCKER"
    ],
    "apifyProxyCountry": "US"
  }
}' |
apify call parsebird/opentable-reviews-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,parsebird/opentable-reviews-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/J29eQX6kgwqrahgJa/builds/DKoFvOuTkh6NLYe5Z/openapi.json
