# Yelp Reviews Scraper (`nice_dev/yelp-reviews-scraper`) Actor

Scrape Yelp reviews from business URLs, IDs or a Yelp search (keyword × location): text, stars, date, owner reply, photos, translation, reviewer. Filters, monitoring of new reviews, full business details. Export to JSON, CSV or Excel.

- **URL**: https://apify.com/nice_dev/yelp-reviews-scraper.md
- **Developed by:** [Nice Dev](https://apify.com/nice_dev) (community)
- **Categories:** MCP servers, Lead generation, Marketing
- **Stats:** 1 total users, 0 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

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

### ⭐ What is Yelp Reviews Scraper?

**Yelp Reviews Scraper** extracts **reviews from [Yelp](https://www.yelp.com)**: **star rating, full text, date, owner reply, photos and videos, Yelp's translation, earlier versions of an edited review, and the reviewer's public profile**, for any business, from a business link, a business id or a **Yelp search by keyword and location**. It can also return **businesses only**, with their full details: phone, website, address, GPS, hours, amenities, health inspections, popular dishes, e-mails and social media links. It works as a **Yelp API alternative**: run it on a schedule, call it from your code, or plug it into Make, Zapier or n8n.

Paste a **business link** (`https://www.yelp.com/biz/golden-boy-pizza-san-francisco`) or type a **keyword and a location** (`pizza` in `San Francisco, CA`), click **Start**, and download the reviews in JSON, CSV or Excel. No login, nothing to set up, and it is **fast: about 100 reviews in 15 seconds, 1,000 in under 2 minutes**. Every Yelp country works: yelp.com, yelp.co.uk, yelp.fr, yelp.ca, yelp.de and the others.

### 📋 What data can you extract from Yelp?

One item per review (or per business with **Scrape reviews** off), 50 fields:

| Category | What you get |
| --- | --- |
| ⭐ **Review** | stars 1-5, full text, language, Yelp's translation into the language you choose |
| 🕒 **Dates** | publication date (UTC and the business's local time), date of the experience when given |
| ✏️ **Edited reviews** | the earlier versions of a review its author updated: their text, stars and date |
| 📸 **Media** | photos (full size, with caption) and videos posted with the review |
| 💬 **Owner reply** | the business's public answer, its date, the name and role of who wrote it |
| 👍 **Reactions and badges** | Helpful, Thanks, Love this, Oh no counts; check-ins, first review, Review of the Day, expert badge; paid through Yelp, deal, reservation |
| 👤 **Reviewer** | display name, location, profile link, photo, number of reviews, friends and photos, Elite years (can be turned off) |
| 🏢 **Business** | name, link, overall rating, number of reviews, reviews per star and per language, categories, city, region, neighborhoods, main photo |
| 📇 **Full business details** (option) | phone, website, address, GPS, price range, opening hours and time zone, open now, closed, claimed, Yelp summary, year established, history, specialties, owner, about 30 amenities, health inspections, popular dishes, review highlights, menu link, service areas, licenses, consumer alerts, messaging response time, questions and answers, logo, chain, Yelp Guaranteed, advertiser |
| 🖼️ **Business photos** (option) | the business's photo gallery, full size, with captions |
| ✉️ **E-mails and social media** (option) | e-mail addresses published on the business's own website, and its Facebook, Instagram, X, TikTok, YouTube, LinkedIn and Pinterest pages |
| 🔎 **Search** | the keyword and location that found the business, and its rank in Yelp's results |

Every field, with an example, is listed in the **Output** section below.

### ✅ Why use Yelp Reviews Scraper?

- 🚀 **Fast**: about 100 reviews in 15 seconds, 1,000 in under 2 minutes; a business with its full details, gallery page and e-mails in a few seconds more.
- 🧭 **Reviews from a link, an id or a search**: type `dentist` and several cities or ZIP codes, and the Actor finds the businesses, then reads their reviews. Each search merges Yelp's three orders (recommended, highest rated, most reviewed) for up to 75 different businesses per keyword and location.
- 🎯 **Every filter in one place**: stars (several at once), date range (from and to), review languages, words to include or exclude, only reviews with an owner reply or with photos; and on the business: minimum rating, minimum number of reviews, price range, open now, phone or website shown, required amenities.
- ✏️ **Edited reviews kept**: when a reviewer updates a review, you also get the earlier versions.
- 🌍 **Free translation**: Yelp's own translation of each review, next to the original text.
- 🔔 **Monitoring built in**: tick **Only new reviews**, schedule the Actor, and each run returns (and charges) only the reviews it has never delivered before.
- 📇 **Lead lists too**: turn **Scrape reviews** off for one row per business with its full details, and add the e-mails and social media links found on its website.
- 🔌 API, scheduling, monitoring, integrations (Make, Zapier, n8n, Google Sheets…) and JSON/CSV/Excel export via the Apify platform.

### 🚀 How to scrape Yelp reviews

1. Create a free Apify account.
2. Open **Yelp Reviews Scraper** and paste one or more Yelp business links into **Yelp URLs** — or type a **Search keyword** and a **Location** to find the businesses.
3. Pick the **Review order** and any filters (stars, dates, languages, keywords…).
4. Set **Max results** (100 by default, 0 = no limit) — and **Max reviews per business** when you read several businesses — then click **Start**.
5. Download the dataset in JSON, CSV, Excel or via API.

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

This Actor uses **pay per event** pricing — see the **Pricing** tab. You pay for the rows saved, and for the options only when you turn them on. Prices per 1,000 events, by Apify plan:

| What you pay for | Event | Free | Bronze | Silver | Gold and above |
| --- | --- | --- | --- | --- | --- |
| A review saved | `review` | $0.045 | $0.044 | $0.036 | $0.035 |
| A business saved, with its full details (**Scrape reviews** off) | `business` | $0.45 | $0.44 | $0.43 | $0.42 |
| Full business details added to the reviews of a business, once per business (**Add full business details**) | `business-details` | $0.45 | $0.44 | $0.43 | $0.42 |
| A page of up to 30 business photos (**Business photos per business**) | `photo-page` | $0.89 | $0.86 | $0.81 | $0.77 |
| A business whose website shows at least one e-mail address (**Find e-mails on business websites**) | `email-enriched` | $2.69 | $2.68 | $2.67 | $2.66 |
| A review or a business read, then dropped by one of the Actor's own filters | `filter-check` | $0.054 | $0.044 | $0.034 | $0.024 |

Each run also costs **$0.01 per run start** (`apify-actor-start`). Example: 10,000 reviews on the Gold plan = 10 × $0.035 + $0.01 = $0.36.

The star filter is applied by Yelp itself: the reviews it leaves out are never read and never charged. Social media links come with the e-mail option at no extra charge, and the translation is free. Platform usage (compute, proxy) is included in the price.

### ⚙️ Input

Reviews of one business, newest first:

```json
{
    "startUrls": [{ "url": "https://www.yelp.com/biz/golden-boy-pizza-san-francisco" }],
    "sortBy": "newest",
    "maxItems": 200
}
```

A search in several places, 50 reviews per business, only the bad recent ones in English:

```json
{
    "query": "pizza",
    "locations": ["San Francisco, CA", "94133"],
    "maxBusinessesPerSearch": 20,
    "maxItemsPerQuery": 50,
    "starRatings": ["1", "2"],
    "postedAfter": "6 months",
    "reviewLanguages": ["en"],
    "maxItems": 2000
}
```

Businesses only, with their details, e-mails and social media links (a lead list):

```json
{
    "query": "plumbers",
    "location": "Austin, TX",
    "includeReviews": false,
    "requirePhone": true,
    "requireWebsite": true,
    "enrichEmails": true,
    "maxItems": 100
}
```

Daily monitoring of a few businesses:

```json
{
    "businessIds": ["PTFxtXS47ZVRCdZIrEWvGw", "golden-boy-pizza-san-francisco"],
    "onlyNew": true,
    "stateKey": "my-restaurants",
    "maxItems": 0
}
```

| Field            | Notes |
| ---------------- | ----- |
| `startUrls` | Yelp business pages of any country (`https://www.yelp.com/biz/golden-boy-pizza-san-francisco`, `https://www.yelp.co.uk/biz/dishoom-london`), or Yelp search pages (`https://www.yelp.com/search?find_desc=pizza&find_loc=San+Francisco`: keyword and location are read from the link). Max 1,000. |
| `businessIds` | Yelp business ids (`PTFxtXS47ZVRCdZIrEWvGw`) or aliases, the last part of a business link (`golden-boy-pizza-san-francisco`). |
| `query`, `searchQueries` | What to search on Yelp, as typed in its search box (`pizza`, `plumber`, `dentist`); `searchQueries` adds more keywords. Needs a location. |
| `location`, `locations` | City, neighborhood or ZIP code (`San Francisco, CA`, `94133`, `London`); `locations` adds more places. Every keyword is searched in every location (max 500 searches per run). |
| `latitude`, `longitude` | Also search around this GPS point. |
| `searchSortBy` | Yelp gives at most 25 businesses per search and order: `all` merges recommended, highest rated and most reviewed (up to 75 businesses); or `recommended`, `highest_rated`, `most_reviewed`. |
| `maxBusinessesPerSearch` | Businesses kept from each search, in Yelp's order (0 = all, up to 75). |
| `includeReviews` | Off = one row per business with its full details, and no review. |
| `maxItems`, `maxItemsPerQuery` | Results for the whole run (0 = no limit), and the cap for each business (with `includeReviews` off: businesses per search). |
| `sortBy` | `newest` (default), `oldest`, `relevance`, `highest_rating`, `lowest_rating` or `elites` (Elite reviewers first). |
| `translateTo` | Two-letter language code (`en`, `fr`, `es`): Yelp's translation lands in `translatedText`, the original is kept. |
| `includeReviewerDetails` | Reviewer's public profile (default on); off = the reviewer column is null. |
| `includeBusinessDetails` | Adds the business's full details to each of its reviews, charged once per business. |
| `maxBusinessPhotos` | Photos of the business gallery per business (0 = none), read 30 per page. |
| `enrichEmails` | Visits each business's own website (up to 3 pages) for its e-mail addresses and social media links. |
| `starRatings` | Only these stars (`5`, `4`, `3`, `2`, `1`; several allowed), applied by Yelp: never charged. |
| `postedAfter`, `postedBefore` | Review date range: `2026-09-01`, or a period before now (`7 days`, `2 weeks`, `6 months`, `24 hours`). |
| `reviewLanguages` | Only reviews written in these languages (`en`, `es`, `fr`). |
| `keywords`, `excludeKeywords` | Keep the reviews whose text contains one of these words (`parking`), or drop them (`delivery`); whole words, case and accents ignored. The words are looked for in the review as its author wrote it, never in its translation. |
| `withResponseOnly`, `withPhotosOnly` | Only the reviews with an owner reply, or with photos or videos. |
| `minRating`, `minReviewCount` | Skip the businesses rated below this, or with fewer reviews on Yelp. |
| `requirePhone`, `requireWebsite`, `openNow` | Only the businesses that show a phone number, a website, or that are open at the time of the run. |
| `priceLevels` | Only these price ranges (`$`, `$$`, `$$$`, `$$$$`); a business with no price range is skipped. |
| `features` | Only the businesses that show ALL these amenities, as written on Yelp (`Outdoor seating`, `Offers delivery`, `Wheelchair accessible`). |
| `onlyNew`, `stateKey`, `resetState` | Monitoring: only the reviews never delivered under this memory key; `resetState` forgets the memory. |
| Advanced | `proxyConfiguration` (Apify proxy by default, included in the price; the residential proxy is not available), `maxConcurrency`, `maxRequestsPerMinute`, `minRequestIntervalMs`, `maxRequestRetries`, `debugLog`. |

### 📦 Output

One real row, shortened (most of `details` and the gallery cut; a row has all 50 fields):

```json
{
    "type": "review",
    "id": "hHOfwEDJ7SzGkQo9RO518Q",
    "url": "https://www.yelp.com/biz/golden-boy-pizza-san-francisco?hrid=hHOfwEDJ7SzGkQo9RO518Q",
    "rating": 4,
    "text": "Yummy pizza and great price! Pizza came out fast, the crust was crispy to perfection, and the line moves quick with great vibes! We also tried a combo pizza which was my favorite",
    "language": "en",
    "translatedText": "Délicieuse pizza à un prix imbattable ! La pizza est arrivée rapidement, la croûte était croustillante à souhait et l'attente était courte et l'ambiance super ! On a aussi testé la pizza combo, mon coup de cœur !",
    "translatedLanguage": "fr",
    "publishedAt": "2026-10-02T14:32:10.000Z",
    "publishedAtLocal": "2026-10-02T07:32:10-07:00",
    "isUpdated": false,
    "previousReviews": [],
    "reactions": {
        "helpful": 0,
        "thanks": 0,
        "loveThis": 0,
        "ohNo": 0
    },
    "photos": [
        {
            "id": "HNvJP9RBhO6tkkxHe2_nLg",
            "url": "https://s3-media0.fl.yelpcdn.com/bphoto/HNvJP9RBhO6tkkxHe2_nLg/o.jpg",
            "caption": "Pepperoni slice and sausage slice",
            "width": 1500,
            "height": 2000
        }
    ],
    "ownerResponse": null,
    "reviewer": {
        "name": "Sara T.",
        "location": "Nashua, NH",
        "profileUrl": "https://www.yelp.com/user_details?userid=e7iyuWtqR4Of8lDpbtUC1Q",
        "reviewCount": 3,
        "isElite": false
    },
    "businessId": "PTFxtXS47ZVRCdZIrEWvGw",
    "businessName": "Golden Boy Pizza",
    "businessUrl": "https://www.yelp.com/biz/golden-boy-pizza-san-francisco",
    "businessRating": 4.3,
    "businessReviewCount": 4871,
    "ratingDistribution": {
        "1": 114,
        "2": 159,
        "3": 435,
        "4": 1392,
        "5": 2772
    },
    "businessCategories": [
        {
            "title": "Pizza",
            "alias": null,
            "rootAlias": "restaurants"
        }
    ],
    "businessCity": "San Francisco",
    "details": {
        "phone": "(415) 982-9738",
        "website": "http://www.goldenboypizza.com",
        "address": {
            "addressLine1": "542 Green St",
            "addressLine2": null,
            "addressLine3": null,
            "city": "San Francisco",
            "state": "CA",
            "postalCode": "94133",
            "country": "US",
            "formatted": "542 Green St, San Francisco, CA 94133"
        },
        "latitude": 37.7997956,
        "longitude": -122.4080729,
        "priceRange": "$",
        "isClaimed": true,
        "summary": "A walk-up window pizza spot with standout clam slices.",
        "yearEstablished": "1978",
        "amenities": [
            {
                "label": "Offers delivery",
                "active": true
            },
            {
                "label": "Offers take-out",
                "active": true
            }
        ]
    },
    "businessPhotos": [
        {
            "id": "LzMZYAathPmoqKgXfx2iOg",
            "url": "https://s3-media0.fl.yelpcdn.com/bphoto/LzMZYAathPmoqKgXfx2iOg/o.jpg",
            "caption": "Pesto Veggie and Combo slices"
        },
        {
            "id": "I3bJGcauLtqgvqcxicD-RQ",
            "url": "https://s3-media0.fl.yelpcdn.com/bphoto/I3bJGcauLtqgvqcxicD-RQ/o.jpg",
            "caption": "Menu"
        }
    ],
    "emails": null,
    "socialLinks": null,
    "sourceInput": "https://www.yelp.com/biz/golden-boy-pizza-san-francisco",
    "scrapedAt": "2026-10-07T18:01:51.941Z"
}
```

You can download the dataset in various formats such as JSON, HTML, CSV or Excel.

#### All 50 fields

| Fields | What you get |
| --- | --- |
| `type`, `id`, `url` | `review` (or `business` with **Scrape reviews** off), the review id, the link to the review on Yelp |
| `reviewId`, `rating`, `text`, `language` | **Review**: id, stars 1-5, full text, language detected by Yelp (`en`) |
| `translatedText`, `translatedLanguage` | Yelp's translation (with `translateTo`); null when the review is already in that language |
| `publishedAt`, `publishedAtLocal`, `experienceDate` | **Dates**: ISO UTC, the same in the business's time zone, the date of the experience when given |
| `isUpdated`, `previousReviews` | **Edited reviews**: true when updated, and the earlier versions (text, stars, date), newest first |
| `reactions` | Helpful, Thanks, Love this and Oh no counts |
| `photos`, `videos` | **Media**: full-size photos with caption, videos with thumbnail |
| `ownerResponse` | **Owner reply**: text, date, name and role of who wrote it |
| `checkInCount`, `isFirstReviewer`, `isReviewOfTheDay`, `expertRecognition` | check-ins, first review of the business, Review of the Day, expert badge |
| `paidThroughYelp`, `purchasedDeal`, `placedReservation`, `reservationProvider` | paid through Yelp, bought a deal, booked a table and through whom |
| `reviewer` | **Reviewer**: id, name, location, profile link, photo, reviews, friends, photos, Elite year (null with `includeReviewerDetails` off) |
| `businessId`, `businessAlias`, `businessName`, `businessUrl` | **Business**: id, alias, name, link |
| `businessRating`, `businessReviewCount`, `ratingDistribution`, `reviewsByLanguage` | overall rating, number of recommended reviews, reviews per star and per language |
| `businessCategories`, `businessCity`, `businessRegion`, `businessNeighborhoods`, `businessPhotoUrl` | categories, city, state or region, neighborhoods, main photo |
| `details` | **Full business details**: about 45 fields (phone, website, address, GPS, hours, amenities, health inspections, popular dishes, owner, licenses, questions and answers…); null when the option is off, always filled for a business row |
| `businessPhotos` | **Business photos**: id, full-size link, caption; filled on the first row of each business |
| `emails`, `emailSource`, `socialLinks` | **E-mails and social media**: addresses found on the business's website, the page of the first one, links to its social media pages (one per account, up to 20); null when the option is off, `[]`, null and `[]` when the website shows none |
| `searchQuery`, `searchLocation`, `searchRank` | **Search**: keyword, location and rank (1 = first) of the business in the results of the search that found it; with the default **Search order** (all three orders), the rank counts the three result lists one after the other, each business once |
| `sourceInput`, `scrapedAt` | the URL, id or search of the input behind the row, ISO timestamp |

### 💡 Tips

#### How to get more results

Yelp returns at most 25 businesses per search and order. Keep **Search order** on all three orders (up to 75 businesses per keyword and location), and split a big city into ZIP codes or neighborhoods in `locations`: each one is a search of its own. Every review Yelp shows on a business page can be read, with **Max reviews per business** at 0.

#### How to reduce costs

The price is per review saved, so the levers are `maxItems`, `maxItemsPerQuery`, the star filter (applied by Yelp, free) and `onlyNew` for recurring runs (you never pay twice for the same review). The other filters cost a small fee per review or business they drop, lower than a review. Full details, photos and e-mails are options, charged only when on.

#### Several businesses and searches in one run

Mix `startUrls`, `businessIds` and searches freely: a business reached twice is read once. Fill `searchQueries` and / or `locations`: the Actor runs one search per keyword × location (3 keywords × 4 cities = 12 searches, up to 500 per run). Set `maxItemsPerQuery` to give each business its own cap: without it the first business can use up the whole `maxItems` budget.

#### Monitoring: only the new reviews

Tick **Only new reviews** (`onlyNew`) and schedule the Actor. The first run returns everything; each later run skips the reviews already delivered: they are not saved and not charged. The memory lives in a named key-value store of your account (`yelp-reviews-scraper-seen`, up to 150,000 reviews per key) and is only updated with reviews that really reached the dataset, so a failed run never hides anything. Give each schedule its own `stateKey` (two schedules sharing a key would hide each other's reviews), and tick `resetState` once to start over. With **Newest first**, reading a business stops at its first review already delivered. With oldest-first sorting, each monitoring run reads the business's review pages to the end (new reviews are at the end). With **Scrape reviews** off, the memory holds businesses instead: only businesses never delivered are returned.

#### Filter by date

`postedAfter` and `postedBefore` take a date (`2026-09-01`, the whole day is included: the day is the one Yelp prints on the review, in the business's own time zone) or a period before now (`7 days`, `2 weeks`, `1 month`; via the API also `24 hours` or a full ISO date-time, which are exact moments in UTC). With **Newest first** and `postedAfter`, reading a business stops at its first older review; with **Oldest first** and `postedBefore`, at its first newer one.

#### Coming from another Yelp scraper?

The input field names of the other Yelp Actors of the Store work here too (for example `biz_urls`, `maxReviews`, `reviewsSort`, `include_personal_data`, `searchTerms`, `price`, `open_now`): paste your old input and it runs. When one of them and our own field are both set, ours wins, and the log says so.

### 🔌 Integrations and API

Call the Actor via the Apify API, the JavaScript or Python clients, or connect it with integrations and webhooks (Make, Zapier, n8n, Google Sheets, Slack, Airtable…). The dataset can be fetched as JSON or CSV from any tool.

### 🤖 Use with AI agents (MCP)

AI agents (Claude, ChatGPT, Cursor…) can find and run this Actor through the [Apify MCP server](https://mcp.apify.com), billed to their Apify account like any run. It returns one item per Yelp review (or per business with `includeReviews` off). Actor id: `nice_dev/yelp-reviews-scraper`; MCP server with this Actor only: `https://mcp.apify.com/?tools=fetch-actor-details,nice_dev/yelp-reviews-scraper`.

Smallest input, for a cheap first call:

```json
{
    "startUrls": [{ "url": "https://www.yelp.com/biz/golden-boy-pizza-san-francisco" }],
    "maxItems": 10
}
```

Key output fields: `rating`, `text`, `publishedAt`, `ownerResponse`, `reviewer`, `businessName`, `businessRating` and `details` (with `includeBusinessDetails`).

Cost: per review saved, plus a small fee per run start; the options are charged only when turned on — see the pricing section above and the **Pricing** tab. Cap each call with `maxItems` and, through the API, with the run option `maxTotalChargeUsd`.

### ❓ FAQ

#### Is it legal to scrape Yelp?

The Actor only reads what Yelp shows publicly to any anonymous visitor. It logs in to nothing and solves no captcha. Reviews carry the reviewer's public display name (first name and initial), city and photo: this is personal data, protected by GDPR and CCPA. Turn **Include reviewer details** off to leave it out, and do not store it without a legitimate reason. You are responsible for using the data in compliance with Yelp's Terms of Service and applicable law. This Actor is not affiliated with Yelp.

#### Where do the e-mail addresses come from?

With **Find e-mails on business websites** on, the Actor reads the pages each business publishes on its own website (home page, contact page, legal notice) and returns the contact addresses shown there: what any visitor sees. It does not log in, guess addresses, fill contact forms or bypass any protection. Some of these addresses are personal data under GDPR (for example `firstname.lastname@company.com`): you are responsible for having a lawful basis before using them, for informing the people concerned and for honouring opt-outs. Rules for B2B e-mail prospecting differ by country (opt-out in some, prior consent in others).

#### Does it need a login or a proxy?

No login. The proxy is included in the price: leave the default setting (the residential proxy is not available). A request Yelp turns away is retried at once on a new proxy session, up to 10 times on top of the retries (without a proxy, after a pause of 5 seconds, doubled at each retry up to 150 seconds).

#### Is the data safe to open in Excel or to show on a web page?

Reviews and owner replies are the users' own words, copied as they are. A text can begin with `-`, `+`, `=` or `@`: Excel and Google Sheets may read such a cell of a CSV file as a formula or as a number. The Actor leaves the text as it is, so that the JSON and the API give the real value: when you open a CSV, import these columns as text. On a web page, escape every field like any text written by a stranger.

#### Known limitations

- Reviews Yelp does not recommend are not shown on the business page: only their number is given (`details.notRecommendedReviewCount`).
- A search returns at most 25 businesses per order (75 with all three); sponsored results of a search page are not returned.
- Yelp's "business highlights" badges, the booking link of a business and the date a reviewer joined Yelp are not available.
- `onlyNew` remembers review ids, not their content: a review edited after it was delivered is not returned again.
- Two runs sharing the same `stateKey` at the same time may both return the same new review.
- A business skipped by a filter is not remembered by `onlyNew`: its rating, prices or hours can change, so each monitoring run checks it again (and charges the filter fee again).
- E-mails: the Actor reads the business's home page and up to 2 pages it links to (contact, legal notice, about), 20 seconds at most per website, without running its JavaScript. A website behind an anti-bot wall, or one that writes its addresses with JavaScript or in an image, gives no e-mail (and no charge). Social media websites are never visited: their links are read on the business's own website.

**A run that reaches its timeout** stops itself about 45 seconds before it: no new page is asked, what it read is saved and, with `onlyNew`, remembered, and the run ends *Succeeded* with "Stopped before the run's timeout". Resurrect it to go on from there, or give the next run a longer timeout (Run options).

**A run the platform stops without warning** (out of memory)

- Resurrect it: it goes on from where it stood at most a minute before the stop. What it had read since is read again, and the reviews already saved are skipped: none is delivered or charged twice, and `maxItems` still counts them.
- With `onlyNew`, the memory is saved after each write (at most once every 2 seconds): resurrect the stopped run and the reviews it had saved meanwhile join the memory; leave it stopped for good, and the next run may return the reviews of its last 2 seconds once more.

#### Something doesn't work?

The last line of the log counts the reviews saved, filtered out and no longer on Yelp, and the requests that failed after every retry. Those requests are listed, with the reason, in the `FAILED_REQUESTS` record of the run's key-value store. A run that saved nothing and had failed requests fails, and its last message gives the cause. A business link or id that does not exist is skipped with a warning that names it.

If Yelp changes its site, you are told instead of paying for blank rows: the run stops and fails with a message that names what changed. If the first 20 reviews read all lack their stars, text, language, date, business name or — with full details — address, the run saves nothing more, stops and fails, and its last message names the missing field: at most those first reviews are charged. A review that `postedAfter` / `postedBefore` drops because it has no date at all counts among those 20. A run of fewer reviews (a scheduled `onlyNew` run that finds a few new ones, a small **Max results**) is checked at its end, from 5 reviews: its reviews are already saved, and the run fails with the missing field instead of ending green.

### 🛟 Support

Open an issue in the **Issues** tab with a link to your run: the run log and the `FAILED_REQUESTS` record of the key-value store show exactly which businesses failed and why.

# Actor input Schema

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

Yelp business pages (`https://www.yelp.com/biz/golden-boy-pizza-san-francisco`, any Yelp country domain: yelp.co.uk, yelp.fr, yelp.ca…) or Yelp search pages (`https://www.yelp.com/search?find_desc=pizza&find_loc=San+Francisco`: the keyword and location are read from the URL). Max 1 000 URLs.

## `businessIds` (type: `array`):

Yelp business ids (22 characters, e.g. `PTFxtXS47ZVRCdZIrEWvGw`) or aliases, the last part of a business URL (e.g. `golden-boy-pizza-san-francisco`). Up to 1 000 entries, each up to 200 characters.

## `query` (type: `string`):

What to search on Yelp, as typed in its search box (e.g. `pizza`, `plumber`, `dentist`). Needs a **Location**. Each search returns up to 25 businesses per search order (up to 75 with **Search order** = all three).

## `searchQueries` (type: `array`):

Several keywords in one run: one search per keyword and per location. Added to **Search keyword**; a business found by several searches is read once. Up to 100 entries, each up to 200 characters.

## `location` (type: `string`):

City, neighborhood or ZIP code, as typed on Yelp (e.g. `San Francisco, CA`, `94133`, `London`). Tip: several ZIP codes or neighborhoods find many more businesses than one city.

## `locations` (type: `array`):

Several locations in one run: every keyword is searched in every location (3 keywords × 4 locations = 12 searches, max 500). Added to **Location**. Up to 100 entries, each up to 200 characters.

## `latitude` (type: `number`):

With **Longitude**: also searches around this GPS point, e.g. `37.7998`. You can also type `37.7998,-122.4081` directly in **Location**.

## `longitude` (type: `number`):

With **Latitude**, e.g. `-122.4081`.

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

Order of the Yelp search. Yelp returns at most 25 businesses per search and order: `All three orders` merges recommended, highest rated and most reviewed (up to 75 different businesses per keyword and location).

## `maxBusinessesPerSearch` (type: `integer`):

Businesses kept from each search (keyword × location, or search URL), in Yelp's order. 0 = all the search returns (up to 75).

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

On = one result per review. Off = businesses only: one result per business with its full details (phone, website, address, GPS, hours, amenities, health inspections, popular dishes, star and language breakdown) and no review.

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

Maximum number of results for the whole run (reviews, or businesses when **Scrape reviews** is off), after filters. 0 = no limit.

## `maxItemsPerQuery` (type: `integer`):

Cap for EACH business, so that the first business cannot use up the whole **Max results**. With **Scrape reviews** off: cap of businesses per search. 0 = no cap (every review Yelp shows: all of them can be read).

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

Order in which Yelp returns the reviews (and in which the caps above keep them). `Newest first` is the fastest with **Posted after** and with monitoring: reading stops at the first older or already delivered review.

## `translateTo` (type: `string`):

Two-letter language code (e.g. `en`, `fr`, `es`, `de`, `ja`): Yelp's own translation of each review is added in `translatedText` (free, original text kept). Empty = no translation.

## `includeReviewerDetails` (type: `boolean`):

Reviewer's display name, location, profile link and photo, review / friend / photo counts and Elite status. Off = the `reviewer` field is null (same columns, no personal data). You are responsible for how you use personal data (GDPR, CCPA).

## `includeBusinessDetails` (type: `boolean`):

Adds to each review its business's `details`: phone, website, full address, GPS, price range, opening hours, open now / closed, claimed, Yelp summary, year established, history, specialties, owner, attributes, amenities (~30), health inspections, popular dishes, review highlights, menu link, licenses, photo count, questions and answers (small extra requests per business, charged once per business; see Pricing). Always included with **Scrape reviews** off.

## `maxBusinessPhotos` (type: `integer`):

Business photo gallery (full-size URL + caption), read 30 per page, charged per page read (see Pricing). The gallery is written on the first row of each business (`businessPhotos`); its other rows say null. 0 = none (the main photo is always included).

## `enrichEmails` (type: `boolean`):

Visits each business's own website (home page + contact / legal pages, 3 pages max, once per business) and adds the e-mail addresses published there to `emails`, and the Facebook, Instagram, X, TikTok, YouTube, LinkedIn and Pinterest links of its home page to `socialLinks`. Slower. Charged as a separate `email-enriched` event, once per business where at least one e-mail is found.

## `starRatings` (type: `array`):

Only reviews with these stars (several allowed). Empty = all.

## `postedAfter` (type: `string`):

Only reviews posted on or after this date: `2026-09-01` (the day as Yelp prints it on the review, in the business's own time zone), or a period before now such as `7 days`, `2 weeks`, `1 month` (API: `24 hours` and full ISO date-times work too).

## `postedBefore` (type: `string`):

Only reviews posted on or before this date (the whole day is included, as Yelp prints it on the review, in the business's own time zone), or older than a period such as `30 days`.

## `reviewLanguages` (type: `array`):

Only reviews written in these languages, as two-letter codes (`en`, `es`, `fr`…). Empty = all languages.

## `keywords` (type: `array`):

Only reviews whose text contains at least one of these words or phrases (whole words, case and accents ignored; the text is the review as its author wrote it, not its translation). Empty = all. Up to 50 entries, each up to 100 characters.

## `excludeKeywords` (type: `array`):

Drop the reviews whose text contains one of these words or phrases (whole words, case and accents ignored; the text is the review as its author wrote it, not its translation). Up to 50 entries, each up to 100 characters.

## `withResponseOnly` (type: `boolean`):

Keep only the reviews the business owner or manager has publicly answered.

## `withPhotosOnly` (type: `boolean`):

Keep only the reviews that include at least one photo or video.

## `minRating` (type: `number`):

Skip the businesses whose overall Yelp rating is below this (e.g. `4`). Checked on the first page of reviews, before reading the others. Empty = all businesses.

## `minReviewCount` (type: `integer`):

Skip the businesses with fewer reviews than this on Yelp. Empty = all businesses.

## `requirePhone` (type: `boolean`):

Skip the businesses that show no phone number on Yelp (checked with 1 small extra request per business, not charged).

## `requireWebsite` (type: `boolean`):

Skip the businesses that show no website on Yelp (same check as above).

## `priceLevels` (type: `array`):

Only businesses with one of these Yelp price ranges (several allowed). Businesses with no price range on Yelp are skipped when this is set. Checked for 25 businesses at a time with 1 small request, not charged. Empty = all.

## `openNow` (type: `boolean`):

Skip the businesses that are closed at the time of the run (Yelp's opening hours this week, in the business's own time zone; same small request as **Price range**, not charged).

## `features` (type: `array`):

Only businesses that show ALL these amenities on Yelp, as written on the business page (e.g. `Outdoor seating`, `Offers delivery`, `Wheelchair accessible`, `Dogs allowed`; case ignored). Checked with 1 small extra request per business, not charged; a business that lacks one is skipped. Empty = all. Up to 20 entries, each up to 100 characters.

## `onlyNew` (type: `boolean`):

Skip the reviews (or businesses, with **Scrape reviews** off) that a previous run with the same **Memory key** already delivered: they are not saved and not charged. With `Newest first`, reading a business stops at its first known review. First run = everything is new.

## `stateKey` (type: `string`):

Name of the memory used by **Only new reviews**. Give each schedule / task its own key (e.g. `my-restaurants`) so that they do not share their memory. Letters, digits, `-` and `_`.

## `resetState` (type: `boolean`):

Forget everything remembered under this **Memory key** before the run: this run returns (and charges) every review again. Untick it afterwards.

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

Apify Proxy or your own proxies. Keep the default: it is included in the price. The residential Apify proxy is not available in this Actor (not needed for Yelp).

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

Maximum number of requests processed in parallel.

## `maxRequestsPerMinute` (type: `integer`):

Most requests to Yelp in any 60 seconds, all of them counted (searches, review pages of 10 reviews, business details, photo pages). A budget, not an even pace: spread them with the minimum delay below. Lower it if Yelp answers HTTP 429 / 403 in the log.

## `minRequestIntervalMs` (type: `integer`):

Smallest gap between two requests, in milliseconds. Unlike the per-minute rate, this spreads the requests evenly instead of letting them go out in a burst. 0 = no gap.

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

Retries per request before it is marked as failed. Behind a proxy, a request Yelp turns away is also retried on a new proxy session up to 10 times without using up these retries.

## `debugLog` (type: `boolean`):

Include debug messages in the run log.

## `biz_urls` (type: `array`):

Same as Yelp URLs (name used by other Yelp scrapers).

## `businessUrls` (type: `array`):

Same as Yelp URLs.

## `directUrls` (type: `array`):

Same as Yelp URLs.

## `search_urls` (type: `array`):

Same as Yelp URLs.

## `urls` (type: `array`):

Same as Yelp URLs.

## `businesses` (type: `array`):

Same as Yelp URLs: a Yelp link goes there, a business id or an alias goes to Business ids.

## `biz_ids` (type: `array`):

Same as Business ids or aliases.

## `placeIds` (type: `array`):

Same as Business ids or aliases.

## `placeSlugs` (type: `array`):

Same as Business ids or aliases.

## `searchTerm` (type: `string`):

Same as Search keyword.

## `searchQuery` (type: `string`):

Same as Search keyword.

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

Same as Location.

## `search_location` (type: `string`):

Same as Location.

## `searchLocations` (type: `array`):

Same as More locations.

## `search_sort` (type: `string`):

Same as Search order.

## `searchLimit` (type: `integer`):

Same as Max businesses per search.

## `maxResults` (type: `integer`):

Same as Max results.

## `maxReviewsPerBusiness` (type: `integer`):

Same as Max reviews per business.

## `maxReviewsPerUrl` (type: `integer`):

Same as Max reviews per business.

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

Same as Max reviews per business.

## `reviews_limit` (type: `integer`):

Same as Max reviews per business.

## `reviews_sort` (type: `string`):

Same as Review order.

## `reviewsSort` (type: `string`):

Same as Review order.

## `reviews_rating` (type: `array`):

Same as Star ratings.

## `ratings` (type: `array`):

Same as Star ratings.

## `date_from` (type: `string`):

Same as Posted after.

## `dateFrom` (type: `string`):

Same as Posted after.

## `dateTo` (type: `string`):

Same as Posted before.

## `language` (type: `string`):

Same as Review languages (one code).

## `reviews_keywords` (type: `array`):

Same as Keywords.

## `reviews_translate` (type: `string`):

Same as Translate reviews to.

## `include_personal_data` (type: `boolean`):

Same as Include reviewer details.

## `fetchBusinessDetails` (type: `boolean`):

Same as Add full business details.

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

Same as Scrape reviews.

## `maxImages` (type: `integer`):

Same as Business photos per business.

## `incremental` (type: `boolean`):

Same as Only new reviews.

## `monitorKey` (type: `string`):

Same as Memory key.

## `open_now` (type: `boolean`):

Same as Only businesses open now.

## `priceLevel` (type: `string`):

Same as Price range (`$$`, or `1,2`).

## `searchPrice` (type: `string`):

Same as Price range (`$$`, or `1,2`).

## `minPrice` (type: `integer`):

Lowest price range, 1 ($) to 4 ($$$$): same as Price range.

## `maxPrice` (type: `integer`):

Highest price range, 1 ($) to 4 ($$$$): same as Price range.

## `searchFeatures` (type: `array`):

Same as Required amenities.

## `search_features` (type: `array`):

Same as Required amenities.

## `lat` (type: `number`):

Same as Latitude.

## `lon` (type: `number`):

Same as Longitude.

## `lng` (type: `number`):

Same as Longitude.

## Actor input object example

```json
{
  "startUrls": [
    {
      "url": "https://www.yelp.com/biz/golden-boy-pizza-san-francisco"
    }
  ],
  "businessIds": [],
  "searchQueries": [],
  "locations": [],
  "searchSortBy": "all",
  "maxBusinessesPerSearch": 0,
  "includeReviews": true,
  "maxItems": 100,
  "maxItemsPerQuery": 0,
  "sortBy": "newest",
  "includeReviewerDetails": true,
  "includeBusinessDetails": false,
  "maxBusinessPhotos": 0,
  "enrichEmails": false,
  "starRatings": [],
  "reviewLanguages": [],
  "keywords": [],
  "excludeKeywords": [],
  "withResponseOnly": false,
  "withPhotosOnly": false,
  "requirePhone": false,
  "requireWebsite": false,
  "priceLevels": [],
  "openNow": false,
  "features": [],
  "onlyNew": false,
  "stateKey": "default",
  "resetState": false,
  "proxyConfiguration": {
    "useApifyProxy": true
  },
  "maxConcurrency": 4,
  "maxRequestsPerMinute": 120,
  "minRequestIntervalMs": 0,
  "maxRequestRetries": 5,
  "debugLog": false
}
```

# 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": [
        {
            "url": "https://www.yelp.com/biz/golden-boy-pizza-san-francisco"
        }
    ],
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("nice_dev/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": [{ "url": "https://www.yelp.com/biz/golden-boy-pizza-san-francisco" }],
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("nice_dev/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": [
    {
      "url": "https://www.yelp.com/biz/golden-boy-pizza-san-francisco"
    }
  ],
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call nice_dev/yelp-reviews-scraper --silent --output-dataset

```

## MCP server setup

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