# Yelp Scraper — businesses, ratings, hours, phone (`xhrdev/yelp-scraper`) Actor

Scrape Yelp business listings past DataDome: name, rating, review count, price range, categories, address, hours, phone and website. Search "what in where" or pass business URLs. No browser. Powered by xhr.dev.

- **URL**: https://apify.com/xhrdev/yelp-scraper.md
- **Developed by:** [xhrdev](https://apify.com/xhrdev) (community)
- **Categories:** Lead generation, Social media
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.10 / 1,000 search results

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

**Scrape [Yelp](https://www.yelp.com) business listings past DataDome**: name, star rating, review count, price range, categories, street, neighborhood and opening hours from search results. Optionally it also opens each business page for phone, website, menu link, full postal address, claimed status and Yelp's one-line summary. Search with "what in where", or pass Yelp URLs you already have.

No browser is launched. [xhr.dev](https://xhr.dev) solves the DataDome challenge as plain HTTP, so a page costs a few hundred milliseconds of compute instead of the several seconds and gigabyte of RAM a stealth browser needs. Runs on Apify, so you get API access, scheduling, integrations and monitoring with no extra setup.

### Quickstart

Paste this into the input and press **Run**.

```json
{
  "queries": ["pizza in San Francisco, CA"],
  "maxPagesPerQuery": 2,
  "scrapeDetails": false
}
```

### Why use Yelp Scraper?

- **Lead lists for local businesses.** Every plumber, dentist or café in a city, with rating, review count and category, ready for a CRM.
- **Market and competitor research.** See how a category is rated across neighborhoods, and who dominates the first page.
- **Location intelligence.** Opening hours, price range and neighborhood for site-selection or delivery-coverage work.

### How to use it

1. Click **Try for free**.
2. Under **Searches**, enter one line per search, written as `what in where`, e.g. `plumbers in Austin, TX`.
3. Set **Pages per search**. Yelp shows 10 businesses a page and stops at 24 pages.
4. Turn on **Open each business page** if you need phone, website and the full address.
5. Click **Start**, then download the results from the **Output** tab.

### Input

| Field | Type | Default | Description |
| --- | --- | --- | --- |
| `queries` | string\[] | `["pizza in San Francisco, CA"]` | Searches, each written as `what in where`. A search with no place is skipped with a message. Yelp would otherwise search wherever the request came from, which is a data centre. |
| `startUrls` | array | `[]` | `/biz/` URLs are read as businesses; `/search` URLs are read as result lists. Copy a search URL from your browser to keep Yelp's own filters. |
| `scrapeDetails` | boolean | `false` | Open every business found for its full record. One extra page per business. |
| `maxPagesPerQuery` | integer | `1` | How deep to page each search, 1–24. |
| `maxItems` | integer | `50` | Stop once this many businesses have been scraped. |
| `proxyConfiguration` | object | No proxy | Yelp solves cleanly from Apify's own address. Try Residential only if it starts refusing you. |
| `maxRetries` | integer | `3` | Attempts per page, 1–5. |
| `timeoutSecs` | integer | `120` | Deadline per page, challenge and all. |
| `maxConcurrency` | integer | `4` | Pages in flight at once, 1–10. |

### Output

One dataset item per business. Fields a business lacks are omitted rather than set to `null`. You can download the dataset in various formats such as JSON, HTML, CSV, or Excel.

| Field | From | Description |
| --- | --- | --- |
| `id` | both | Yelp business ID. |
| `name` | both | Business name. |
| `url` | both | Canonical `yelp.com/biz/...` URL. |
| `rating` | both | Star rating, e.g. `4.2`. |
| `reviewCount` | both | Number of reviews. |
| `priceRange` | both | `$` to `$$$$`. |
| `categories` | both | Yelp categories, e.g. `["Pizza", "Italian"]`. |
| `street` / `city` | both | Street line and city. |
| `neighborhoods` | both | Yelp neighborhood names. |
| `hours` | both | Weekly opening ranges as `{ day, open, close }`, 24-hour clock. |
| `rank` | search | Position in the organic results. Sponsored results are left out. |
| `image` | both | Main photo. |
| `phone` | business page | Phone number as Yelp displays it. |
| `website` / `menu` | business page | The business's own site and menu link. |
| `address` / `region` / `postalCode` / `country` | business page | Full postal address. |
| `isClosed` / `isClaimed` | business page | Permanently closed; owner has claimed the page. |
| `summary` | business page | Yelp's one-line description. |

#### Example record

From a live run with `scrapeDetails` on, with `hours` trimmed to two days:

```json
{
  "id": "mSMZJj2pFvttWLpcDmgrEA",
  "name": "Tony's Pizza Napoletana",
  "url": "https://www.yelp.com/biz/tonys-pizza-napoletana-san-francisco",
  "rating": 4.2,
  "reviewCount": 9032,
  "priceRange": "$$",
  "categories": ["Pizza", "Italian", "Cocktail Bars"],
  "address": "1570 Stockton St, San Francisco, CA 94133",
  "street": "1570 Stockton St",
  "city": "San Francisco",
  "region": "CA",
  "postalCode": "94133",
  "country": "US",
  "neighborhoods": ["North Beach/Telegraph Hill"],
  "hours": [
    { "day": "Mon", "open": "12:00", "close": "22:00" },
    { "day": "Tue", "open": "12:00", "close": "22:00" }
  ],
  "phone": "(415) 835-9888",
  "website": "http://www.tonyspizzanapoletana.com",
  "menu": "https://tonyspizzanapoletana.com/currentmenu",
  "isClosed": false,
  "isClaimed": true,
  "summary": "Award-winning pizza and a classic San Francisco atmosphere.",
  "image": "https://s3-media0.fl.yelpcdn.com/bphoto/ptCPOJoqVokZW7GmQ5F4NQ/o.jpg"
}
```

#### Business data only

Review text, reviewer names and photo authors also appear on these pages, and this Actor deliberately leaves them out. They are personal data, and a list of businesses does not need them.

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

- **$3.00 per 1,000 businesses** from search results (`listing-item`).
- **$15.00 per 1,000 businesses** opened on their own page (`product-detail`), when `scrapeDetails` is on.

You are charged only for rows that reach your dataset; failed pages cost nothing. No proxy is needed by default, so there is no proxy bill on top of Apify compute.

### Tips

- **Write the place the way Yelp would**: `Austin, TX`, `Brooklyn, NY`, or a ZIP code.
- **Go wide before you go deep.** Ten searches at one page each usually beat one search at ten pages, because Yelp's later pages drift away from the place you asked for.
- **Leave `scrapeDetails` off** unless you need phone or website. Search rows are a fifth of the price.
- **Set `maxTotalChargeUsd`** on the run for a hard spend cap; the Actor stops fetching when it is reached.

### Limits and failure behaviour

- **100 pages per run**, hard, to keep one run from flooding the shared solver. Split bigger jobs across runs.
- **Failures never enter the dataset.** Each run writes a `RUN_SUMMARY` record to the key-value store with pages fetched, pages failed, and why.
- **Pagination is never speculative.** Page 2 is fetched only after page 1 confirms it exists.

### FAQ

**Is scraping Yelp legal?** This Actor collects publicly visible business information and no personal data. You are responsible for how you use it: check Yelp's terms and the law where you operate before running at scale.

**Is this affiliated with Yelp?** No. It is an independent tool with no connection to Yelp or any bot-protection vendor.

**Something broke, or you need a field we skip?** Open an issue on the **Issues** tab. For volume or a custom build, reach us through [xhr.dev](https://xhr.dev).

### Related Actors

- **[DataDome Unblocker](https://apify.com/xhrdev/datadome-unblocker)**: any URL behind DataDome, returning HTML plus clearance cookies.
- **[Saks Fifth Avenue Scraper](https://apify.com/xhrdev/saks-scraper)**: luxury product prices.
- **[Etsy Scraper](https://apify.com/xhrdev/etsy-scraper)**, **[Anthropologie Scraper](https://apify.com/xhrdev/anthropologie-scraper)**, **[Grainger Scraper](https://apify.com/xhrdev/grainger-scraper)**, **[leboncoin Scraper](https://apify.com/xhrdev/leboncoin-scraper)**.

***

Built by [xhr.dev](https://xhr.dev). Independent tool, not affiliated with Yelp or any bot-protection vendor.

# Actor input Schema

## `queries` (type: `array`):

What to find and where, written as "what in where" — e.g. "pizza in San Francisco, CA" or "plumbers in Austin, TX". Yelp needs a place for every search; a search without one is skipped with a message.

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

Yelp URLs to scrape. /biz/ URLs are read as businesses; /search URLs are read as result lists — copy one out of your browser to keep Yelp's own filters.

## `scrapeDetails` (type: `boolean`):

Off by default: search results already carry name, rating, review count, price range, categories, street, neighborhood and opening hours. Turn it on to also get phone, website, menu link, full postal address, claimed status and Yelp's one-line summary — one extra page per business.

## `maxPagesPerQuery` (type: `integer`):

How deep to page through each search, 10 businesses a page. Yelp itself stops at 24 pages (240 results) however many match.

## `maxItems` (type: `integer`):

Stop once this many businesses have been scraped, across everything in this run.

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

Left off by default: Yelp solves cleanly from the container's own address — search, page 2 and business pages all cleared on the first attempt, every run, when this Actor was verified. If Yelp starts refusing cleared requests for you, try Residential.

## `maxRetries` (type: `integer`):

How many times to try a page before giving up on it. Each attempt takes a fresh proxy session, so a dead exit node or a burnt IP gets a genuinely new chance.

## `timeoutSecs` (type: `integer`):

How long one page — challenge, solve and all — may take before it counts as a failed attempt.

## `maxConcurrency` (type: `integer`):

How many pages to work on at once. The solve path is HTTP-only and cheap, so this can go higher than a browser scraper would allow, but be a considerate guest on someone else's site.

## Actor input object example

```json
{
  "queries": [
    "pizza in San Francisco, CA"
  ],
  "startUrls": [],
  "scrapeDetails": false,
  "maxPagesPerQuery": 1,
  "maxItems": 50,
  "proxyConfiguration": {
    "useApifyProxy": false
  },
  "maxRetries": 3,
  "timeoutSecs": 120,
  "maxConcurrency": 4
}
```

# Actor output Schema

## `results` (type: `string`):

No description

## `runSummary` (type: `string`):

No description

# 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 = {
    "queries": [
        "pizza in San Francisco, CA"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("xhrdev/yelp-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 = { "queries": ["pizza in San Francisco, CA"] }

# Run the Actor and wait for it to finish
run = client.actor("xhrdev/yelp-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 '{
  "queries": [
    "pizza in San Francisco, CA"
  ]
}' |
apify call xhrdev/yelp-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,xhrdev/yelp-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/tsp0NJgfeTUgcZglz/builds/osPrDYtneJKi4OokM/openapi.json
