# Yelp Reviews Scraper — Unlimited Reviews + AI Analysis (`memo23/yelp-reviews-scraper`) Actor

Scrape unlimited Yelp reviews past the 3-review page cap — reviewer name, rating, date, full text, photos and owner replies. Feed it a business URL or a search term plus city. Optional AI pain-point teardown turns the reviews into ranked complaint themes. No login or API key. Clean JSON or CSV.

- **URL**: https://apify.com/memo23/yelp-reviews-scraper.md
- **Developed by:** [Muhamed Didovic](https://apify.com/memo23) (community)
- **Categories:** AI, Agents, Automation
- **Stats:** 17 total users, 16 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: 5.00 out of 5 stars

## Pricing

from $2.75 / 1,000 results

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## Yelp Reviews Scraper

Pull the **full review history** of any Yelp business — not the 3 reviews Yelp shows an anonymous visitor. Paste business URLs or search a category and city, and get one clean row per business with every review attached: reviewer, star rating, date, full text, photos and the owner's reply.

Runs over plain HTTP with a built-in residential proxy. No Yelp account, no API key, no login, no browser.

### Why use it

- **Past the 3-review cap.** Yelp's public page stops at three reviews. This walks the whole list — hundreds or thousands per business.
- **Reviews you can actually analyse.** Star rating, ISO date, full text, reviewer name, photo count and owner responses, as structured fields rather than scraped blobs.
- **AI pain-point analysis.** Optional LLM teardown that turns a pile of reviews into ranked complaint themes with supporting quotes. Nothing else on the Store does this.
- **Review insights.** Optional computed summary per business: rating distribution, recent-vs-lifetime trend, and the phrases that keep recurring.
- **Proxy included.** Residential routing is built in at no extra cost. You do not need Apify's RESIDENTIAL add-on, and you do not need to configure anything.

### Two ways to start

**By business URL** — fastest when you already know the businesses:

```json
{
  "startUrls": [{ "url": "https://www.yelp.com/biz/gary-danko-san-francisco" }],
  "scrapeReviews": true,
  "maxReviews": 200
}
```

**By category and city** — when you want every business in a market:

```json
{
  "searchTerms": ["plumbers"],
  "searchLocation": "Chicago, IL",
  "scrapeReviews": true,
  "maxReviews": 100,
  "maxItems": 50
}
```

Use one or the other. Filling both scrapes the URLs **and** the whole category, which costs more than you probably intended.

### Input

| Field | Type | Default | Description |
| --- | --- | --- | --- |
| `startUrls` | array | — | Yelp business page URLs to pull reviews from |
| `searchTerms` | array | — | Category search, e.g. `["plumbers"]`. Needs `searchLocation` |
| `searchLocation` | string | — | City or region for the category search, e.g. `"Chicago, IL"` |
| `searchSortBy` | string | — | Sort order for search results |
| `scrapeReviews` | boolean | `true` | Pull the full review list per business |
| `maxReviews` | integer | `200` | Cap on reviews per business |
| `reviewInsights` | boolean | `false` | Rating distribution, trend and recurring phrases. Billed per business |
| `painPointAnalysis` | boolean | `false` | AI complaint-theme teardown. Paid plans, billed per business |
| `maxItems` | integer | `1000` | Cap on businesses returned |
| `useCachedData` | boolean | `true` | Reuse recent results instead of refetching |
| `maxCacheAgeDays` | integer | — | How stale cached data may be |
| `proxy` | object | — | Optional override. Leave empty to use the built-in residential proxy |

### Output

One row per business, with reviews nested:

```json
{
  "rating": 4.5,
  "reviewCount": "6140 reviews",
  "url": "https://www.yelp.com/biz/gary-danko-san-francisco",
  "reviews": [
    {
      "type": "review",
      "reviewId": "bk9F7IbAlP7unixO-Wsoig",
      "rating": "5",
      "text": "Wife and I came here for our Anniversary...",
      "createdAt": "2026-07-14",
      "user": { "name": "…", "reviewCount": 42 },
      "photos": [],
      "ownerReply": null
    }
  ]
}
```

Export as JSON, CSV, Excel or XML from the dataset, or read it straight from the API.

### Use cases

- **Reputation monitoring** — track how a location's rating moves over time and catch complaint spikes early.
- **Competitor teardown** — pull a rival's reviews and let the pain-point analysis rank what their customers complain about.
- **Market research** — collect every review in a category and city to find the gaps nobody is serving.
- **Review-response workflows** — feed unanswered reviews into a drafting pipeline.
- **Training data** — sentiment and rating pairs at volume.

### Cost

Pay per event. You are charged for the businesses returned and the reviews collected, plus the optional insight and analysis add-ons if you enable them. Lower `maxReviews` to control spend on businesses with thousands of reviews, and set Apify's **Max charge** field on the run for a hard ceiling.

### FAQ

**Do I need a Yelp account or API key?** No. Everything comes from public pages.

**Do I need Apify's RESIDENTIAL proxy add-on?** No. Residential routing is built in. Leaving the proxy field empty is the intended setup.

**How many reviews can it get?** As many as Yelp publishes for that business, bounded by `maxReviews`.

**Why did I get fewer reviews than I asked for?** The business has fewer than your cap, or Yelp filtered some as "not recommended" — those are not on the public list.

**Can I get reviews from a date range?** Reviews carry their posted date, so filter downstream on `createdAt`.

**Does it get business contact details and emails too?** This listing is reviews-focused. For business data with contact-email enrichment, use [Yelp Leads & Business Scraper](https://apify.com/memo23/yelp-scraper).

### Support

Open an issue on the actor's Issues tab. Include the run ID — it makes problems much faster to pin down.

### 🤖 For AI agents & LLM apps

Callable over the Apify API and MCP. Pass `startUrls` for a known business or `searchTerms` + `searchLocation` to discover businesses first. The dataset is one row per business with a `reviews` array, which suits retrieval and summarisation directly. Keep `maxReviews` modest for interactive use — review collection dominates runtime.

### ⚠️ Disclaimer

This actor collects publicly available information from Yelp business pages. Use the data in line with Yelp's terms and applicable law, including data-protection rules where review content contains personal data. You are responsible for how you use what you collect.

# Actor input Schema

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

Paste one or more Yelp business page URLs to pull their reviews directly — the fastest path when you already know the businesses.

## `searchTerms` (type: `array`):

Find businesses by category, then scrape the reviews of everything found — e.g. "plumbers". Needs the location field below. Leave empty when using business URLs.

## `searchLocation` (type: `string`):

City or region for the category search above, e.g. "Chicago, IL". Ignored when you supply business URLs.

## `searchSortBy` (type: `string`):

Result ordering for generated searches. Applies to **Search terms** only.

## `scrapeReviews` (type: `boolean`):

Pull the full review list for every business found. Yelp only shows 3 reviews per page to anonymous visitors; this walks the full set.

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

Upper bound per business. Lower it to control cost on businesses with thousands of reviews.

## `reviewInsights` (type: `boolean`):

Adds a computed summary per business: rating distribution, recent-vs-lifetime trend, and most-repeated phrases. Billed per business.

## `painPointAnalysis` (type: `boolean`):

Runs an LLM teardown of the collected reviews and returns ranked complaint themes with supporting quotes. Paid plans only, billed per business.

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

Maximum number of items that will be scraped. One item = one business row. Default: 1000 — set a lower cap (e.g. 50) for test runs.

## `useCachedData` (type: `boolean`):

When <b>enabled</b> (default), business and search pages that were already scraped recently are served from a shared cache instead of being re-fetched — noticeably faster and cheaper. Cached rows are marked with <code>servedFromCache: true</code> and a <code>dataAsOf</code> timestamp so you always know how fresh the data is. Reviews (when enabled) are always fetched fresh. Turn this <b>off</b> to force every page to be scraped live.

## `maxCacheAgeDays` (type: `integer`):

Freshness limit for cached pages. A cached record older than this many days is re-scraped live. Set <b>0</b> to always bypass the cache and fetch everything fresh. Leave empty to use sensible defaults (business details ~21 days, search listings ~14 days). Only applies when <b>Use cached data</b> is enabled.

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

Maximum number of pages that can be processed at the same time (max 20). When <b>Fetch full business details</b> is enabled, the effective value is additionally capped to what the run's memory can sustain (about 10 at 1024MB) to prevent out-of-memory failures.

## `minConcurrency` (type: `integer`):

Minimum number of pages that will be processed at the same time.

## `maxRequestRetries` (type: `integer`):

Number of times the crawler will retry a failed request before giving up.

## `proxy` (type: `object`):

Leave empty — the actor already routes all traffic through its own built-in residential proxy at no extra cost to you. Only set this if you want to use your own proxies.<br><br>Heads-up: selecting Apify's RESIDENTIAL group here will make the run fail before it starts unless your account has that add-on enabled.

## `proxyProviders` (type: `array`):

Paying users only. Preference list of providers from the shared proxy-pool KV store. First usable provider wins; add fallbacks like \['evomi','decodo'] for resilience. Rotation is centralised — credentials are updated in the KV store, not in this input. Defaults to \['evomi'].

## Actor input object example

```json
{
  "startUrls": [
    "https://www.yelp.com/biz/gary-danko-san-francisco"
  ],
  "searchSortBy": "",
  "scrapeReviews": true,
  "maxReviews": 200,
  "reviewInsights": false,
  "painPointAnalysis": false,
  "maxItems": 1000,
  "useCachedData": true,
  "maxConcurrency": 20,
  "minConcurrency": 1,
  "maxRequestRetries": 100,
  "proxyProviders": [
    "evomi"
  ]
}
```

# Actor output Schema

## `results` (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 = {
    "startUrls": [
        "https://www.yelp.com/biz/gary-danko-san-francisco"
    ],
    "scrapeReviews": true,
    "maxReviews": 200
};

// Run the Actor and wait for it to finish
const run = await client.actor("memo23/yelp-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.yelp.com/biz/gary-danko-san-francisco"],
    "scrapeReviews": True,
    "maxReviews": 200,
}

# Run the Actor and wait for it to finish
run = client.actor("memo23/yelp-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.yelp.com/biz/gary-danko-san-francisco"
  ],
  "scrapeReviews": true,
  "maxReviews": 200
}' |
apify call memo23/yelp-reviews-scraper --silent --output-dataset

```

## MCP server setup

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