# Zomato Restaurant Reviews Scraper (`factden/zomato-restaurant-reviews-scraper`) Actor

Scrape Zomato restaurant reviews at scale - ratings, full review text, reviewer, owner responses, plus a per-restaurant lead record (phone, address, geo, cuisines, cost, rating). Paste restaurant URLs, city/locality listing URLs, or IDs. Filter by rating/date; export JSON/CSV.

- **URL**: https://apify.com/factden/zomato-restaurant-reviews-scraper.md
- **Developed by:** [Factden](https://apify.com/factden) (community)
- **Categories:** E-commerce, Lead generation, AI
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 1 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.00 / 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

## Zomato Restaurant Reviews Scraper

**Scrape Zomato restaurant reviews at scale** - star **ratings** (/5), full **review text**, **reviewer**
details and **owner responses** - plus a per-restaurant **lead record** (**phone number**, full **address**,
**GPS coordinates**, **cuisines**, **cost for two**, aggregate **rating**). Pick a **mode**: **Reviews** (paste
restaurant page URLs or bare IDs to get every review + a lead record for each) or **Discovery** (paste a
**city/locality listing URL** to pull a **lead record for every restaurant** in that area). Every review also
ships as an **LLM-ready markdown** block. **No login, no Zomato API key.**

Runs on [Apify](https://apify.com): scheduling, REST API, proxy rotation, monitoring, and one-click export to
**JSON, CSV, Excel or HTML**.

https://www.youtube.com/watch?v=0U-MXEz\_uiM

### What does Zomato Restaurant Reviews Scraper do?

Choose a **mode** and give it the matching input:

- **Reviews mode** - paste any [Zomato](https://www.zomato.com) restaurant URL or a bare restaurant ID. Returns
  every **review** plus a **lead record** for each restaurant.
- **Discovery mode** - pick a **city** (and optional **cuisine**) from the dropdowns, or paste a city/locality
  listing URL. Returns a **lead record for every restaurant** in that area (name, phone, address, geo, cuisines,
  cost, rating). Discovery is leads-only and does not scrape reviews - feed the restaurants it finds into
  Reviews mode when you want their reviews.

Output datasets:

- **Reviews** (Reviews mode) - one row per review: rating (/5), full text, reviewer name & profile, the
  restaurant's owner response, a short permalink, and an approximate date.
- **Restaurant leads** (both modes) - one record per restaurant: name, **phone number(s)**, full **address**,
  **latitude/longitude**, **cuisines**, **cost for two**, aggregate rating, total review count and timings.

![Zomato reviews output: rating, review text, reviewer, owner response](https://raw.githubusercontent.com/factden/apify-actor-assets/main/zomato-restaurant-reviews-scraper/02-reviews-output.png)

![Zomato restaurant leads: phone, address, geo, cuisines, cost for two, rating](https://raw.githubusercontent.com/factden/apify-actor-assets/main/zomato-restaurant-reviews-scraper/04-leads-output.png)

It works across **India, UAE and every other market Zomato covers**, and can **discover** every restaurant in
a locality (up to 200 per listing URL) as a ready-to-import lead list.

### Why scrape Zomato reviews?

- **Reputation & sentiment analysis** - track ratings, complaints and owner responses across your outlets or
  your competitors.
- **Restaurant lead lists & market mapping** - phone, address and GPS for every restaurant in a city or
  cuisine, ready for CRM import.
- **AI / RAG pipelines** - every review ships as a self-contained markdown block for embeddings and LLM
  ingestion.
- **Competitive & location intelligence** - cost-for-two, cuisines and rating distribution per locality.

### How to scrape Zomato restaurant reviews

1. Pick a **Mode**. For **Reviews**, paste restaurant URLs
   (`https://www.zomato.com/ncr/warehouse-cafe-connaught-place-new-delhi`) or bare IDs like `301605` into
   **Restaurant URLs or IDs**. For **Discovery**, pick a **City** (and optionally a **Cuisine**) from the
   dropdowns, or paste your own locality listing URL (`https://www.zomato.com/ncr/connaught-place-restaurants`)
   into **City / locality listing URLs (advanced)**, and set **Max restaurants per listing**.
2. In **Reviews** mode, set **Max reviews per restaurant** and any optional **rating** or **date** filter (or
   turn **Scrape reviews** off for a leads-only pass over your pasted URLs). In **Discovery** mode these are
   ignored - it always returns one lead per restaurant, no reviews.
3. Click **Start**, then download the results as JSON, CSV or Excel - or pull them from the Apify API.

![Zomato scraper input: pick a mode, city and cuisine, or paste restaurant URLs](https://raw.githubusercontent.com/factden/apify-actor-assets/main/zomato-restaurant-reviews-scraper/01-input-form.png)

### Input

| Field | Description |
|---|---|
| `mode` | `reviews` (default) or `discovery`. Picks which inputs below are used. |
| `startUrls` | **Reviews mode.** Restaurant page URLs or bare restaurant IDs. |
| `city` | **Discovery mode.** Pick a city; the actor builds and paginates its Zomato restaurants listing. |
| `cuisine` | **Discovery mode.** Optional: narrow the city search to one cuisine. |
| `listingUrls` | **Discovery mode (advanced).** Your own city/locality/collection listing URLs (used with or instead of `city`). |
| `maxRestaurants` | Discovery mode: how many restaurants to expand and scrape per listing (the actor paginates the listing to reach this many, up to 200). |
| `maxReviews` | Max reviews per restaurant (newest-first). Defaults to 200. |
| `includeReviews` | Reviews mode: turn off for a leads-only run (no reviews, no review charges). Discovery is always leads-only. |
| `sortBy` | Output order: newest / oldest / highest / lowest rating. |
| `fromDate` | Keep only reviews on or after this day (approximate; stops early once older reviews are reached). |
| `minRating` / `maxRating` | Keep reviews within a 1-5 rating range. |
| `proxyConfiguration` | Proxy settings. Defaults to Apify **Residential (India)** because Zomato blocks datacenter IPs; switch to datacenter to cut cost if you prefer. |

### Output

The **default dataset** holds the run's main results: in **Reviews mode**, one row per review (also mirrored to
the **reviews** dataset); in **Discovery mode**, one **restaurant lead** per restaurant (also mirrored to the
**restaurants** dataset). In Reviews mode the per-restaurant lead record is in the **restaurants** dataset.
Download in JSON, HTML, CSV or Excel, or via the API.

```json
{
  "restaurantId": 301605,
  "restaurantName": "Warehouse Cafe",
  "reviewId": "504560717",
  "rating": 4,
  "ratingType": "DINING",
  "reviewText": "Great ambience and food, loved the pizza and the cocktails ...",
  "timestamp": "17 hours ago",
  "reviewDate": "2026-08-30",
  "reviewerName": "Nitesh Mehra",
  "reviewerProfileUrl": "https://www.zomato.com/users/nitesh-mehra-88230886",
  "ownerResponse": { "text": "Thank you for visiting!", "author": "Warehouse Cafe" },
  "reviewUrl": "https://www.zoma.to/Avnobmn"
}
```

Restaurant lead record:

```json
{
  "restaurantId": 301605,
  "restaurantName": "Warehouse Cafe",
  "restaurantUrl": "https://www.zomato.com/ncr/warehouse-cafe-connaught-place-new-delhi",
  "phones": ["+919953033368", "+919999537128"],
  "address": "D 19/20, D Block, Inner Circle, Connaught Place, New Delhi",
  "locality": "Connaught Place, New Delhi",
  "city": "New Delhi",
  "zipcode": "110001",
  "latitude": 28.6337308501,
  "longitude": 77.2210077569,
  "cuisines": ["North Indian", "Italian", "Asian"],
  "costForTwo": "₹3,000 for two people (approx.) with alcohol",
  "rating": 4.2,
  "reviewCount": 15400
}
```

### Data fields

| Field | Description |
|---|---|
| `rating` / `ratingType` | Review rating (1-5) and the experience it is for (DINING / DELIVERY). |
| `reviewText` | Full review body. |
| `timestamp` / `reviewDate` | Relative timestamp as shown + an approximate ISO date. |
| `reviewerName` / `reviewerProfileUrl` | Reviewer identity. |
| `ownerResponse` | Restaurant/management reply `{text, author}`. |
| `commentCount` | Number of comments on the review. |
| `phones` / `address` / `latitude` / `longitude` / `zipcode` | Restaurant contact + location (leads). |
| `cuisines` / `costForTwo` / `rating` / `reviewCount` / `timing` | Restaurant profile (leads). |
| `markdownContent` | LLM-ready per-review markdown block. |

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

This actor uses **pay-per-event** pricing: a small **start fee** per run, plus a charge per **review** delivered
and per **restaurant lead** record. On the **Free** plan it is $0.005 start + $0.005 per review + $0.005 per
lead; **per-event rates drop on higher Apify plans** (as low as $0.002 each). You are never charged for a review
that is filtered out or a lead that could not be fetched. Turn **Scrape reviews** off for a cheaper, leads-only
run. See the **Pricing** tab for current rates. On the Apify Free plan you get monthly usage credits to try it
at no cost.

### Tips

- **Discovery mode**: set **Mode** to Discovery, pick a **City** (and optional **Cuisine**), or paste a
  locality URL (e.g. `.../ncr/connaught-place-restaurants`), and set **Max restaurants** to pull an entire
  area's restaurant **leads** (name/phone/address/geo/cuisine/cost/rating), up to 200 per listing. Discovery
  does not scrape reviews - feed the restaurants it finds into Reviews mode for that.
- **Cheap leads run**: set **Scrape reviews** off to collect only phone/address/geo/cuisine/cost per
  restaurant.
- **Recent reviews only**: use **Reviews from** to stop early once older reviews are reached (faster + cheaper).
- **Schedule** the actor to track new reviews over time.

### FAQ

- **Do I need a Zomato account or API key?** No.
- **Can it scrape a whole city?** Yes - in Discovery mode pick a **City** (and optional **Cuisine**), or paste
  a listing URL. It returns a lead for every restaurant (up to 200 per listing; use several cuisines or
  localities to cover more). For their reviews, run those restaurants through Reviews mode.
- **Is there a restaurant email?** No - Zomato does not publish restaurant emails; phone, address and GPS are
  the available contact fields.
- **Are review dates exact?** Zomato shows relative timestamps ("6 months ago"), so `reviewDate` is an
  approximation computed at scrape time; the exact string is kept in `timestamp`.
- **Can I call it from an AI agent / MCP?** Yes - it is a standard Apify actor with a typed input schema, so
  agents and the Apify MCP server can run it directly.
- **Is scraping Zomato legal?** This tool collects only publicly available data. You are responsible for how
  you use it and for complying with Zomato's terms and applicable law.

### Related FactDen actors

- [Google Hotels Scraper](https://apify.com/factden/google-hotels-scraper)
- [Agoda Hotel Reviews Scraper](https://apify.com/factden/agoda-hotel-reviews-scraper)
- [TripAdvisor Reviews Scraper](https://apify.com/factden/tripadvisor-reviews-scraper)
- [Expedia Hotel Reviews Scraper](https://apify.com/factden/expedia-hotel-reviews-scraper)
- [G2 Reviews Scraper](https://apify.com/factden/g2-reviews-scraper)

### Support

Questions, a missing field, or a bug? Open the **Issues** tab on this actor's page - we read every one. If this
actor helps your work, a ⭐ review on the Apify Store means a lot 🙏

### Changelog

- **2026-08-30** - Initial release: reviews + per-restaurant leads + city/locality discovery, multi-event
  pricing, LLM-ready markdown, JSON/CSV/Excel export.

# Actor input Schema

## `mode` (type: `string`):

**Reviews** (default): paste restaurant page URLs or bare IDs below and get every review + a lead record for each. **Discovery**: paste a city/locality/collection listing URL and the actor finds every restaurant on it, then scrapes each one's reviews + lead record. Only the selected mode's input is used.

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

**Reviews mode.** Paste one input per line: a **restaurant** page URL (e.g. `https://www.zomato.com/ncr/warehouse-cafe-connaught-place-new-delhi`) or a bare numeric **restaurant ID** (e.g. `301605`).

## `city` (type: `string`):

**Discovery mode.** Pick a city and the actor builds its Zomato restaurants listing and paginates it for you. For a specific locality, collection, or a city not listed here, leave this empty and paste a URL into **City / locality listing URLs** below instead.

## `cuisine` (type: `string`):

Discovery mode: narrow a City search to one cuisine (ignored if City is empty). Leave as All cuisines for every restaurant.

## `listingUrls` (type: `array`):

**Discovery mode, optional override.** Paste one Zomato **listing** URL per line for full control: a locality/city restaurants page (e.g. `https://www.zomato.com/ncr/connaught-place-restaurants`), a `/dine-out`, `/delivery`, `/search` or `/collections` page. Each listing is paginated and a **lead record** (name, phone, address, geo, cuisines, cost, rating) is produced for every restaurant on it, up to Max restaurants. Used together with City if both are set.

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

In Discovery mode, how many restaurants to expand and scrape from each listing URL (the actor paginates the listing to reach this many). Ignored in Reviews mode.

## `maxReviews` (type: `integer`):

Reviews mode only. How many reviews to pull per restaurant (fetched newest-first). Set to 0, or turn Scrape reviews off, for a leads-only run. Lower this to control cost and run time.

## `includeReviews` (type: `boolean`):

Reviews mode only. Turn OFF for a **leads-only** run over your pasted restaurant URLs: just the lead record (name, phone, address, geo, cuisines, cost, rating), no reviews (skips all review requests and review charges). Discovery mode is always leads-only.

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

Output order of the returned reviews. Reviews are fetched newest-first from the source; `Highest rating` / `Lowest rating` reorder the retrieved set (not a global top-N across the whole restaurant).

## `fromDate` (type: `string`):

Keep only reviews on or after this day, and stop paginating once older reviews are reached (faster and cheaper). Zomato reviews carry a relative timestamp (e.g. `6 months ago`), so the date is approximate. Leave empty to fetch the newest reviews with no date bound.

## `minRating` (type: `integer`):

Keep only reviews with a rating at or above this value. Zomato ratings are on a 1-5 scale.

## `maxRating` (type: `integer`):

Keep only reviews with a rating at or below this value. Zomato ratings are on a 1-5 scale.

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

Proxy settings. Zomato is Akamai-fronted and blocks datacenter IPs intermittently, so this defaults to **Apify Residential (India)** for reliable results. You can switch to datacenter to cut proxy cost, but expect occasional blocks.

## Actor input object example

```json
{
  "mode": "reviews",
  "startUrls": [
    "https://www.zomato.com/ncr/warehouse-cafe-connaught-place-new-delhi"
  ],
  "city": "",
  "cuisine": "",
  "maxRestaurants": 200,
  "maxReviews": 200,
  "includeReviews": true,
  "sortBy": "newest",
  "minRating": 1,
  "maxRating": 5,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "IN"
  }
}
```

# Actor output Schema

## `reviews` (type: `string`):

One row per restaurant review (restaurant context merged onto each row) with rating, full text, reviewer, owner response and an LLM-ready markdownContent block.

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

One lead record per restaurant with name, phone, full address, coordinates, cuisines, cost for two, aggregate rating, total review count and how many reviews were extracted.

# 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": [
        "https://www.zomato.com/ncr/warehouse-cafe-connaught-place-new-delhi"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("factden/zomato-restaurant-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": ["https://www.zomato.com/ncr/warehouse-cafe-connaught-place-new-delhi"] }

# Run the Actor and wait for it to finish
run = client.actor("factden/zomato-restaurant-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": [
    "https://www.zomato.com/ncr/warehouse-cafe-connaught-place-new-delhi"
  ]
}' |
apify call factden/zomato-restaurant-reviews-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,factden/zomato-restaurant-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/siKCDNRhoxJiFWSun/builds/E5tm8Bqp44b7w15QF/openapi.json
