# OpenTable Restaurants, Ratings & Reviews Scraper (`parseforge/opentable-scraper`) Actor

Scrape OpenTable restaurants in any city. Export profiles, ratings, reviews, menus, cuisine, price, hours, coordinates as CSV, Excel, JSON, or XML.

- **URL**: https://apify.com/parseforge/opentable-scraper.md
- **Developed by:** [ParseForge](https://apify.com/parseforge) (community)
- **Categories:** Travel, E-commerce, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, NaN bookmarks
- **User rating**: No ratings yet

## Pricing

from $19.00 / 1,000 results

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/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are a software tools running on the Apify platform, for all kinds of web data extraction and automation use cases.
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.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp.md).

If your project is in a different language, use 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

![ParseForge Banner](https://github.com/ParseForge/apify-assets/blob/ad35ccc13ddd068b9d6cba33f323962e39aed5b2/banner.jpg?raw=true)

## 🍽️ OpenTable Scraper: Restaurants, Ratings & Reviews

> 🚀 **Export OpenTable restaurant listings in seconds.** Ratings, reviews, cuisine, hours, menus, prices, and exact coordinates for any city OpenTable indexes, ready to drop into your spreadsheet, BI tool, or AI pipeline.

> 🕒 **Last updated:** 2026-05-21 · **📊 48 fields** per record · **60k+ restaurants** indexed worldwide · **OpenTable coverage** across 20+ countries · **Real-time ratings + reservations**

OpenTable is the long-running reservations network that restaurant operators have used since the late 1990s, with active listings in cities from New York to Tokyo to Madrid. The structured data sitting behind each restaurant page is far richer than the booking widget you see on the front end: rating breakdowns by food, service, ambience, value, and noise, cuisine tags, dining style, hours of operation, price band, accepted payment methods, accessibility flags, neighborhood and metro, exact latitude and longitude, contact phone, and a recent reservation count. This Actor pulls all of it into clean JSON or CSV so you can analyze restaurants the way OpenTable's own analytics team does.

The Actor accepts plain-English search terms ("New York", "Greenwich Village italian", "Paris brunch") and walks the OpenTable search results page by page, enriching each restaurant with the full profile data fetched from its dedicated page. You can also pass direct restaurant URLs if you already have a target list. Output is the same flat record shape regardless of input mode, so it merges cleanly into existing datasets, and the run finishes whether the user is on a free preview or a paid plan up to a million items.

| 🎯 Target Audience | 💡 Primary Use Cases |
|---|---|
| Restaurant operators, food critics, hospitality investors, marketing agencies, travel planners, data journalists, academic researchers, location analytics teams | Competitive analysis, market entry research, restaurant scoring and ranking, neighborhood food density studies, menu trend tracking, review monitoring, deal sourcing for hospitality M&A, dataset enrichment for travel apps |

---

### 📋 What the OpenTable Scraper does

- 🔍 **Searches OpenTable by city, neighborhood, or cuisine.** Pass any term OpenTable's search bar accepts and the Actor paginates through every result page until your `maxItems` cap is hit.
- 💰 **Filters by price band.** Restrict the output to $, $$, $$$, or $$$$ tiers, alone or combined.
- 📊 **Sorts by Featured or Distance.** Match the order users actually see on the OpenTable site.
- 🍽️ **Enriches each restaurant with its full profile.** Hours, executive chef, dress code, parking, payment options, full address, public transit, and accessibility flags all pulled from the restaurant's detail page.
- 🔗 **Accepts direct restaurant URLs.** Drop in a list of `/r/...` or `/restaurant/profile/...` links and the Actor scrapes those directly without the search step.
- 📷 **Captures every gallery photo.** All restaurant photos available on OpenTable's CDN are returned as a deduplicated URL list.

Each record stands on its own with 48 named fields covering identification (restaurant ID, slug, OpenTable URL), commerce (price band, accepted payments, delivery partners, private dining flags), reputation (overall plus 5 sub-ratings, review count, recent reservation count, one recent review text), and geography (street address, neighborhood, metro, latitude, longitude, cross street, public transit). The output is the same shape whether you searched a city or fed a list of URLs.

> 💡 **Why it matters:** OpenTable is the booking layer that runs a meaningful share of dinner reservations in the English-speaking world. The data sitting behind it is the closest public proxy for actual restaurant traffic in many markets, and it includes detail you cannot get from a generic mapping service: granular sub-ratings, recent reservation counts, and the operator-curated cuisine tags and amenities.

---

### 🎬 Full Demo

🚧 Coming soon: a 3-minute walkthrough showing search, enrichment, and CSV export end to end.

---

### ⚙️ Input

<table>
<tr><th>Field</th><th>Type</th><th>Required</th><th>Description</th></tr>
<tr><td><code>searchTerms</code></td><td>array of strings</td><td>One of searchTerms or restaurantUrls</td><td>Cities, neighborhoods, cuisines, or restaurant names to search on OpenTable. Each entry is paginated independently.</td></tr>
<tr><td><code>restaurantUrls</code></td><td>array of strings</td><td>Optional</td><td>Direct OpenTable restaurant URLs. Used instead of or together with search terms.</td></tr>
<tr><td><code>maxItems</code></td><td>integer</td><td>No</td><td>Cap on records returned. Free users are limited to 10; paid users may set up to 1,000,000.</td></tr>
<tr><td><code>priceBands</code></td><td>array of strings</td><td>No</td><td>Restrict the search to specific price tiers. Pick from "1" ($), "2" ($$), "3" ($$$), "4" ($$$$).</td></tr>
<tr><td><code>sortBy</code></td><td>string</td><td>No</td><td>How OpenTable orders results. Either "web_conversion" (Featured, the default) or "distance".</td></tr>
<tr><td><code>enrichWithProfile</code></td><td>boolean</td><td>No</td><td>If true (default), each restaurant's profile page is fetched for the complete record. Set to false for a faster, lighter run.</td></tr>
</table>

Example: search a city for the top 50 paid records.

```json
{
    "searchTerms": ["New York"],
    "maxItems": 50,
    "priceBands": ["3", "4"],
    "sortBy": "web_conversion",
    "enrichWithProfile": true
}
````

Example: scrape three specific restaurants directly.

```json
{
    "restaurantUrls": [
        "https://www.opentable.com/r/le-bernardin-new-york",
        "https://www.opentable.com/restaurant/profile/100",
        "https://www.opentable.com/r/eleven-madison-park"
    ],
    "maxItems": 3
}
```

> ⚠️ **Good to Know:** OpenTable serves slightly different result sets per region. Searches default to a US viewpoint. If you want France, Spain, or Japan results, include the country or city name explicitly in `searchTerms` (e.g. "Paris", "Tokyo Ginza"). The `enrichWithProfile` step adds roughly 1 second per restaurant.

***

### 📊 Output

Each record is a flat JSON object with all 48 fields below. Empty values are returned as `null` or empty arrays so downstream tooling never has to guess.

#### 🧾 Schema

| Field | Type | Example |
|---|---|---|
| 🖼 `imageUrl` | string | `https://resizer.otstatic.com/v4/photos/49981008-3?width=640&height=640` |
| 🍽 `title` | string | `Sofia's of Little Italy` |
| 🔗 `url` | string | `https://www.opentable.com/r/sofias-of-little-italy-new-york` |
| 🆔 `restaurantId` | integer | `1228705` |
| 📝 `description` | string | `A trendy Italian restaurant & bar located at 143 Mulberry Street...` |
| 🍝 `primaryCuisine` | string | `Italian` |
| 🧾 `cuisines` | array of strings | `["Italian", "Pizza Bar"]` |
| 💰 `priceRange` | string | `$30 and under` |
| 🪙 `priceTier` | integer | `2` |
| 🍴 `diningStyle` | string | `Casual Dining` |
| ⭐ `rating` | number | `4.3` |
| 🍲 `ratingFood` | number | `4.3` |
| 🛎 `ratingService` | number | `4.4` |
| 🌃 `ratingAmbience` | number | `4.5` |
| 💵 `ratingValue` | number | `4.1` |
| 🔊 `ratingNoise` | number | `2` |
| 💬 `reviewCount` | integer | `112` |
| 🗒 `totalReviewCount` | integer | `26` |
| 📅 `recentReservationCount` | integer | `6` |
| 🗣 `topReviewText` | string | `The food was good. We sat outdoors and I loved how the staff handled a crazy man outside...` |
| 📞 `phoneNumber` | string | `(212) 219-9799` |
| 🌐 `website` | string | `https://www.sofias143.com/` |
| 🏠 `address` | object | `{ line1, line2, city, state, postCode, country }` |
| 📍 `neighborhood` | string | `Little Italy` |
| 🌆 `metro` | string | `New York City` |
| 🛣 `crossStreet` | string | `Between Grand Street and Hester Street` |
| 🚇 `publicTransit` | string | `Canal Street Station: Served by the N, Q, R, W, 6, and J/Z trains...` |
| 📐 `latitude` | number | `40.7189347` |
| 📐 `longitude` | number | `-73.9978869` |
| 🕒 `hoursOfOperation` | string | `Daily 11:00 am-11:00 pm` |
| 👔 `dressCode` | string | `Business Casual` |
| 👨‍🍳 `executiveChef` | string or null | `null` |
| 🅿️ `parkingInfo` | string | `None` |
| 🅿️ `parkingDetails` | string or null | `null` |
| ✨ `features` | object | `{ bar, counter, highTop, outdoor, reservationMaxPartySize }` |
| 💳 `paymentOptions` | array of strings | `["AMEX", "Discover", "Mastercard", "Visa"]` |
| 🔖 `additionalDetails` | array of strings | `["Bar/Lounge", "Beer", "Delivery", "Dog Friendly", "Wheelchair Access"]` |
| 🥡 `hasTakeout` | boolean | `true` |
| 🥂 `hasPrivateDining` | boolean | `true` |
| 🛵 `hasDeliveryPartners` | boolean | `false` |
| 🛵 `hasDeliveryDirect` | boolean | `true` |
| 🛵 `deliveryPartners` | array of objects | `[{ deliveryPartnerName, menuUrl }]` |
| 🌐 `orderOnlineLink` | string or null | `https://www.grubhub.com/restaurant/sofias-in-little-italy-nyc...` |
| 🏆 `awards` | array of objects or null | `null` |
| 💎 `inPremiumMarketplace` | boolean | `false` |
| 🖼 `photoUrls` | array of strings | `["https://resizer.otstatic.com/v4/photos/49981008-3?width=640&height=360", ...]` |
| 🕒 `scrapedAt` | string (ISO 8601) | `2026-05-21T16:25:08.884Z` |
| ❌ `error` | string or null | `null` |

#### 📦 Sample records

<details>
<summary><strong>🍕 Sofia's of Little Italy - casual Italian, neighborhood gem</strong></summary>

```json
{
    "imageUrl": "https://resizer.otstatic.com/v4/photos/49981008-3?width=640&height=640",
    "title": "Sofia's of Little Italy",
    "url": "https://www.opentable.com/r/sofias-of-little-italy-new-york",
    "restaurantId": 1228705,
    "description": "A trendy Italian restaurant & bar located at 143 Mulberry Street in the heart of historical Little Italy NYC. Handmade Lasagna, Ravioli, Manicotti, Fettuccini with fresh-made pizza and a full seating bar with happy hour specials make Sofia's a must-visit.",
    "primaryCuisine": "Italian",
    "cuisines": ["Italian", "Pizza Bar"],
    "priceRange": "$30 and under",
    "priceTier": 2,
    "diningStyle": "Casual Dining",
    "rating": 4.3,
    "ratingFood": 4.3,
    "ratingService": 4.4,
    "ratingAmbience": 4.5,
    "ratingValue": 4.1,
    "ratingNoise": 2,
    "reviewCount": 112,
    "totalReviewCount": 26,
    "recentReservationCount": 6,
    "topReviewText": "The food was good. We sat outdoors and I loved how the staff handled a crazy man outside who was constantly cussing and disturbing the guests. Our server named Flower was such a sweetheart. They surprised me with a birthday cake.",
    "phoneNumber": "(212) 219-9799",
    "website": "https://www.sofias143.com/",
    "address": {
        "line1": "143 Mulberry St",
        "line2": null,
        "city": "New York",
        "state": "NY",
        "postCode": "10013-4737",
        "country": "United States"
    },
    "neighborhood": "Little Italy",
    "metro": "New York City",
    "crossStreet": "Between Grand Street and Hester Street",
    "latitude": 40.7189347,
    "longitude": -73.9978869,
    "hoursOfOperation": "Daily 11:00 am-11:00 pm",
    "dressCode": "Business Casual",
    "executiveChef": null,
    "parkingInfo": "None",
    "features": { "bar": false, "counter": false, "highTop": false, "outdoor": true, "reservationMaxPartySize": 20 },
    "paymentOptions": ["AMEX", "Discover", "Mastercard", "Visa"],
    "additionalDetails": ["Bar/Lounge", "Beer", "Delivery", "Dog Friendly", "Entertainment", "Happy Hour", "Non-Smoking", "Patio/Outdoor Dining", "Private Room", "Takeout", "Wheelchair Access", "Wine"],
    "hasTakeout": true,
    "hasPrivateDining": true,
    "hasDeliveryPartners": false,
    "hasDeliveryDirect": true,
    "deliveryPartners": [],
    "orderOnlineLink": "https://www.grubhub.com/restaurant/sofias-in-little-italy-nyc-143-mulberry-st-new-york/3228087",
    "awards": null,
    "inPremiumMarketplace": false,
    "photoUrls": [
        "https://resizer.otstatic.com/v4/photos/49981008-3?width=640&height=360",
        "https://resizer.otstatic.com/v4/photos/50208343-2?width=640&height=360",
        "https://resizer.otstatic.com/v4/photos/50208251-2?width=640&height=360"
    ],
    "scrapedAt": "2026-05-21T16:25:08.884Z",
    "error": null
}
```

</details>

<details>
<summary><strong>🍣 Blue Ribbon Sushi Bar & Grill - high-rated Japanese, 470 reviews</strong></summary>

```json
{
    "imageUrl": "https://resizer.otstatic.com/v4/photos/51710616-2?width=640&height=640",
    "title": "Blue Ribbon Sushi Bar & Grill - Financial District",
    "url": "https://www.opentable.com/r/blue-ribbon-sushi-bar-and-grill-financial-district-new-york",
    "restaurantId": 1228645,
    "description": "We serve Japanese seafood, hot entrees & signature fried chicken plated in a sophisticated atmosphere located at the corner of Maiden Lane and William Street. Our menu features expertly prepared traditional Japanese Sushi and Sashimi, complemented by signature entrees from our hot kitchen including Grilled Skirt Steak, Oxtail Fried Rice, Steamed Lobster, Japanese A5 Wagyu, and our famous Blue Ribbon Fried Chicken.",
    "primaryCuisine": "Japanese",
    "cuisines": ["Japanese"],
    "priceRange": "$30 and under",
    "priceTier": 2,
    "diningStyle": "Casual Dining",
    "rating": 4.8,
    "ratingFood": 4.8,
    "ratingService": 4.7,
    "ratingAmbience": 4.6,
    "ratingValue": 4.3,
    "ratingNoise": 2,
    "reviewCount": 470,
    "totalReviewCount": 186,
    "recentReservationCount": 46,
    "topReviewText": "Excellent experience all around. Friendly & helpful staff. Oxtail fried rice was amazing",
    "phoneNumber": "(212) 315-4900",
    "website": "https://www.blueribbonsushibarandgrilldowntown.com/",
    "address": {
        "line1": "84 William Street",
        "line2": null,
        "city": "New York",
        "state": "NY",
        "postCode": "10038",
        "country": "United States"
    },
    "neighborhood": "Financial District",
    "metro": "New York City",
    "crossStreet": "William Street and Maiden Lane",
    "publicTransit": "Subways: 2, 3, J, Z",
    "latitude": 40.7080047,
    "longitude": -74.0077256,
    "hoursOfOperation": "Mon-Fri 11:30 am-10:00 pm\nSat, Sun 4:00 pm-10:00 pm",
    "dressCode": "Casual Dress",
    "executiveChef": null,
    "parkingInfo": "None",
    "features": { "bar": true, "counter": false, "highTop": false, "outdoor": false, "reservationMaxPartySize": 8 },
    "paymentOptions": ["AMEX", "Discover", "Mastercard", "Visa"],
    "additionalDetails": ["Beer", "Cocktails", "Delivery", "Gluten-free Options", "Non-Smoking", "Takeout", "Wine"],
    "hasTakeout": true,
    "hasPrivateDining": false,
    "hasDeliveryPartners": false,
    "hasDeliveryDirect": true,
    "deliveryPartners": [],
    "orderOnlineLink": "https://order.online/store/BlueRibbonSushiBarGrillFiDi-22984166/en-US/?hideModal=true&pickup=true",
    "awards": null,
    "inPremiumMarketplace": false,
    "photoUrls": [
        "https://resizer.otstatic.com/v4/photos/51710616-2?width=640&height=360",
        "https://resizer.otstatic.com/v4/photos/49020890-2?width=640&height=360",
        "https://resizer.otstatic.com/v4/photos/49020885-2?width=640&height=360"
    ],
    "scrapedAt": "2026-05-21T16:25:10.484Z",
    "error": null
}
```

</details>

<details>
<summary><strong>🍝 Serafina Tribeca - mid-tier Italian with outdoor dining and delivery</strong></summary>

```json
{
    "imageUrl": "https://resizer.otstatic.com/v4/photos/26102648-1?width=640&height=640",
    "title": "Serafina Tribeca",
    "url": "https://www.opentable.com/r/serafina-tribeca-new-york",
    "restaurantId": 732637,
    "description": "A beautiful building on the corner of West Broadway and Reade Street with large windows, excellent for people watching in the colder months and lovely breezes on warmer days and nights. Comforting Italian cuisine paired with excellent wines, or one of the many choices from the large bar menu cocktails and spirits.",
    "primaryCuisine": "Italian",
    "cuisines": ["Italian", "Pizzeria", "Pizza Bar"],
    "priceRange": "$31 to $50",
    "priceTier": 3,
    "diningStyle": "Casual Dining",
    "rating": 4.7,
    "ratingFood": 4.6,
    "ratingService": 4.6,
    "ratingAmbience": 4.4,
    "ratingValue": 4.3,
    "ratingNoise": 2,
    "reviewCount": 835,
    "totalReviewCount": 134,
    "recentReservationCount": 35,
    "topReviewText": "The food here is delicious the waitress was a little bit rude but nothing crazy we just brushed it off but the food here is bomb",
    "phoneNumber": "(212) 766-2700",
    "website": "https://www.serafinarestaurant.com/location/serafina-tribeca/",
    "address": {
        "line1": "95 West Broadway",
        "line2": null,
        "city": "New York",
        "state": "NY",
        "postCode": "10007",
        "country": "United States"
    },
    "neighborhood": "TriBeCa",
    "metro": "New York City",
    "crossStreet": "W. Broadway",
    "latitude": 40.7156101,
    "longitude": -74.008958,
    "hoursOfOperation": "Mon-Thu, Sun 11:00 am-9:45 pm\nFri, Sat 11:00 am-10:45 pm",
    "dressCode": "Casual Dress",
    "executiveChef": null,
    "parkingInfo": "Street Parking",
    "features": { "bar": true, "counter": false, "highTop": false, "outdoor": true, "reservationMaxPartySize": 18 },
    "paymentOptions": ["AMEX", "Discover", "Mastercard", "Visa"],
    "additionalDetails": ["Bar/Lounge", "Beer", "Cocktails", "Delivery", "Full Bar", "Gluten-free Options", "Happy Hour", "Non-Smoking", "Patio/Outdoor Dining", "Private Room", "Takeout", "Weekend Brunch", "Wheelchair Access", "Wine"],
    "hasTakeout": true,
    "hasPrivateDining": true,
    "hasDeliveryPartners": true,
    "hasDeliveryDirect": false,
    "deliveryPartners": [
        {
            "active": true,
            "deliveryPartnerName": "UBER_EATS",
            "deliveryPartnerId": 3,
            "menuUrl": "https://ubertrk.com/c/2606859/811249/5714?prodsku=b9e8267b-9fd4-42a4-86f6-59abb902b03e"
        }
    ],
    "orderOnlineLink": null,
    "awards": null,
    "inPremiumMarketplace": false,
    "photoUrls": [
        "https://resizer.otstatic.com/v4/photos/26102648-1?width=640&height=360",
        "https://resizer.otstatic.com/v4/photos/26138345-1?width=640&height=360",
        "https://resizer.otstatic.com/v4/photos/26138344-1?width=640&height=360"
    ],
    "scrapedAt": "2026-05-21T16:25:12.093Z",
    "error": null
}
```

</details>

***

### ✨ Why choose this Actor

| | Capability |
|---|---|
| 🍽️ | **Full restaurant detail, not just listings.** Every record carries hours, executive chef, dress code, parking, payment methods, accessibility flags, and the full delivery partner list, not just name and rating. |
| ⭐ | **Five-axis ratings, not one number.** Overall, food, service, ambience, value, and noise scores arrive separately so you can model "loud but good" or "quiet but expensive" properly. |
| 📍 | **Exact coordinates.** Latitude and longitude in every record, suitable for direct ingestion into PostGIS, BigQuery GIS, or a CARTO map. |
| 🌐 | **Multi-country.** OpenTable runs in 20+ countries and the search term is the only knob you need to switch from "New York" to "London" to "Madrid". |
| 🔁 | **Two input modes.** Search by text or feed direct URLs. The output shape is identical so both flows merge cleanly into the same dataset. |
| 🆓 | **Free tier for previewing.** Free Apify accounts can run a 10-record preview before committing to a paid plan. |
| 🧾 | **Schema is flat and stable.** Forty-eight fields, dot-pathed objects only where the source is structurally nested (address, features, delivery partners). |

> 📊 A single New York search returns 600 to 800 distinct restaurants depending on price filter, and the Actor pulls roughly 5 records per minute with full profile enrichment on a residential proxy.

***

### 📈 How it compares to alternatives

| Approach | Cost | Coverage | Refresh | Filters | Setup |
|---|---|---|---|---|---|
| **⭐ OpenTable Scraper** *(this Actor)* | Pay per item, free preview | All countries OpenTable indexes | On demand | Search term, price band, sort order, direct URL list | One JSON input, no API key |
| Generic mapping APIs | Per-call pricing, monthly tiers | Restaurants alongside other POIs | Indexed quarterly | Place name lookup, category | Account, project, billing setup |
| Paid live reservation APIs | Enterprise license, contract negotiation | Operator-side only | Real-time | API-key gated | Engineering integration |
| DIY scraper | Engineering time, proxy bill | Whatever you can maintain | Whatever you can maintain | Whatever you build | Build and ship the whole stack |
| Manual copy-paste | Time | What you have patience for | Stale on day two | Manual | None |

OpenTable's data shape is consumer-search-first, so this Actor gives you the same view a diner sees plus the structured fields hiding behind it.

***

### 🚀 How to use

1. ✅ **Sign up for a free Apify account.** Use [this referral link](https://console.apify.com/sign-up?fpr=vmoqkp) to get started with $5 in free credit. Free accounts can preview 10 records per run.
2. 🍽️ **Open the OpenTable Scraper.** Find it on your dashboard or in the Apify Store.
3. 🛠️ **Paste your input.** A list of cities, neighborhoods, or direct restaurant URLs. Pick a price band if you want. Set `maxItems`.
4. ▶️ **Click Start.** The Actor walks search pages and enriches every record. Output appears in the dataset tab as records land.
5. 📥 **Download CSV, Excel, JSON, or XML.** Or stream the dataset into Make, Zapier, Airbyte, or your own webhook.

> ⏱️ **Total time:** under 2 minutes to first record, around 1 minute per 50 enriched records after that. A 1,000-restaurant pull typically completes in 20-25 minutes.

***

### 💼 Business use cases

<table>
<tr>
<td width="50%">

#### 🍽️ Restaurant operators

- Track competitor ratings and review counts in your neighborhood
- Identify newly opened venues in the same price band
- Benchmark amenities (private dining, takeout, wheelchair access) against peers
- Watch top-review text for shifts in customer language

</td>
<td width="50%">

#### 📈 Hospitality investors and M\&A

- Source acquisition targets by city and price band
- Compare review velocity across multiple candidates
- Pull recent reservation counts as a traffic proxy
- Build comparable sets for valuation models

</td>
</tr>
<tr>
<td width="50%">

#### 🗺️ Travel and food media

- Build "best of" city guides with verified data, not guesses
- Cross-reference Michelin and James Beard award lists
- Generate consistent restaurant profile cards at scale
- Power affiliate booking pages with current ratings

</td>
<td width="50%">

#### 🏢 Marketing agencies and analytics

- Build restaurant prospect lists for hospitality clients
- Score neighborhoods for emerging food scenes
- Train recommendation models on real cuisine, price, and rating data
- Feed CRM systems with phone and address fields

</td>
</tr>
</table>

***

### 🔌 Automating OpenTable Scraper

Schedule runs, chain into pipelines, or trigger from your own code. The Actor exposes the standard Apify run API so any HTTP client works.

- 🟩 **Node.js:** use the [Apify JavaScript client](https://docs.apify.com/api/client/js) to start runs and read the dataset programmatically.
- 🐍 **Python:** use the [Apify Python client](https://docs.apify.com/api/client/python) for the same operations from a notebook or backend service.
- 📚 **Docs:** see the [Apify Actor API reference](https://docs.apify.com/api/v2#/reference/actors) for raw HTTP examples.

Schedules run from Apify Console without writing any glue. Pick a frequency, attach an input template, and the dataset rebuilds itself on the cadence you choose, ready for webhooks or storage exports.

***

### 🌟 Beyond business use cases

Data like this powers more than commercial workflows. The same structured records support research, education, civic projects, and personal initiatives.

<table>
<tr>
<td width="50%">

#### 🎓 Research and academia

- Empirical datasets for papers, thesis work, and coursework
- Longitudinal studies tracking changes across snapshots
- Reproducible research with cited, versioned data pulls
- Classroom exercises on data analysis and ethical scraping

</td>
<td width="50%">

#### 🎨 Personal and creative

- Side projects, portfolio demos, and indie app launches
- Data visualizations, dashboards, and infographics
- Content research for bloggers, YouTubers, and podcasters
- Hobbyist collections and personal trackers

</td>
</tr>
<tr>
<td width="50%">

#### 🤝 Non-profit and civic

- Transparency reporting and accountability projects
- Advocacy campaigns backed by public-interest data
- Community-run databases for local issues
- Investigative journalism on public records

</td>
<td width="50%">

#### 🧪 Experimentation

- Prototype AI and machine-learning pipelines with real data
- Validate product-market hypotheses before engineering spend
- Train small domain-specific models on niche corpora
- Test dashboard concepts with live input

</td>
</tr>
</table>

***

### 🤖 Ask an AI assistant about this scraper

Not sure if this Actor covers your use case? Paste the question below into ChatGPT, Claude, or Gemini.

> "I found the ParseForge OpenTable Scraper on Apify. It scrapes restaurant listings from OpenTable including ratings, cuisine, price band, hours, coordinates, photos, and reservation counts. I want to \[describe your project]. Can this Actor help me? What input would I use?"

The AI will map your requirements against the input schema and sample output documented above.

***

### ❓ Frequently Asked Questions

<details>
<summary>🔍 <strong>Which cities can I scrape?</strong></summary>

Any city OpenTable indexes. Pass the city name as a search term, optionally combined with a neighborhood or cuisine. The Actor accepts the same free text the OpenTable search bar accepts.

</details>

<details>
<summary>📊 <strong>How many restaurants can I get per run?</strong></summary>

OpenTable typically returns 600 to 1,500 distinct restaurants per major-city search. The Actor paginates through them all up to your `maxItems` cap. Free accounts are capped at 10 records, paid accounts at 1,000,000.

</details>

<details>
<summary>⚡ <strong>How fast is it?</strong></summary>

Roughly 5 to 10 records per minute with full profile enrichment turned on. Setting `enrichWithProfile: false` returns the listing-level data alone and runs about 4x faster.

</details>

<details>
<summary>🔁 <strong>Does it handle pagination?</strong></summary>

Yes. The Actor paginates through OpenTable's search results in 50-restaurant pages until your `maxItems` cap is reached or OpenTable runs out of results.

</details>

<details>
<summary>🏆 <strong>Can I filter for Michelin restaurants?</strong></summary>

Include "michelin" in your search term (e.g. `searchTerms: ["michelin new york"]`). Award data is returned in the `awards` field whenever OpenTable surfaces it.

</details>

<details>
<summary>🛵 <strong>Are takeout and delivery flags included?</strong></summary>

Yes. Each record carries `hasTakeout`, `hasDeliveryDirect`, `hasDeliveryPartners`, the full `deliveryPartners` array, and `orderOnlineLink` when the restaurant publishes one.

</details>

<details>
<summary>🗺️ <strong>Are coordinates accurate?</strong></summary>

Yes. Latitude and longitude come straight from OpenTable's restaurant record and match the marker placement on its map. Suitable for GIS work.

</details>

<details>
<summary>💼 <strong>Can I use this Actor for commercial purposes?</strong></summary>

Yes. Output can power commercial dashboards, analytics products, and internal tooling. You are responsible for how the data is used and stored.

</details>

<details>
<summary>💳 <strong>Do I need a paid Apify plan?</strong></summary>

A free Apify account can run the Actor and preview 10 records per run. Paid plans unlock the full `maxItems` range up to 1,000,000.

</details>

<details>
<summary>❗ <strong>What if a run fails partway?</strong></summary>

The Actor retries failed fetches up to three times with backoff. Records that successfully scraped before the failure are still saved to the dataset. Re-running picks up fresh.

</details>

<details>
<summary>⚖️ <strong>Is scraping OpenTable legal?</strong></summary>

Only public, non-personal restaurant data is collected. The Actor does not log in, bypass paywalls, or pull diner contact information. Compliance with your local laws and OpenTable's terms is your responsibility.

</details>

<details>
<summary>🔌 <strong>Does the Actor expose an API?</strong></summary>

Yes. Every Apify Actor has a stable run-and-fetch API. Trigger from Make, Zapier, Airbyte, GitHub Actions, a cron job, or your own backend.

</details>

***

### 🔌 Integrate with any app

Trigger runs, read datasets, and chain workflows from wherever your team already works.

- [**Make**](https://apify.com/integrations) - drag-and-drop scenarios that start an OpenTable run and route the dataset to a sheet or CRM.
- [**Zapier**](https://apify.com/integrations) - zaps that trigger off new dataset items.
- [**Slack**](https://apify.com/integrations) - post run summaries or new restaurants to a channel.
- [**Airbyte**](https://apify.com/integrations) - sync the dataset to Postgres, BigQuery, Snowflake, or Redshift.
- [**GitHub Actions**](https://docs.apify.com/api/v2) - run the Actor on every push or on a cron schedule.
- [**Google Drive**](https://apify.com/integrations) - drop CSV exports straight into a shared folder.

***

### 🔗 Recommended Actors

- [**⭐ Yelp Reviews Scraper**](https://apify.com/parseforge/yelp-reviews-scraper) - restaurant and business reviews from Yelp with star ratings, reviewer profiles, and photo counts.
- [**🗺️ Yellow Pages Scraper**](https://apify.com/parseforge/yellowpages-scraper) - business listings including phone, address, categories, and rating across any US city.
- [**🏨 Hostelworld Scraper**](https://apify.com/parseforge/hostelworld-scraper) - hostel and budget accommodation listings for the same travel destinations your restaurant searches cover.
- [**🍲 Allrecipes Scraper**](https://apify.com/parseforge/allrecipes-scraper) - recipe data to pair with restaurant cuisine analysis, covering ingredients, ratings, and nutrition.
- [**👗 Depop Scraper**](https://apify.com/parseforge/depop-scraper) - marketplace listings for second-hand goods, useful for lifestyle and consumer behavior datasets alongside dining data.

> 💡 **Pro Tip:** browse the complete [ParseForge collection](https://apify.com/parseforge) for more hospitality, travel, and review scrapers.

***

**🆘 Need Help?** [**Open our contact form**](https://tally.so/r/BzdKgA) and we will get back the same day.

***

> **⚠️ Disclaimer:** Independent tool, not affiliated with OpenTable. Only publicly available restaurant data is collected. Users are responsible for compliance with applicable laws and OpenTable's terms of use.

# Actor input Schema

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

Locations, neighborhoods, cuisines, or restaurant names to search on OpenTable. Each entry is paginated separately.

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

Direct OpenTable restaurant URLs (e.g. https://www.opentable.com/r/le-bernardin-new-york or https://www.opentable.com/restaurant/profile/100). Used instead of search terms.

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

Free users: Limited to 10 items (preview). Paid users: Optional, max 1,000,000.

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

Restrict to specific price tiers ($ = cheapest, $$$$ = most expensive). Leave empty for all.

## `sortBy` (type: `string`):

How OpenTable orders the search results.

## `enrichWithProfile` (type: `boolean`):

Open each restaurant's profile page for the complete record (hours, menu, executive chef, payment options). Slower but richer.

## Actor input object example

```json
{
  "searchTerms": [
    "New York"
  ],
  "restaurantUrls": [],
  "maxItems": 10,
  "priceBands": [],
  "sortBy": "web_conversion",
  "enrichWithProfile": true
}
```

# Actor output Schema

## `results` (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 = {
    "searchTerms": [
        "New York"
    ],
    "maxItems": 10
};

// Run the Actor and wait for it to finish
const run = await client.actor("parseforge/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"],
    "maxItems": 10,
}

# Run the Actor and wait for it to finish
run = client.actor("parseforge/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"
  ],
  "maxItems": 10
}' |
apify call parseforge/opentable-scraper --silent --output-dataset

```

## MCP server setup

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

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "OpenTable Restaurants, Ratings & Reviews Scraper",
        "description": "Scrape OpenTable restaurants in any city. Export profiles, ratings, reviews, menus, cuisine, price, hours, coordinates as CSV, Excel, JSON, or XML.",
        "version": "0.1",
        "x-build-id": "hhcq7cL3TblGtqNhg"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/parseforge~opentable-scraper/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-parseforge-opentable-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/acts/parseforge~opentable-scraper/runs": {
            "post": {
                "operationId": "runs-sync-parseforge-opentable-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor and returns information about the initiated run in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/runsResponseSchema"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/acts/parseforge~opentable-scraper/run-sync": {
            "post": {
                "operationId": "run-sync-parseforge-opentable-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "inputSchema": {
                "type": "object",
                "properties": {
                    "searchTerms": {
                        "title": "Search Terms",
                        "type": "array",
                        "description": "Locations, neighborhoods, cuisines, or restaurant names to search on OpenTable. Each entry is paginated separately.",
                        "default": [],
                        "items": {
                            "type": "string"
                        }
                    },
                    "restaurantUrls": {
                        "title": "Restaurant URLs (alternative input)",
                        "type": "array",
                        "description": "Direct OpenTable restaurant URLs (e.g. https://www.opentable.com/r/le-bernardin-new-york or https://www.opentable.com/restaurant/profile/100). Used instead of search terms.",
                        "default": [],
                        "items": {
                            "type": "string"
                        }
                    },
                    "maxItems": {
                        "title": "Max Items",
                        "minimum": 1,
                        "maximum": 1000000,
                        "type": "integer",
                        "description": "Free users: Limited to 10 items (preview). Paid users: Optional, max 1,000,000."
                    },
                    "priceBands": {
                        "title": "Price Bands",
                        "uniqueItems": true,
                        "type": "array",
                        "description": "Restrict to specific price tiers ($ = cheapest, $$$$ = most expensive). Leave empty for all.",
                        "items": {
                            "type": "string",
                            "enum": [
                                "1",
                                "2",
                                "3",
                                "4"
                            ],
                            "enumTitles": [
                                "$ (Under $30)",
                                "$$ ($31 to $50)",
                                "$$$ ($50 and over)",
                                "$$$$ ($100 and over)"
                            ]
                        },
                        "default": []
                    },
                    "sortBy": {
                        "title": "Sort Order",
                        "enum": [
                            "web_conversion",
                            "distance"
                        ],
                        "type": "string",
                        "description": "How OpenTable orders the search results.",
                        "default": "web_conversion"
                    },
                    "enrichWithProfile": {
                        "title": "Fetch full restaurant profile",
                        "type": "boolean",
                        "description": "Open each restaurant's profile page for the complete record (hours, menu, executive chef, payment options). Slower but richer.",
                        "default": true
                    }
                }
            },
            "runsResponseSchema": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            },
                            "actId": {
                                "type": "string"
                            },
                            "userId": {
                                "type": "string"
                            },
                            "startedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "finishedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "status": {
                                "type": "string",
                                "example": "READY"
                            },
                            "meta": {
                                "type": "object",
                                "properties": {
                                    "origin": {
                                        "type": "string",
                                        "example": "API"
                                    },
                                    "userAgent": {
                                        "type": "string"
                                    }
                                }
                            },
                            "stats": {
                                "type": "object",
                                "properties": {
                                    "inputBodyLen": {
                                        "type": "integer",
                                        "example": 2000
                                    },
                                    "rebootCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "restartCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "resurrectCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "computeUnits": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "options": {
                                "type": "object",
                                "properties": {
                                    "build": {
                                        "type": "string",
                                        "example": "latest"
                                    },
                                    "timeoutSecs": {
                                        "type": "integer",
                                        "example": 300
                                    },
                                    "memoryMbytes": {
                                        "type": "integer",
                                        "example": 1024
                                    },
                                    "diskMbytes": {
                                        "type": "integer",
                                        "example": 2048
                                    }
                                }
                            },
                            "buildId": {
                                "type": "string"
                            },
                            "defaultKeyValueStoreId": {
                                "type": "string"
                            },
                            "defaultDatasetId": {
                                "type": "string"
                            },
                            "defaultRequestQueueId": {
                                "type": "string"
                            },
                            "buildNumber": {
                                "type": "string",
                                "example": "1.0.0"
                            },
                            "containerUrl": {
                                "type": "string"
                            },
                            "usage": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "usageTotalUsd": {
                                "type": "number",
                                "example": 0.00005
                            },
                            "usageUsd": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "number",
                                        "example": 0.00005
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
