Zomato Restaurant Reviews Scraper
Pricing
from $0.96 / 1,000 item extracteds
Zomato Restaurant Reviews Scraper
Export public Zomato restaurant reviews with ratings, review text, reviewer metadata, dates, engagement, and restaurant context.
Pricing
from $0.96 / 1,000 item extracteds
Rating
0.0
(0)
Developer
Stas Persiianenko
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
12 hours ago
Last modified
Categories
Share
Export public Zomato restaurant reviews as clean JSON, CSV, Excel, or API-ready dataset rows. Give the Actor restaurant URLs or numeric IDs and receive review text, ratings, reviewer metadata, dates, engagement, restaurant identity, and summary fields.
This Actor is built for recurring reputation analysis and market research. It paginates public Zomato review pages, deduplicates reviews by stable ID, applies rating filters before charging, and preserves source URLs for verification.
What can you do with this Zomato reviews scraper?
- Build a review dataset for a one-time customer-feedback analysis.
- Schedule recurring runs and compare stable
reviewIdvalues to find new feedback. - Route one- and two-star reviews into complaint-triage workflows.
- Compare restaurant ratings, review volume, themes, and reviewer engagement.
- Send normalized review rows to spreadsheets, databases, dashboards, or language models.
The Actor exports source data. It does not perform sentiment classification, alert delivery, or historical change storage by itself; connect the dataset to your preferred analysis workflow.
Who is this Actor for?
Restaurant operators can review recent low-rated feedback without manually paging through Zomato.
Reputation teams can schedule a repeatable feed and deduplicate records using reviewId.
Market researchers can compare public ratings and review themes across supplied restaurants.
Data teams can consume a stable typed schema through Apify datasets, webhooks, integrations, or API clients.
AI teams can create source-attributed text datasets while retaining reviewer and restaurant context.
Why use this Actor?
- Review-level output: one dataset row per accepted review, not a restaurant-only summary.
- Useful context: review text and rating are joined with reviewer, restaurant, date, and engagement fields.
- URL and ID inputs: use a restaurant URL directly or resolve a numeric restaurant ID from a supplied Zomato listing page.
- Bounded pagination: global and per-restaurant limits stop requests as soon as enough records are saved.
- Rating filters: collect all reviews or focus on a rating range such as one to two stars.
- Stable deduplication: duplicate review IDs are never saved or charged twice in one run.
- Clear failures: blocked, malformed, or non-restaurant pages fail instead of returning a misleading empty success.
What data does the Actor extract?
| Group | Fields |
|---|---|
| Review | reviewId, reviewText, rating, ratingLabel, experience, reviewUrl |
| Date | reviewDate, reviewDateLabel, scrapedAt |
| Reviewer | reviewerId, reviewerName, reviewerProfileUrl, reviewerProfileImageUrl, reviewerReviewCount, reviewerFollowerCount |
| Engagement | likeCount, commentCount, photoUrls, tags, managementResponses |
| Restaurant | restaurantId, restaurantName, restaurantUrl, restaurantCuisines, restaurantRating, restaurantReviewCount |
| Traceability | sourcePage, scrapedAt |
Fields not exposed by a particular public review remain absent. reviewDateLabel preserves Zomato's displayed label. When the label is relative, reviewDate is an approximate date calculated at scrape time.
How to scrape Zomato restaurant reviews
- Open the Actor input page.
- Paste one or more public Zomato restaurant URLs into Zomato restaurant URLs.
- Set Maximum reviews and Maximum reviews per restaurant.
- Optionally set a minimum and maximum rating.
- Keep the default Apify Proxy configuration unless you have tested another route.
- Click Start.
- Open the Reviews dataset view and export JSON, CSV, Excel, XML, or RSS.
A restaurant /info, /menu, /order, or /reviews URL is accepted and normalized to the reviews page.
Input parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
startUrls | array | prefilled restaurant | Public Zomato restaurant URLs. |
restaurantIds | string array | [] | Numeric Zomato restaurant IDs to resolve from discoveryUrls. |
discoveryUrls | array | Bengaluru restaurants | Public listing pages containing requested restaurant IDs. Used only for ID input. |
maxItems | integer | 20 | Maximum reviews saved across all restaurants, from 1 to 10,000. |
maxReviewsPerRestaurant | integer | 20 | Maximum reviews saved for each restaurant, from 1 to 5,000. |
maxPagesPerRestaurant | integer | 20 | Safety cap on source pages fetched for each restaurant. |
minRating | number | 0 | Minimum accepted rating. |
maxRating | number | 5 | Maximum accepted rating. |
includeEmptyText | boolean | false | Keep rating-only entries with no public text. |
proxyConfiguration | object | SHADER | Apify Proxy configuration. Lower-cost SHADER datacenter proxy is enabled by default. |
At least one restaurant URL or restaurant ID is required. Rating filters must satisfy 0 <= minRating <= maxRating <= 5.
URL input example
{"startUrls": [{"url": "https://www.zomato.com/bangalore/cbd-central-bar-district-mg-road-bangalore/reviews"}],"maxItems": 25,"maxReviewsPerRestaurant": 25}
Restaurant ID input example
Numeric IDs are resolved from the embedded restaurant cards on the supplied discovery pages.
{"restaurantIds": ["21913226"],"discoveryUrls": [{ "url": "https://www.zomato.com/bangalore/restaurants" }],"maxItems": 10}
If an ID is not present on the supplied listing page, provide the restaurant URL or another listing page containing that ID. The Actor will not silently substitute another restaurant.
Low-rating monitoring example
{"startUrls": [{"url": "https://www.zomato.com/bangalore/cbd-central-bar-district-mg-road-bangalore/reviews"}],"minRating": 1,"maxRating": 2,"maxItems": 100,"maxReviewsPerRestaurant": 100}
Schedule this input and compare reviewId against your previous dataset to identify newly observed low-rated feedback.
Output example
The default dataset contains one object per review. This representative example is anonymized; live output contains public source values.
{"reviewId": "500123456","reviewText": "Example review text about the dining experience.","rating": 2,"ratingLabel": "Poor","experience": "dining_order","reviewDate": "2025-01-15","reviewDateLabel": "2 days ago","reviewerId": "12345678","reviewerName": "Example Reviewer","reviewerProfileUrl": "https://www.zomato.com/users/example-reviewer-12345678","likeCount": 1,"commentCount": 0,"restaurantId": "20012345","restaurantName": "Example Restaurant","restaurantUrl": "https://www.zomato.com/bangalore/example-restaurant/reviews","restaurantCuisines": ["North Indian", "Chinese"],"restaurantRating": 4.3,"restaurantReviewCount": 1200,"sourcePage": 1,"scrapedAt": "2025-01-15T12:00:00.000Z"}
How pagination and limits work
Zomato currently exposes five reviews per public reviews page. The Actor requests pages in recent-first order and stops when any of these conditions is reached:
maxItemsis reached across the run;maxReviewsPerRestaurantis reached for the current restaurant;maxPagesPerRestaurantis reached;- Zomato reports the last available page;
- no review entity section remains.
Filters are applied before a record is saved. A restrictive rating range may require more source pages to collect the requested number of matching reviews.
How much does it cost to scrape Zomato restaurant reviews?
This Actor uses pay-per-event pricing:
- Start: $0.025 once per run.
- Zomato review: tiered per saved review. The BRONZE price is $0.001592 per review, with lower rates on higher plans.
Examples at BRONZE pricing:
| Saved reviews | Approximate Actor charge |
|---|---|
| 10 | $0.04092 |
| 100 | $0.18420 |
| 1,000 | $1.61700 |
Only accepted dataset rows trigger the review event. Invalid, duplicate, filtered-out, or failed records are not charged as review items. Platform compute and proxy usage may be billed separately according to your Apify plan and active pricing configuration.
Schedule recurring reputation analysis
- Save a Task with stable restaurant URLs and rating filters.
- Add a daily or weekly schedule.
- Export the default dataset or trigger a webhook when each run finishes.
- Upsert records into your database using
reviewIdas the source key. - Compare first-seen timestamps and rating changes in your own history table.
Each run is a current public snapshot. The Actor does not maintain a cross-run database, so your destination should store history when change tracking matters.
Export to spreadsheets and data pipelines
From the dataset page, export the review rows as JSON, CSV, Excel, XML, or RSS. You can also connect the run to:
- Google Sheets for a lightweight review inbox;
- webhooks for immediate downstream processing;
- Make or Zapier for no-code routing;
- cloud object storage or a warehouse for recurring analysis;
- language models for summarization or theme extraction.
Use stable source IDs rather than review text as the deduplication key.
Run through the Apify API with cURL
curl -X POST \"https://api.apify.com/v2/acts/automation-lab~zomato-restaurant-reviews-scraper/runs?token=$APIFY_TOKEN" \-H "Content-Type: application/json" \-d '{"startUrls": [{"url": "https://www.zomato.com/bangalore/cbd-central-bar-district-mg-road-bangalore/reviews"}],"maxItems": 25}'
The response contains the run ID. Fetch dataset items after the run reaches SUCCEEDED.
Run with JavaScript
import { ApifyClient } from 'apify-client';const client = new ApifyClient({ token: process.env.APIFY_TOKEN });const run = await client.actor('automation-lab/zomato-restaurant-reviews-scraper').call({startUrls: [{ url: 'https://www.zomato.com/bangalore/cbd-central-bar-district-mg-road-bangalore/reviews' },],maxItems: 25,});const { items } = await client.dataset(run.defaultDatasetId).listItems();console.log(items);
Run with Python
import osfrom apify_client import ApifyClientclient = ApifyClient(os.environ['APIFY_TOKEN'])run = client.actor('automation-lab/zomato-restaurant-reviews-scraper').call(run_input={'startUrls': [{'url': 'https://www.zomato.com/bangalore/cbd-central-bar-district-mg-road-bangalore/reviews'}],'maxItems': 25,})for item in client.dataset(run['defaultDatasetId']).iterate_items():print(item)
Use with Apify MCP
Add the Actor to Claude Code:
claude mcp add --transport http apify \"https://mcp.apify.com?tools=automation-lab/zomato-restaurant-reviews-scraper"
Claude Desktop, Cursor, and VS Code can use this equivalent MCP configuration:
{"mcpServers": {"apify": {"url": "https://mcp.apify.com?tools=automation-lab/zomato-restaurant-reviews-scraper"}}}
Example prompts:
- “Run the Zomato Restaurant Reviews Scraper for this restaurant URL and return the 20 latest reviews.”
- “Collect one- and two-star reviews for these Zomato restaurants and summarize recurring complaints.”
- “Export reviews for restaurant ID 21913226 using the Bengaluru listing page.”
Proxy behavior and reliability
Zomato may block repeated direct requests. The default input uses Apify's SHADER datacenter proxy group because it returned complete public review state during validation at lower cost than residential traffic.
The Actor reuses one proxy identity during a run, retries only transient network, 408, 429, and selected 5xx failures, and stops after three attempts. Residential fallback is not automatic. This prevents an unexpected higher-cost mode from being triggered silently.
If you override the proxy configuration and extraction fails, restore the default setting before retrying.
Limitations
- Only public, anonymously visible Zomato restaurant review pages are supported.
- Numeric IDs must be present on a supplied
discoveryUrlslisting page; a URL is more direct. - Zomato currently displays some dates as relative labels. Normalized dates for those values are approximate.
- Public field availability varies by review. Photos, tags, responses, follower counts, or text may be absent.
- The Actor collects dining-review pagination exposed by the public page; delivery-only or login-only feedback may not be available.
- Source layout or anti-bot changes can temporarily interrupt extraction.
- The Actor does not provide sentiment scores, translations, alerts, or historical storage.
Responsible use and legality
This Actor extracts publicly visible information. Your use must comply with applicable laws, Zomato's terms, Apify's Acceptable Use Policy, and privacy obligations relevant to your jurisdiction and purpose.
Do not use reviewer data for harassment, identity enrichment, discriminatory profiling, spam, or decisions that materially affect individuals. Collect only the fields and volume needed for a legitimate purpose. Respect deletion, retention, and access-control requirements in downstream systems.
FAQ and troubleshooting
Why did the Actor say no reviews matched?
Check that the restaurant has public dining reviews and that minRating and maxRating are not too restrictive. Enable includeEmptyText only when rating-only entries are useful.
Why could a restaurant ID not be resolved?
The numeric ID was not present in the supplied listing page's embedded restaurant cards. Paste the direct restaurant URL or provide another public Zomato listing page containing that restaurant.
Why did a public page fail?
Restore the default SHADER proxy configuration. Confirm that the URL opens a restaurant rather than a city, search, profile, or 404 page. The Actor intentionally fails when structured review state is missing.
Can I scrape multiple restaurants?
Yes. Add multiple entries to startUrls. maxItems is shared across the run, while maxReviewsPerRestaurant applies separately to each restaurant.
How do I find new reviews between runs?
Store prior dataset rows and compare reviewId. A review ID first seen in the current run is a newly observed record in your workflow.
Related Actor
Need restaurant discovery before collecting reviews? Use Zomato Restaurant Search Scraper to export public restaurant IDs, names, ratings, cuisines, localities, and profile URLs from Zomato city and cuisine pages.