OpenTable Review Scraper collects structured guest feedback from OpenTable restaurant pages, turning scattered reviews into clean, analysis-ready data. It helps you monitor customer sentiment, track experience trends, and benchmark performance across locations. Use it to power sentiment analysis, CX dashboards, and competitive intelligence with fresh OpenTable reviews.
Created by Bitbash, built to showcase our approach to Scraping and Automation!
If you are looking for opentable-review-scraper you've just found your team — Let’s Chat. 👆👆
OpenTable Review Scraper is designed to automatically extract customer reviews from OpenTable restaurant listings and convert them into a consistent JSON format. It focuses on capturing key experience signals such as overall ratings, category scores, and written feedback, making it ideal for analytics and reporting workflows.
This project is built for:
- Data analysts and BI teams who need structured review data.
- Restaurant groups and franchises monitoring guest satisfaction.
- Agencies and consultants running CX, reputation, or competitive analysis.
- Collects reviews from one or many restaurant detail pages with a single configuration.
- Follows pagination links to capture reviews across multiple pages per restaurant.
- Normalizes ratings, dates, and reviewer information into a unified schema.
- Preserves both overall rating and category-level scores (e.g., Food, Service, Ambience).
- Outputs clean JSON suitable for dashboards, spreadsheets, or data pipelines.
| Feature | Description |
|---|---|
| Multi-page review crawling | Follows pagination to collect reviews across multiple pages per restaurant, ensuring deeper historical coverage. |
| Structured JSON output | Normalizes all reviews into a consistent JSON schema with ratings, dates, reviewer info, and detailed category scores. |
| Category-level rating capture | Extracts individual scores for Food, Service, and Ambience to enable granular CX and NPS-style analysis. |
| Configurable page limit | maxPagesPerCrawl lets you cap how deep to go for each restaurant, balancing coverage and runtime. |
| Flexible start URLs | Accepts a list of restaurant page URLs so you can scrape single locations or entire portfolios. |
| Integration-friendly data | JSON output aligns well with tools like Looker Studio, Google Sheets, DinerVibe-style dashboards, or custom ETL flows. |
| Field Name | Field Description |
|---|---|
reviewer |
Name or label of the guest leaving the review. |
date |
Date of the visit or review in YYYY-MM-DD format. |
rating |
Overall rating score given by the guest, typically on a 1–5 scale. |
review |
Full free-text feedback written by the guest. |
source |
Constant identifier for the data source (e.g., "OpenTable"). |
detailedRatings |
Object containing category-level scores such as Food, Service, and Ambience. |
detailedRatings.Food |
Numeric score representing the guest’s rating of food quality. |
detailedRatings.Service |
Numeric score representing the guest’s rating of service. |
detailedRatings.Ambience |
Numeric score representing the guest’s rating of ambience/atmosphere. |
restaurantUrl |
The URL of the restaurant page from which the review was extracted. |
scrapedAt |
Timestamp indicating when the review was scraped, useful for audit and freshness checks. |
Example:
[
{
"reviewer": "Jane",
"date": "2025-04-15",
"rating": 5,
"review": "Exceptional service and perfectly cooked steak!",
"source": "OpenTable",
"detailedRatings": {
"Food": 5,
"Service": 5,
"Ambience": 4
},
"restaurantUrl": "https://www.opentable.com/r/restaurant-name",
"scrapedAt": "2025-04-16T10:23:51Z"
},
{
"reviewer": "Michael",
"date": "2025-04-10",
"rating": 3,
"review": "Food was good but the wait time was longer than expected.",
"source": "OpenTable",
"detailedRatings": {
"Food": 4,
"Service": 2,
"Ambience": 4
},
"restaurantUrl": "https://www.opentable.com/r/restaurant-name",
"scrapedAt": "2025-04-16T10:23:51Z"
}
]
OpenTable Review Scraper/
├── src/
│ ├── index.js
│ ├── scraper/
│ │ ├── browserClient.js
│ │ ├── reviewExtractor.js
│ │ └── paginationHandler.js
│ ├── config/
│ │ ├── defaults.js
│ │ └── selectors.js
│ ├── utils/
│ │ ├── logger.js
│ │ ├── dateParser.js
│ │ └── rateLimiter.js
│ └── cli/
│ └── run.js
├── data/
│ ├── sample-start-urls.json
│ └── sample-output.json
├── tests/
│ ├── reviewExtractor.test.js
│ └── paginationHandler.test.js
├── .env.example
├── .gitignore
├── package.json
├── package-lock.json
└── README.md
- Restaurant owners use it to aggregate weekly and monthly review data, so they can spot service issues early and prioritize staff training.
- CX and analytics teams use it to feed sentiment analysis models and dashboards, so they can monitor guest satisfaction trends across multiple locations.
- Marketing agencies use it to benchmark clients against local competitors, so they can highlight strengths and address negative themes in campaigns.
- Franchise operators use it to compare performance across regions, so they can identify top-performing locations and replicate best practices.
- Product and strategy teams use it to map feedback to menu changes or pricing experiments, so they can validate decisions with real guest sentiment.
Q1: What input do I need to provide? You only need to supply a list of restaurant page URLs and a maximum number of pages to crawl per URL. A typical input looks like:
{
"startUrls": [
{ "url": "https://www.opentable.com/r/restaurant-name" }
],
"maxPagesPerCrawl": 5
}
This lets you control both which restaurants are included and how deep the scraper goes into historical reviews.
Q2: Does this scraper capture all review details from the page? It focuses on the most important and stable fields for analytics: reviewer name, visit or review date, overall rating, category scores, and written feedback. If additional non-critical fields exist on the page (such as badges or profile photos), they are intentionally omitted to keep the output lean and analysis-friendly.
Q3: How do I use the data once it is exported? The JSON output can be loaded into tools like Looker Studio, Google Sheets, or any BI platform that accepts structured data. You can also plug it into ETL pipelines, data warehouses, or custom applications that perform sentiment analysis, NPS calculation, or CX reporting.
Q4: What happens if the page layout changes? The scraper is built around OpenTable’s HTML structure as of 2025, including review containers and pagination buttons. If the layout changes significantly, you may need to update selector definitions in the configuration to restore full compatibility.
Primary Metric: In typical usage, the scraper processes around 150–250 reviews per minute per restaurant page sequence, depending on network latency and page complexity.
Reliability Metric: Across long-running crawls of multiple restaurants, success rates above 98% per page are achievable when network conditions are stable and rate limits are respected.
Efficiency Metric: With smart pagination handling and lightweight parsing, average memory usage stays low, allowing multiple restaurant URLs to be processed in a single run without resource saturation.
Quality Metric: Field-level completeness for core attributes (reviewer, date, rating, review text) routinely exceeds 99%, with category-level scores present whenever they are available on the originating OpenTable page.
