---
title: "Yelp scraper"
description: "Scrape Yelp business pages as JSON: name, rating, price range, phone, address, hours, categories and photos. One API request from Python, Node.js, the CLI or MCP."
canonical: https://www.zenrows.com/scrape/yelp
updated: 2026-10-20
---

# Yelp scraper

The Zenrows Yelp scraper turns any Yelp business URL into structured JSON: business name, Yelp ID, rating, price range, phone, website, street address, coordinates, opening hours, categories, amenities, vibe attributes and photos with captions. You send the URL, Fetch in Adaptive Stealth Mode opens the page, and Extract returns the fields. Run it from an API call, the CLI or an AI agent.

- Site: yelp.com
- Returns: Local businesses, ratings, hours, categories and photos

## Run it: one Yelp business in, JSON out

```json Input
{
  "url": "https://www.yelp.com/biz/tonys-pizza-napoletana-san-francisco",
  "mode": "auto",
  "extract": "auto"
}
```

```json Output
{
  "business": {
    "name": "Tony's Pizza Napoletana",
    "yelp_id": "mSMZJj2pFvttWLpcDmgrEA",
    "rating": 4.2,
    "price_range": "$$",
    "phone": "(415) 835-9888",
    "is_claimed": true,
    "health_score": "Pass",
    "yelp_url": "https://www.yelp.com/biz/tonys-pizza-napoletana-san-francisco"
  },
  "categories": [
    { "name": "Pizza" },
    { "name": "Italian" },
    { "name": "Cocktail Bars" }
  ],
  "location": {
    "street_address": "1570 Stockton St",
    "city": "San Francisco",
    "state": "CA",
    "postal_code": "94133",
    "country": "US",
    "latitude": 37.800389,
    "longitude": -122.409033
  },
  "hours": [
    { "day": "Mon", "hours_range": "12:00 PM - 10:00 PM" },
    { "day": "Fri", "hours_range": "12:00 PM - 11:00 PM" }
  ]
}
```

Request and output of a live call to a Yelp business page on Oct 20, 2026, trimmed for length. A field is returned when the page shows it.

## What data can you scrape from Yelp?

A Yelp business page comes back as the business, its location, hours, categories, amenities, vibe and photos. These are the fields teams use most, with the path where each lives in the JSON.

| Field | What it holds | Example |
|---|---|---|
| `business.name` | Business name | `Tony's Pizza Napoletana` |
| `business.yelp_id` | Yelp's business ID, stable when the URL changes | `mSMZJj2pFvttWLpcDmgrEA` |
| `business.rating` | Star rating out of 5 | `4.2` |
| `business.price_range` | Price level from `$` to `$$$$` | `$$` |
| `business.phone` | Public business phone number | `(415) 835-9888` |
| `business.website_url` | Link to the business website, through Yelp's redirect | `/biz_redir?url=http%3A%2F%2Fwww.tonyspizzanapoletana.com…` |
| `business.is_claimed` | Whether the owner has claimed the page | `true` |
| `business.health_score` | Health inspection result, where Yelp shows one | `Pass` |
| `business.specialties_description` | The owner's description of the business | `Tony's Pizza Napoletana is a state of the art full service restaurant…` |
| `location.street_address` | Street address, with `city`, `state`, `postal_code` and `country` next to it | `1570 Stockton St` |
| `location.latitude`, `location.longitude` | Coordinates | `37.800389, -122.409033` |
| `hours[]` | Opening hours per day | `{ "day": "Mon", "hours_range": "12:00 PM - 10:00 PM" }` |
| `categories[].name` | Yelp categories | `Pizza` |
| `amenities[].label` | Services the business offers | `Takes reservations` |
| `vibe_attributes[].label` | Atmosphere and audience tags | `Good for groups` |
| `photos[]` | Photo URL, thumbnail and caption | `{ "caption": "… Il Padrino Sicilian pizza …" }` |

## How to scrape Yelp with Zenrows

1. **Create a free Zenrows account** and copy your API key from the dashboard.
2. **Pick the business URL.** Yelp business pages follow `https://www.yelp.com/biz/<name>-<city>`, with a number at the end when a name repeats in a city, as in `golden-boy-pizza-san-francisco-5`.
3. **Send it with the default configuration**: Adaptive Stealth Mode to open the page and Extract to return the fields.
4. **Read `parsed`** from the response. To keep only some fields, list them with their paths and the response returns just those.
5. **Send your list of businesses to Batch** once one URL returns what you need.

```python Python
# pip install requests
import requests

params = {
    "apikey": "YOUR_ZENROWS_API_KEY",
    "url": "https://www.yelp.com/biz/tonys-pizza-napoletana-san-francisco",
    "mode": "auto",          # Adaptive Stealth Mode
    "extract": "auto",       # structured JSON
}
response = requests.get("https://api.zenrows.com/v1/", params=params, timeout=180)
response.raise_for_status()

data = response.json()["parsed"]
biz, loc = data["business"], data["location"]
print(biz["name"], biz["rating"], biz["price_range"], biz["phone"])
print(loc["street_address"], loc["city"], loc["state"], loc["postal_code"])
print([c["name"] for c in data["categories"]])
```

```javascript Node.js
// Node 18+ (built-in fetch)
const params = new URLSearchParams({
  apikey: "YOUR_ZENROWS_API_KEY",
  url: "https://www.yelp.com/biz/tonys-pizza-napoletana-san-francisco",
  mode: "auto",
  extract: "auto",
});

const response = await fetch(`https://api.zenrows.com/v1/?${params}`, {
  signal: AbortSignal.timeout(180_000),
});
if (!response.ok) throw new Error(`${response.status}: ${await response.text()}`);

const { parsed } = await response.json();
console.log(parsed.business.name, parsed.business.rating);
console.table(parsed.hours);
```

```bash cURL
curl "https://api.zenrows.com/v1/?apikey=YOUR_ZENROWS_API_KEY&url=https%3A%2F%2Fwww.yelp.com%2Fbiz%2Ftonys-pizza-napoletana-san-francisco&mode=auto&extract=auto"

# Only the fields you need
curl "https://api.zenrows.com/v1/?apikey=YOUR_ZENROWS_API_KEY&url=https%3A%2F%2Fwww.yelp.com%2Fbiz%2Ftonys-pizza-napoletana-san-francisco&mode=auto&extract=auto&extract_fields=business.name%2Cbusiness.rating%2Cbusiness.phone%2Clocation.street_address%2Chours"
```

```python Python SDK
# pip install zenrows
from urllib.parse import parse_qs, urlparse
from zenrows import ZenRowsClient

client = ZenRowsClient("YOUR_ZENROWS_API_KEY")
response = client.get(
    "https://www.yelp.com/biz/golden-boy-pizza-san-francisco",
    params={"mode": "auto", "extract": "auto"},
)
biz = response.json()["parsed"]["business"]
redirect = biz.get("website_url") or ""
website = parse_qs(urlparse(redirect).query).get("url", [None])[0]   # the real site behind Yelp's redirect
print(biz["name"], biz["rating"], website)
```

## Input

The scraper takes one Yelp URL per request, plus the options below. A Batch job applies the same parameters to every task, so the input for a thousand businesses is a list of URLs with these settings.

| Parameter | Type | Default | Description |
|---|---|---|---|
| `url` | string | required | A Yelp business page (`/biz/<name>-<city>`), on yelp.com or a Yelp country site |
| `mode` | string | `auto` | Adaptive Stealth Mode: starts with the lightest setup and adds rendering and protected-site handling only when Yelp needs them |
| `extract` | string | `auto` | Returns the page's fields as JSON in `parsed`, next to the raw `html` |
| `extract_fields` | string | all fields | Comma-separated paths to keep, such as `business.name,business.rating,hours` |
| `proxy_country` | string | any | Two-letter country code, to see the page as a visitor from that country, for example `ca` for yelp.ca |
| `wait_for` | string | none | A CSS selector to wait for before the page is read |
| `session_id` | integer | none | Keep the same session for up to 10 minutes across several pages of one business |

```json Batch input
{
  "type": "regular",
  "status": "closed",
  "zenrows_params": {
    "mode": "auto",
    "extract": "auto"
  },
  "tasks": [
    { "url": "https://www.yelp.com/biz/tonys-pizza-napoletana-san-francisco", "external_id": "mSMZJj2pFvttWLpcDmgrEA" },
    { "url": "https://www.yelp.com/biz/golden-boy-pizza-san-francisco", "external_id": "golden-boy-north-beach" },
    { "url": "https://www.yelp.com/biz/golden-boy-pizza-san-francisco-5", "external_id": "golden-boy-parkside" }
  ]
}
```

## Output

Every response is JSON with two keys: `html`, the page as Yelp served it, and `parsed`, the structured record. A business page returns the groups below. The sample keeps more of the same live response, including the owner's description, amenities, vibe and photos.

```json Business page
{
  "business": {
    "name": "Tony's Pizza Napoletana",
    "yelp_id": "mSMZJj2pFvttWLpcDmgrEA",
    "rating": 4.2,
    "price_range": "$$",
    "phone": "(415) 835-9888",
    "is_claimed": true,
    "health_score": "Pass",
    "photo_count": 10,
    "logo_url": "https://s3-media0.fl.yelpcdn.com/bphoto/ptCPOJoqVokZW7GmQ5F4NQ/l.jpg",
    "website_url": "/biz_redir?url=http%3A%2F%2Fwww.tonyspizzanapoletana.com&cachebuster=1792462315&website_link_type=website…",
    "specialties_description": "Tony's Pizza Napoletana is a state of the art full service restaurant that offers several styles of pizzas which include Neapolitan, Classic American and Italian, Sicilian, Pizza Romana, Gluten Free and New York, Detroit and St. Louis Style and displays seven different types of pizza ovens…",
    "yelp_url": "https://www.yelp.com/biz/tonys-pizza-napoletana-san-francisco"
  },
  "categories": [
    { "name": "Pizza" },
    { "name": "Italian" },
    { "name": "Cocktail Bars" }
  ],
  "location": {
    "street_address": "1570 Stockton St",
    "city": "San Francisco",
    "state": "CA",
    "postal_code": "94133",
    "country": "US",
    "neighborhood": null,
    "latitude": 37.800389,
    "longitude": -122.409033
  },
  "hours": [
    { "day": "Mon", "hours_range": "12:00 PM - 10:00 PM" },
    { "day": "Tue", "hours_range": "12:00 PM - 10:00 PM" },
    { "day": "Sat", "hours_range": "12:00 PM - 11:00 PM" },
    { "day": "Sun", "hours_range": "12:00 PM - 11:00 PM" }
  ],
  "amenities": [
    { "label": "Takes reservations" },
    { "label": "Offers delivery" },
    { "label": "Offers take-out" }
  ],
  "vibe_attributes": [
    { "label": "Casual" },
    { "label": "Outdoor seating" },
    { "label": "Good for groups" }
  ],
  "photos": [
    {
      "caption": "Tony's Pizza Napoletana - Il Padrino Sicilian pizza - San Francisco, CA",
      "thumbnail_url": "https://s3-media0.fl.yelpcdn.com/bphoto/zEg9dnZ8yfhXrGtsNnpteg",
      "url": "https://s3-media0.fl.yelpcdn.com/bphoto/zEg9dnZ8yfhXrGtsNnpteg/l.jpg"
    }
  ]
}
```

Need a spreadsheet? Flatten `business` and `location` into one row per business with `pd.json_normalize(...)` and write CSV or Excel. Need the page for an LLM? Ask for Markdown instead of JSON.

## Scrape Yelp from your coding agent

Claude Code, Cursor, Codex and any MCP client can scrape Yelp from a prompt.

The agent sends the same Fetch and Extract request a developer would, so it reads the business record above and can compare places for you. Connect the Zenrows MCP server once, or install the CLI and let the agent run it in the terminal.

```bash Connect the MCP server (Claude Code)
claude mcp add zenrows -e ZENROWS_API_KEY=YOUR_ZENROWS_API_KEY -- npx -y @zenrows/mcp
```

```json MCP config (Cursor, Claude Desktop, Windsurf)
{
  "mcpServers": {
    "zenrows": {
      "command": "npx",
      "args": ["-y", "@zenrows/mcp"],
      "env": { "ZENROWS_API_KEY": "YOUR_ZENROWS_API_KEY" }
    }
  }
}
```

```bash Or run the CLI
npx -y @zenrows/cli init
zenrows extract "https://www.yelp.com/biz/tonys-pizza-napoletana-san-francisco"
```

```text Then ask your agent
Use Zenrows to scrape these Yelp pages and return a table with name,
rating, price range, phone, address, categories and Sunday hours:
https://www.yelp.com/biz/tonys-pizza-napoletana-san-francisco
https://www.yelp.com/biz/golden-boy-pizza-san-francisco
```

## Scrape Yelp at scale with Batch and Crawl

**Batch** runs a list of Yelp business URLs as one job, in parallel, with your own ID on each result. Use the Yelp ID or your own location code as the ID, and rerun the job monthly to catch changes in ratings, hours and categories across a market.

**Crawl** follows links from a Yelp page and returns every page it reaches. Start it on a Yelp search for a category and city, keep the links that contain `/biz/`, and it collects the business pages in those results. Send that list to Batch with Extract.

```bash Batch (cURL)
curl -X POST "https://async.api.zenrows.com/v1/jobs" \
  -H "X-API-Key: YOUR_ZENROWS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "regular",
    "status": "closed",
    "zenrows_params": { "mode": "auto", "extract": "auto" },
    "tasks": [
      { "url": "https://www.yelp.com/biz/tonys-pizza-napoletana-san-francisco", "external_id": "mSMZJj2pFvttWLpcDmgrEA" },
      { "url": "https://www.yelp.com/biz/golden-boy-pizza-san-francisco", "external_id": "golden-boy-north-beach" }
    ]
  }'

# Read the results when the job finishes
curl "https://async.api.zenrows.com/v1/jobs/JOB_ID/results?status=successful" \
  -H "X-API-Key: YOUR_ZENROWS_API_KEY"
```

```bash Batch (CLI)
# businesses.jsonl: one {"url": "...", "external_id": "...", "extract": "auto"} per line
zenrows batch create businesses.jsonl --wait
zenrows batch results <job-id> --out yelp-businesses.jsonl
```

```bash Crawl (cURL)
curl -X POST "https://api.zenrows.com/v1/crawls" \
  -H "X-API-Key: YOUR_ZENROWS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://www.yelp.com/search?find_desc=pizza&find_loc=San+Francisco%2C+CA",
    "depth": 1,
    "max_pages": 100,
    "include_patterns": ["/biz/"]
  }'
```

**Scheduled jobs** run the same Batch job on a timetable, on Zenrows' side: every few hours, once a day, at set times on chosen days, or once at a future date. Each run keeps its own results, a webhook can tell your app when a run finishes, and you can pause or resume the schedule at any time, with no cron server to keep alive.

```bash Scheduled job (cURL)
# Runs every day on Zenrows' side; each run keeps its own results
curl -X POST "https://async.api.zenrows.com/v1/jobs" \
  -H "X-API-Key: YOUR_ZENROWS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
      "type": "scheduled",
      "status": "closed",
      "schedule": {
        "rate": {
          "every": 1,
          "unit": "day"
        }
      },
      "zenrows_params": {
        "mode": "auto",
        "extract": "auto"
      },
      "tasks": [
        {
          "url": "https://www.yelp.com/biz/tonys-pizza-napoletana-san-francisco",
          "external_id": "yelp"
        }
      ]
    }'

# Or at set times: "schedule": { "calendar": { "times_of_day": ["09:00"],
#   "cadence": { "weekly": { "days": ["mon", "thu"] } } }, "timezone": "Europe/Madrid" }
```

## What teams do with Yelp data

| Use case | Data they pull | Who runs it |
|---|---|---|
| Local lead lists | Name, category, phone, website, address and claimed status per business | Sales teams selling to restaurants and local services |
| Market mapping | Businesses per category and neighborhood, with coordinates and price level | Franchise, real estate and expansion teams |
| Competitor benchmarking | Rating, price range, hours and amenities of nearby competitors | Restaurant groups and multi-location brands |
| Listing accuracy audits | Hours, phone, address and categories against your own location data | Local SEO agencies and brand teams |
| Food and hospitality research | Categories, vibe attributes, delivery and reservation options by city | Analysts, investors and food service suppliers |
| AI local search assistants | The full business record, or the page as Markdown | AI and product teams |

## Tips for scraping Yelp

- **Watch the number at the end of the URL.** Yelp adds `-2`, `-5` and so on when a name repeats in a city, so `golden-boy-pizza-san-francisco` and `golden-boy-pizza-san-francisco-5` are two locations. Keep the exact URL per location.
- **Key rows on `yelp_id`.** Yelp can rename a business URL; the Yelp ID in `business.yelp_id` stays the same. Use it as your primary key and as the `external_id` in Batch.
- **Decode the website link.** `business.website_url` points to Yelp's redirect. The business's own site is the `url` value in that link's query string, as in the Python SDK example.
- **Collect URLs from search pages.** A Yelp search such as `/search?find_desc=pizza&find_loc=San+Francisco%2C+CA` lists the businesses of a category and city. Crawl it, or page it with `&start=10`, to build your list of `/biz/` URLs.
- **Normalize hours per day.** `hours[]` gives one entry per day with a text range. Split `hours_range` on the dash to get opening and closing times for open-now checks.
- **Use the country sites for other markets.** yelp.ca, yelp.co.uk and yelp.com.au list businesses in those countries with the same page layout. Set the matching country.

## Frequently asked questions

### Is it legal to scrape Yelp?

Collecting public business information from Yelp, such as names, categories, ratings, hours and business phone numbers shown to every visitor, is common practice for market research and local lead lists. Reviews and photos can include personal data about reviewers, which laws such as the GDPR and the CCPA protect, so collect only what you have a legitimate reason to use. Check Yelp's terms for your use case and ask your lawyer if you are unsure.

### Is there an official Yelp API?

Yes. The Yelp Places API, formerly Yelp Fusion, returns business search results and business details with an API key, and up to three review excerpts per business. Its terms cover how the data is displayed and stored, and commercial use runs on paid plans after a trial. Teams that need the full business page, with every amenity, vibe tag and photo caption, use a scraper.

### What Yelp pages can I scrape?

Business pages at yelp.com/biz/<name>-<city> on yelp.com and the Yelp country sites. Search pages work as start points for Crawl to find business URLs.

### How do I scrape Yelp with Python?

Send a GET request to https://api.zenrows.com/v1/ with your API key, the Yelp business URL, Adaptive Stealth Mode and Extract turned on, as in the Python example above. The response's parsed key holds the business as a Python dictionary. The zenrows package on PyPI wraps the same request.

### Can I get phone numbers and addresses from Yelp?

Yes. Each business page returns the public business phone number in business.phone and the full address in location , with street, city, state, postal code, country and coordinates. These are business details the owner publishes, not personal contact data.

### How many Yelp businesses can I scrape?

Send one URL per request, or a whole list as a Batch job that runs the URLs in parallel and keeps your own ID on each result. One Batch job accepts more than 10,000 URLs, sent inline or as a CSV file.

### Can AI agents scrape Yelp with Zenrows?

Yes. Connect the Zenrows MCP server to Claude, Cursor, Codex or any MCP client, or give your agent the Zenrows CLI. Ask for the businesses you want in plain language and the agent calls Fetch and Extract for you.

### Can I scrape Yelp on a schedule?

Yes. Create a scheduled Batch job with your Yelp URLs and the same settings as a single request, and Zenrows runs it on its side: every few hours, once a day, at set times on chosen days, or once at a future date. Each run keeps its own results, a webhook can notify your app when a run finishes, and the schedule can be paused or resumed at any time.

### Which integrations work with the Yelp scraper?

Zenrows works with n8n, Make, Zapier, Clay, Dify, LangChain, LlamaIndex, CrewAI and Mastra, plus the Python, Node.js and Go SDKs and any HTTP client. Send businesses to a CRM, Clay table or Google Sheet from the workflow tool you already use. See the integrations page for the full list. For hotels and restaurants with traveler reviews, see the Tripadvisor scraper .

### What format does the data come in?

JSON by default, with the structured record in parsed and the original page in html . You can also ask for the page as Markdown or plain text, which is what most LLM and RAG pipelines want.

All scrapers: https://www.zenrows.com/scrape. Start free: https://app.zenrows.com/register. Docs: https://docs.zenrows.com
