Zomato Restaurants Scraper avatar

Zomato Restaurants Scraper

Pricing

Pay per event

Go to Apify Store
Zomato Restaurants Scraper

Zomato Restaurants Scraper

Scrape Zomato (zomato.com) restaurant listings by city+cuisine or city+locality listing pages — name, rating, votes, locality, cuisines, and price for two, one row per restaurant. Covers India/APAC's leading restaurant-discovery platform for site-selection and dining competitive intel.

Pricing

Pay per event

Rating

0.0

(0)

Developer

DevilScrapes

DevilScrapes

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

an hour ago

Last modified

Categories

Share


🎯 What this scrapes

Point this Actor at one or more Zomato city+cuisine or city+locality listing URLs (e.g. zomato.com/bangalore/pizza) and it returns one clean row per restaurant — name, canonical URL, aggregate rating, vote count, locality, cuisines, and price for two. Ratings and vote counts arrive parsed as real numbers (not raw "4.3" / "2,664" strings), and every row is stamped with the listing URL it came from plus an ISO-8601 scrape timestamp, so scheduled runs diff cleanly. Built on curl-cffi with browser TLS impersonation against Zomato's own embedded page data — no fragile CSS-selector scraping.

🔥 What we handle for you

  • 🧭 Fault-isolated multi-URL crawling — one bad listing URL never aborts the batch; each city+cuisine or city+locality page is fetched and parsed independently.
  • 🧮 Numbers you can compute on — vote counts and ratings arrive as clean int/float, not "2,664" strings scraped raw off the page.
  • 🛡️ Browser fingerprint rotationcurl-cffi impersonates real Chrome/Firefox TLS handshakes on every request, so the crawl holds up if Zomato ever tightens its defenses.
  • 🔁 Retries with backoff on 408/429/5xx — up to 5 attempts per page, Retry-After honoured.
  • 🧊 Clean, typed dataset rows — Pydantic-validated, ISO-8601 timestamps, stable restaurant URLs, JSON/CSV/Excel export straight from the Apify Console.
  • 💰 Pay-Per-Event pricing — you only pay for restaurants that actually land in your dataset.

💡 Use cases

  • Franchise and site-selection research — compare restaurant density, ratings, and price tier across neighborhoods before picking a location.
  • Competitive intel for food-delivery and hospitality platforms — track how rivals are rated and priced, city by city.
  • Local-market research — build a structured dataset of restaurants, cuisines, and price points for a city or cuisine segment.
  • Scheduled monitoring — diff rating and vote-count changes across repeat runs.

⚙️ How to use it

  1. Click Try for free at the top of the page.
  2. Fill in the input form — most fields have sensible defaults.
  3. Click Start. Output streams into the run's dataset.
  4. Export from Storage → Dataset as JSON, CSV, or Excel — or fetch via the API.

📥 Input

FieldTypeRequiredDefaultNotes
listingUrlsarrayyes['https://www.zomato.com/bangalore/pizza', 'https://www.zomato.com/mumbai/andheri-west-restaurants']Zomato city+cuisine or city+locality listing page URLs to scrape, e.g.…
maxResultsPerUrlintegerno30Cap on the number of restaurants emitted per input listing URL.
proxyConfigurationobjectno{'useApifyProxy': True}Apify Proxy spec. Standard (datacenter-tier) default — RESIDENTIAL not required given confirmed clean reach to…

Example input

{
"listingUrls": [
"https://www.zomato.com/bangalore/pizza",
"https://www.zomato.com/mumbai/andheri-west-restaurants"
],
"maxResultsPerUrl": 5,
"proxyConfiguration": {
"useApifyProxy": true
}
}

📤 Output

Every row is one dataset item.

FieldTypeNotes
namestringRestaurant name from the embedded state blob.
urlstringCanonical restaurant detail-page URL (blob or JSON-LD fallback).
restaurant_id['string', 'null']Internal ID/slug if present in the blob.
aggregate_rating['number', 'null']Parsed rating, e.g. 4.3 (blob ships it as a string).
votes['integer', 'null']Parsed vote count, thousands separators stripped (e.g. '2,664' -> 2664).
locality['string', 'null']locality.text from the blob, e.g. 'Brigade Road, Bangalore'.
citystringParsed from the input listingUrls path segment.
cuisinesarrayCuisine tags, only if present in the blob for that record. Empty list is valid.
price_for_two['integer', 'null']Only if present in the blob.
source_listing_urlstringWhich listingUrls entry produced this row.
scraped_atstringISO 8601 UTC timestamp at row creation.

Example output

{
"name": "Jamie Oliver's Pizzeria",
"url": "https://www.zomato.com/bangalore/jamie-olivers-pizzeria-whitefield-bangalore",
"restaurant_id": "jamie-olivers-pizzeria-whitefield-bangalore",
"aggregate_rating": 4.3,
"votes": 2664,
"locality": "Brigade Road, Bangalore",
"city": "Bangalore",
"cuisines": [
"Pizza",
"Italian"
],
"price_for_two": 1200,
"source_listing_url": "https://www.zomato.com/bangalore/pizza",
"scraped_at": "2026-09-15T12:00:00+00:00"
}

💰 Pricing

Pay-Per-Event — you pay only when these events fire:

EventUSDWhat it is
actor-start$0.2One-off warm-up charge per run
restaurant-scraped$0.004PPE event

Example: 1 000 restaurants at the rates above ≈ $4.20. No subscription, no minimum, no card to start — Apify gives every new account $5 of free credit.

🚧 Limitations

  • v1 parses only the first page load's embedded data per input listing URL — no infinite-scroll pagination follow. Add more listingUrls (more cities, cuisines, or localities) to scale coverage.
  • Restaurant detail-page fields (menus, photos, review text) are out of scope in v1 — only listing-page fields ship.
  • Order/delivery-flow data, table-booking availability, and any authenticated/logged-in view are out of scope.

❓ FAQ

Does this follow pagination beyond the first page load?

No — v1 parses the restaurants embedded in a listing page's first load only (Zomato's listing pages are JS-paginated/infinite-scroll). Point the Actor at more listingUrls — more cities, cuisines, or localities — to scale coverage instead.

What listing URLs are supported?

Any zomato.com city+cuisine or city+locality listing page, e.g. https://www.zomato.com/bangalore/pizza or https://www.zomato.com/mumbai/andheri-west-restaurants. Individual restaurant detail-page URLs are not supported in v1.

Why are some fields null?

restaurant_id, aggregate_rating, votes, locality, and price_for_two are only populated when Zomato's page includes them for that restaurant. A missing value is reported as null, never guessed.

Is this legal?

We only fetch content Zomato makes publicly available on its listing pages. Respect Zomato's own terms of service before using output commercially.

💬 Your feedback

Spotted a bug, hit a weird edge case, or need a new field? Open an issue on the Actor's Issues tab on Apify Console — we ship fixes weekly and we read every report.