# Yelp Scraper: Businesses, Reviews, Menus - No Login (`cliqtomedia/yelp-scraper`) Actor

Get Yelp business profiles, phones, websites, hours, photos, menus and reviews from a search or link. Track new reviews over time. No login or API key.

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

## Pricing

from $1.89 / 1,000 business profiles

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

Search [Yelp](https://www.yelp.com) by keyword and city, or paste business links, and get profiles with phones, websites, hours, photos, menus and reviews. Rows land in a table you can export to CSV, Excel or JSON, or read by API. You need no login and no API key, and 10 businesses take about a minute and cost about $0.044.

![Yelp Scraper turns a search or business link into a table of profiles, phones, websites, menus and reviews](https://api.apify.com/v2/key-value-stores/vNIj1cqCfw9danayl/records/hero-20261104.png)

### Table of contents

- [What it does](#what-it-does)
- [How it works](#how-it-works)
- [Quick start](#quick-start)
- [Use cases](#use-cases)
- [Input](#input)
- [Output](#output)
- [Pricing](#pricing)
- [Limits](#limits)
- [API, export and integrations](#api-export-and-integrations)
- [Troubleshooting](#troubleshooting)
- [FAQ](#faq)
- [Related Actors](#related-actors)
- [Support](#support)

### What it does

Pick one of three modes in **What to collect**:

- **Find businesses:** run a Yelp search by keyword and location, or from a Yelp search link, and save one full profile per business.
- **Business profiles:** read the profiles for business links, aliases or IDs you already have.
- **Reviews:** save one row per review for the businesses you list, with text, rating, date, language and owner reply.

Optional extras add menus, more photos, questions with answers, and review rows next to each profile. Monitoring mode saves only businesses and reviews it has not seen in earlier runs.

#### Good fit

- You build a local lead list with phones and websites for a category and city.
- You compare ratings, price levels and amenities across competing venues.
- You read new reviews of your own or rival businesses on a schedule.
- You collect menu items and prices for restaurant research.

It is not a good fit if you need owner emails, reviewer contact details or private account data. Those fields are not collected. For a whole metro area, split the search by neighborhood or ZIP code, because each Yelp search stops at 240 positions, which give about 200 different businesses.

> **👉 [Try it now: open the input form](https://console.apify.com/actors/gneubWrrN8lvn56RD/input)**

### How it works

1. You enter a search, or the businesses you already know, and choose what to collect.
2. The run reads public Yelp pages and data feeds. You supply no account, cookie or proxy.
3. Each business or review becomes one row. Open the rows in the **Output** tab, export them, or fetch them by API.

If one business cannot be read, the run skips it, writes the reason to `RUN_SUMMARY` and moves on.

> **👉 [Try it now: open the input form](https://console.apify.com/actors/gneubWrrN8lvn56RD/input)**

### Quick start

[![Input form with What to collect, Search query, Search location and Maximum results marked](https://api.apify.com/v2/key-value-stores/vNIj1cqCfw9danayl/records/quick-start-form-20261104.png)](https://console.apify.com/actors/gneubWrrN8lvn56RD/input)

1. Open the **Input** tab and keep **What to collect** on **Find businesses** (box 1).
2. Keep **coffee** in **Search query**, or type your own keyword (box 2).
3. Keep **San Francisco** in **Search location**, or type your own city (box 3).
4. Keep **Maximum results** at **10** (box 4).
5. Click **Start**.

[![Output table with the Output tab and the name, rating, reviewsCount, address, phone and website columns marked](https://api.apify.com/v2/key-value-stores/vNIj1cqCfw9danayl/records/output-table-20261104.png)](https://console.apify.com/actors/gneubWrrN8lvn56RD/input)

6. When the run ends, open the **Output** tab (box 6).
7. Check `name`, `rating`, `reviewsCount`, `address.formatted`, `phone` and `website` (box 7). Some businesses publish no phone or website, so those cells can show `null`.

**Expected result:** 10 business rows in about a minute, for about $0.044 on the Free plan.

> **👉 [Try it now: open the input form](https://console.apify.com/actors/gneubWrrN8lvn56RD/input)**

### Use cases

| Buyer job | Input path | Output entity | Key fields | Next integration |
| --- | --- | --- | --- | --- |
| Build a local lead list | Find businesses, keyword and city, **Businesses with a website** on | Business | `name`, `phone`, `website`, `address`, `categories` | CSV for a CRM or outreach sheet |
| Compare rival venues | Business profiles, list of links | Business | `rating`, `reviewsCount`, `priceRange`, `amenities`, `hours` | Google Sheets or BI table |
| Watch new reviews | Reviews, business IDs, **Only new results** on | Review | `rating`, `text`, `date`, `ownerReply`, `url` | Apify schedule plus Slack or Notion summary |
| Study restaurant menus | Business profiles, **Menu and popular dishes** on | Business | `menu`, `popularDishes`, `menuUrl` | JSON for pricing analysis |
| Analyse customer opinions | Reviews, date range and keywords | Review | `text`, `language`, `translatedText`, `reactions` | Text analysis or LLM pipeline |

> **👉 [Try it now: open the input form](https://console.apify.com/actors/gneubWrrN8lvn56RD/input)**

### Input

#### Input fields

| Field | Plain name | Type | Required | Default / prefill | Allowed values | Effect | Example | Recommendation |
| --- | --- | --- | --- | --- | --- | --- | --- | --- |
| `mode` | What to collect | String | Yes | `search` | `search`, `business`, `reviews` | Picks the kind of rows you get | `reviews` | Start with `search` |
| `query` | Search query | String | For a search | prefill `coffee` | Text | Keyword, category or name to look up | `plumber` | Needs a location too |
| `location` | Search location | String | For a search | prefill `San Francisco` | Text | City, address, neighborhood or ZIP | `94103` | Narrow areas find more in total |
| `businessUrls` | Business URLs or aliases | Array | For business links | empty | Yelp `/biz/` links or aliases | Reads these businesses | `gary-danko-san-francisco` | Regional Yelp links work too |
| `businessIds` | Business IDs | Array | No | empty | Yelp IDs | Reads reviews without a profile lookup | `WavvLdfdP6g8aZTtbBQHTw` | Cheapest path for review monitors |
| `searchTerms` | More search queries | Array | No | empty | Text | Runs each query in each location, replaces **Search query** | `["bakery","deli"]` | Multiplies search pages |
| `locations` | More search locations | Array | No | empty | Text | Replaces **Search location** | `["Oakland","Berkeley"]` | Use to cover a metro area |
| `maxItems` | Maximum results | Integer | No | `10` | 1 or more | Total saved rows, business and review rows together | `100` | Main cost control |
| `maxBusinessesPerSearch` | Businesses per search | Integer | No | `240` | 1 or more | Caps one query and location pair | `50` | Lower it for many pairs |
| `searchSort` | Search order | String | No | `recommended` | `recommended`, `rating`, `review_count`, `distance` | Yelp order for results | `rating` | Keep the default for full lists |
| `category` | Category alias | String | No | empty | Yelp category alias | Moves results toward a category. Yelp can still return nearby matches from other categories | `coffee` | Optional |
| `priceLevels` | Price levels | Array | No | empty | `1`, `2`, `3`, `4` | Filters on Yelp's search page | `["1","2"]` | Optional |
| `features` | Business features | Array | No | empty | Yelp feature keys | Filters on Yelp's search page | `DogsAllowed`, `WiFi.free` | Optional |
| `openNow` | Open now | Boolean | No | `false` | true, false | Asks Yelp for open businesses, then drops any whose profile says closed. Unknown hours stay | `true` | Each dropped profile costs `detail-page` |
| `includeAds` | Include sponsored results | Boolean | No | `false` | true, false | Keeps sponsored search rows | `true` | Marked with `isAd` |
| `searchUrls` | Yelp search URLs | Array | No | empty | Yelp `/search` links | Replaces query and location, starts from the first page | `https://www.yelp.com/search?find_desc=pizza&find_loc=Boston` | Copy filters from Yelp |
| `minRating` | Minimum business rating | Number | No | `0` | 0 to 5 | Drops businesses below this rating, not reviews | `4` | The read still costs `detail-page` |
| `minReviews` | Minimum business review count | Integer | No | `0` | 0 or more | Drops businesses with fewer reviews | `50` | The read still costs `detail-page` |
| `onlyWithWebsite` | Businesses with a website | Boolean | No | `false` | true, false | Drops businesses without a website | `true` | The read still costs `detail-page` |
| `includeReviews` | Also collect reviews | Boolean | No | `false` | true, false | Adds review rows after each business | `true` | Set **Maximum results** for both kinds |
| `maxReviewsPerBusiness` | Reviews per business | Integer | No | `100` | 1 or more | Caps reviews for one business | `20` | Lower it for wide searches |
| `reviewsSort` | Review order | String | No | `newest` | `recommended`, `newest`, `oldest`, `rating_desc`, `rating_asc`, `elites` | Yelp review order | `newest` | Keep `newest` for monitors |
| `ratings` | Review ratings | Array | No | empty | `1` to `5` | Keeps reviews with these stars | `["1","2"]` | Good for complaints |
| `language` | Review language | String | No | `en` | Language code, empty for all | Filters reviews by language | `es` | Clear it to get every language |
| `keywords` | Review keywords | Array | No | empty | Text | Keeps reviews with at least one word | `["parking"]` | Filtered pages still cost |
| `dateFrom` | Reviews from | String | No | empty | `YYYY-MM-DD` or `30 days`, `2 months` | Oldest review date | `30 days` | Stops early with `newest` |
| `dateTo` | Reviews through | String | No | empty | `YYYY-MM-DD` | Newest review date, inclusive | `2026-10-31` | Optional |
| `translateTo` | Translate reviews to | String | No | empty | Language code | Adds `translatedText` where Yelp has it | `en` | Recommended reviews only |
| `reviewType` | Review list | String | No | `recommended` | `recommended`, `not_recommended`, `removed` | Picks Yelp's review list | `not_recommended` | The other two lists have fixed order |
| `includeReviewerDetails` | Public reviewer details | Boolean | No | `false` | true, false | Adds name, profile link, review count and Elite year | `true` | Leave off unless needed |
| `maxPhotos` | Photos per business | Integer | No | `20` | 0 or more | First 25 come with the profile, more load paid pages | `35` | Keep at 25 or lower to avoid page fees |
| `maxQuestions` | Questions per business | Integer | No | `2` | 0 or more | Up to 2 include a top-answer preview, more load paid pages | `3` | Keep at 2 or lower to avoid page fees |
| `includeMenu` | Menu and popular dishes | Boolean | No | `false` | true, false | Adds `menu` and `popularDishes` | `true` | Many businesses have no menu on Yelp |
| `onlyNew` | Only new results | Boolean | No | `false` | true, false | Saves only rows not seen in earlier runs | `true` | Needs **State name** |
| `stateName` | State name | String | With **Only new results** | empty | Letters, numbers, dashes | Names the memory shared between runs | `sf-coffee` | Use one name per monitor |
| `deliveryConnector` | Send results to (optional) | String | No | empty | Slack, Notion or another MCP connector | Sends a short summary after the run | Slack | See below |
| `deliveryTarget` | Notion page or channel (optional) | String | With some connectors | empty | Notion page link, Slack channel ID | Where the summary goes | `C0123456789` | Depends on the connector |

#### Interacting settings

| When | Input A | Input B | Effective behavior | Example | Cost or result effect |
| --- | --- | --- | --- | --- | --- |
| Lists replace single fields | `searchTerms` | `query` | The list wins | `["deli"]` and `coffee` | Only `deli` is searched |
| Links replace text | `searchUrls` | `query`, `location` | Links win | a pizza link and `coffee` | Only the link is searched |
| Find businesses gets links too | `businessUrls` | `query` | Both run | one link and one search | You pay for both |
| Reviews next to profiles | `includeReviews` | `maxItems` | Both kinds count toward the total | `maxItems` 50 | Profiles can use up the total before reviews |
| Filters run after the read | `minRating`, `minReviews`, `onlyWithWebsite`, `openNow` | `search` and `business`, not `reviews` | Rejected profile saves no row | `minRating` 4 | Each rejected profile costs one `detail-page` |
| Date limit and order | `dateFrom` | `reviewsSort` | With `newest`, reading stops at the first old page | `30 days` | Other orders read every page |
| Non-recommended lists | `reviewType` | `reviewsSort`, `language`, `translateTo` | The last three apply only to `recommended` | `removed` | Translation and language stay `null` |
| Monitor needs a name | `onlyNew` | `stateName` | No name means the run fails before any read | `onlyNew` alone | Costs the start fee only |

#### Input examples

Search for businesses with a website:

```json
{
  "mode": "search",
  "query": "dentist",
  "location": "Austin, TX",
  "maxItems": 100,
  "onlyWithWebsite": true
}
```

**Expected output:** up to 100 business rows that have a website.

**Cost note:** about 12 search pages plus 100 businesses, about $0.47 on the Free plan. Each rejected profile adds $0.0014. Set a timeout of 10 minutes in **Run options**, because 100 search rows took about 6 to 7 minutes.

Read one profile with menu and extra photos:

```json
{
  "mode": "business",
  "businessUrls": ["https://www.yelp.com/biz/sotto-mare-san-francisco-4"],
  "includeMenu": true,
  "maxPhotos": 35
}
```

**Expected output:** one business row with `menu`, `popularDishes` and up to 35 items in `photos`.

**Cost note:** about $0.003 for the profile, plus $0.0014 for each extra photo page.

Monitor the newest reviews of one business:

```json
{
  "mode": "reviews",
  "businessIds": ["WavvLdfdP6g8aZTtbBQHTw"],
  "maxItems": 100,
  "reviewsSort": "newest",
  "dateFrom": "30 days",
  "onlyNew": true,
  "stateName": "gary-danko-reviews"
}
```

**Expected output:** first run saves the matching reviews. Later runs save only reviews not seen before, and the dataset can be empty.

**Cost note:** a later run with nothing new costs the start fee plus $0.0014 per review page read, from about $0.0017.

> **👉 [Try it now: open the input form](https://console.apify.com/actors/gneubWrrN8lvn56RD/input)**

### Output

#### Output fields

| Field | Meaning | Type | Can be empty? | Example / enum | Source / notes |
| --- | --- | --- | --- | --- | --- |
| `recordType` | Row kind | String | No | `business`, `review` | Set by the run |
| `status` | Row completeness | String | No | `complete` | Set by the run |
| `source` | Data source | String | No | `Yelp` | Set by the run |
| `businessId` | Yelp business ID | String | No | `UXCtOlad97FzZNWyxOii3g` | Use for later review runs |
| `name` | Business name | String | Business rows only | `Q Specialty Coffee` | Profile |
| `alias` | Yelp link slug | String | Business rows only | `q-specialty-coffee-san-francisco` | Profile |
| `businessName` | Business of this review | String | Review rows only | `Gary Danko` | Review |
| `businessAlias` | Slug of that business | String | Review rows only | `gary-danko-san-francisco` | Review |
| `reviewId` | Yelp review ID | String | Review rows only | `xtEERBKGS2OT72htwE2oDA` | Review |
| `url` | Yelp link to the row | String | No | `https://www.yelp.com/biz/...` | Profile or review |
| `rating` | Star rating | Number | Yes | `4.2` | Average on businesses, stars on reviews |
| `reviewsCount` | Yelp review total | Integer | Yes | `356` | Profile |
| `categories` | Yelp categories | Array | Empty array | `{alias, title}` | Profile |
| `address` | Street, city, region, postal code, country and `formatted` | Object | Yes | `3490 California St, Ste A` | Profile |
| `neighborhoods` | Yelp neighborhoods | Array | Empty array | `Presidio Heights` | Profile |
| `coordinates` | Latitude and longitude | Object | Yes | `37.786916, -122.451689` | Profile |
| `phone` | Public phone | String | Yes, often | `(415) 757-0536` | `null` if the business lists none |
| `website` | Business website | String | Yes | `http://www.qspecialtycoffee.com` | `null` if the business lists none |
| `menuUrl` | Menu link | String | Yes, often | Link | Profile |
| `priceRange` | Price level | String | Yes | `$$` | Profile |
| `isClosed` | Closed for good | Boolean | Yes | `false` | Profile |
| `isOpenNow` | Open at read time | Boolean | Yes | `true` | Profile |
| `hours` | Opening hours | Array | Empty array | Weekday and times | Profile |
| `specialHours` | Holiday hours | Array | Yes | Date and times | Profile |
| `description` | Text from the business | String | Yes | Text | Profile |
| `summary` | Yelp's summary | String | Yes | Text | Profile |
| `yearEstablished` | Founding year | Integer | Yes, often | `1999` | Profile |
| `history` | Business history text | String | Yes, often | Text | Profile |
| `amenities` | Name, label and value | Array | Empty array | `Validated parking` | Profile |
| `photos` | Photo or video items | Array | Empty array | `{photoId, url, caption, label}` | For business videos, `url` is the thumbnail |
| `photosCount` | Photos on Yelp | Integer | Yes | `120` | Profile |
| `questions` | Questions and answers | Array | Empty array | `{text, answers}` | Answer depth depends on `maxQuestions` |
| `popularDishes` | Popular menu items | Array | Yes | `{name, priceText}` | With **Menu and popular dishes** |
| `menu` | Menu items with prices | Array | Yes, or absent | Item name and price | With **Menu and popular dishes**. `null` if the business has none or Yelp refused the menu, and `menuBlocked` in `RUN_SUMMARY` counts refusals |
| `ranking` | Position in the search | Integer | Yes | `3` | Search rows, order changes between runs |
| `isAd` | Sponsored result | Boolean | Yes | `false` | Search rows |
| `searchQuery` | Query that found it | String | Yes | `coffee` | Search rows |
| `searchLocation` | Location that found it | String | Yes | `San Francisco` | Search rows |
| `snippet` | Short text Yelp shows on the search page, usually from a review | String | Yes | `Just discovered the great coffee shop...` | Search rows |
| `text` | Review text | String | Review rows only | Text | Review |
| `translatedText` | Yelp translation | String | Yes | Text | With **Translate reviews to** |
| `language` | Review language | String | Yes | `en` | Review |
| `date` | Review date, UTC | String | Review rows only | `2026-11-02T04:16:53Z` | Review |
| `reactions` | Reader reactions | Object | Yes | `{helpful, thanks, love_this, oh_no}` | Review |
| `videos` | Review videos | Array | Empty array | Link | Review |
| `ownerReply` | Reply from the business | Object | Yes | `{text, date}` | Review |
| `previousReviews` | Earlier reviews by the same person | Array | Empty array | `{rating, text, date}` | Review |
| `reviewer` | Reviewer details | Object | Yes, or absent | Display name, profile link | With **Public reviewer details** |
| `recommendationStatus` | Yelp review list | String | Yes | `not_recommended` | Non-recommended lists |
| `fetchedAt` | Read time, UTC | String | No | `2026-11-04T12:05:48Z` | Set by the run |

`null` means Yelp shows no value for that field. An empty array means the list exists and has no items. A field is absent only when the row kind does not use it or its option is off.

#### Output entities and surfaces

| Situation | Dataset, API, KVS or live view | Result shape | User action |
| --- | --- | --- | --- |
| Normal | Dataset table with **Business profiles**, **Reviews** and **All fields** views, API `/items`, `RUN_SUMMARY` | `status` `complete` | Export or fetch |
| Domain-empty | Empty dataset, `RUN_SUMMARY` `complete` or `not_found` | No rows, counts in the summary | Widen the search or check the link. A monitor with nothing new also ends here |
| Partial | Saved rows stay, run `SUCCEEDED`, `RUN_SUMMARY` `partial`, `stopReason` `ITEMS_SKIPPED`, `CHARGE_LIMIT` or `DEADLINE` | Rows plus `itemErrors`, `itemErrorSample` where relevant | Rerun skipped IDs or raise the limit |
| Technical failure | Run `FAILED`, `RUN_SUMMARY` `error` or `partial`, `stopReason` holds the code | Saved rows stay in the dataset | See Troubleshooting. No page or row fee is taken for a failed read |

`RUN_SUMMARY` also holds `savedCount`, `businessCount`, `reviewCount`, `filteredOut`, `skippedSeen`, `notFound` and `delivery`. `menuBlocked` and `searchRowsUnreadable` appear only when they are above 0. If a business is skipped and the run still reaches `maxItems`, `status` is `complete`, `stopReason` is `MAX_ITEMS` and `itemErrors` still counts the skip. `REPORTS` is the same summary with dataset and run links.

#### Output example

```json
{
  "recordType": "review",
  "status": "complete",
  "source": "Yelp",
  "businessId": "WavvLdfdP6g8aZTtbBQHTw",
  "businessName": "Gary Danko",
  "businessAlias": "gary-danko-san-francisco",
  "reviewId": "xtEERBKGS2OT72htwE2oDA",
  "url": "https://www.yelp.com/biz/gary-danko-san-francisco?hrid=xtEERBKGS2OT72htwE2oDA",
  "rating": 5,
  "text": "Review text as published on Yelp.",
  "translatedText": null,
  "language": "en",
  "date": "2026-11-02T04:16:53Z",
  "reactions": { "helpful": 0, "thanks": 0, "love_this": 0, "oh_no": 0 },
  "photos": [],
  "videos": [],
  "ownerReply": null,
  "previousReviews": [],
  "fetchedAt": "2026-11-03T00:06:42.987Z"
}
```

#### Send results to Slack or Notion

Choose a connector in **Send results to (optional)** and, where asked, fill in **Notion page or channel (optional)**. After the run you get the row count, the status, up to 25 rows, and links to the dataset and the run. Delivery trouble never changes the rows. Its outcome is stored in `delivery` in `RUN_SUMMARY`.

#### Use case → fields

| Use case | Fields to read |
| --- | --- |
| Lead list | `name`, `phone`, `website`, `address.formatted`, `categories` |
| Rival comparison | `rating`, `reviewsCount`, `priceRange`, `amenities`, `hours` |
| Review monitoring | `businessName`, `rating`, `text`, `date`, `ownerReply.text`, `url` |
| Menu research | `menu`, `popularDishes`, `menuUrl` |

> **👉 [Try it now: open the input form](https://console.apify.com/actors/gneubWrrN8lvn56RD/input)**

### Pricing

Pay per event. Platform usage is included in these prices.

| Pricing unit | When you pay | No plan or Free | Gold and above |
| --- | --- | --- | --- |
| Run start | Once per run | $0.00027 | $0.00027 |
| Business | One saved business row | $0.0027 | $0.00189 |
| Search page | One Yelp search page read, including a valid empty page | $0.0165 | $0.01155 |
| Review | One saved review row | $0.000255 | $0.0001785 |
| Detail page | One extra page read: a review page, extra photo or question page, a business that does not exist, or a profile your filter rejected | $0.0014 | $0.00098 |

Paid Apify plans save more: Bronze 10%, Silver 20%, Gold, Platinum and Diamond 30%. The start fee stays the same on every plan.

- **Zero results:** a valid empty search costs the start fee plus one search page, about $0.017. A review page or a missing business costs one detail page.
- **Filter with no match:** you pay for the pages read, because filters run after the read. A rejected profile costs one detail page and saves no row. `filteredOut` in `RUN_SUMMARY` counts every rejected profile and review.
- **Nothing new in a monitor:** you pay for the search or review pages read. Seen businesses are not read again.
- **Partial results:** you pay only for what was saved and read. A failed Yelp response costs nothing, so in a full source outage you pay only the start fee, $0.00027.

#### Cost examples

Free plan prices.

| Scenario | Input scope | Expected item-event count | Base charge | Optional charge | Stop-cap behavior |
| --- | --- | --- | --- | --- | --- |
| 10 businesses | 1 search | 10 business, 1 search page | $0.04377 | None | Stops at **Maximum results** |
| 100 businesses | 1 search, 10-minute timeout | 100 business, 12 search pages | $0.46827 | Rejected profiles $0.0014 each | About 6 to 7 minutes. The default 5-minute timeout saves about 50 to 80 |
| 1 profile by link | 1 alias | 1 business | $0.00297 | Menu has no fee and adds about 5 seconds. Extra photo pages $0.0014 each | Ends after the profile |
| 3 profiles, 35 photos, 3 questions | 3 aliases | 3 business, 18 detail pages | $0.03357 | Included | Ends after the third profile |
| 100 reviews | 1 business | 100 review, 3 detail pages | $0.02997 | None | Stops at **Maximum results** |
| 1,000 reviews | 1 business | 1,000 review, 21 detail pages | $0.28467 | None | Stops at **Maximum results** |
| 7,000 reviews | 2 businesses, 10-minute timeout | 7,000 review, 143 detail pages | $1.98547 | None | About 7 minutes. The default 5-minute timeout saves about 5,000 |
| Review date filter with no match | 1 business, about 6,000 reviews read | 126 detail pages | $0.17667 | None | About 5 minutes, so a larger business can hit the default timeout |
| Monitor, nothing new | 1 business, 1 review page | 1 detail page | $0.00167 | None | Dataset stays empty |
| Empty search | 1 search | 1 search page | $0.01677 | None | Dataset stays empty |
| Source outage | Any | Start only | $0.00027 | None | Run fails with no rows |

**Maximum cost per run:** set it in **Run options**. The run stops before going over and keeps saved rows, with `stopReason` `CHARGE_LIMIT`. The lowest accepted value is $0.02.

The start fee scales with run memory per GB. The default 256 MB run pays it once.

> **👉 [Try it now: open the input form](https://console.apify.com/actors/gneubWrrN8lvn56RD/input)**

### Limits

- **Public data only.** The run uses no login and no customer cookies. Yelp's terms of service apply to how you use the data, so check them for your case.
- **The source can change.** The run depends on Yelp's public data feeds, which are not a documented API. If Yelp changes one, reads fail with a `*_FORMAT_CHANGED` code rather than saving wrong data.
- **Countries.** Tested on US businesses through Yelp's public frontend. Other countries can work but are not all tested.
- **Search depth.** Yelp shows 240 positions per query and location. It repeats some businesses on later pages, and the run saves each one once, so two deep searches gave 185 and 204 different businesses from 24 pages. Repeats cost no row, so a page brings about 8 rows, not 10. There is no automatic map splitting, so use several locations for bigger areas.
- **Search order.** Yelp's order differs between runs, so a monitor with a low **Maximum results** can return different businesses each time.
- **Photos and questions.** A profile includes up to 25 gallery items and 2 question previews. Larger values load paid pages. For business videos, `url` is the thumbnail only.
- **Non-recommended and removed reviews.** These lists have a fixed order, and language and translation are `null`.
- **Monitor memory.** **Only new results** keeps the latest 100,000 hashed IDs, so a very old row can come back. If the memory cannot be opened, you get all results and a `stateWarning` in `RUN_SUMMARY`.
- **Batch handling.** A business that cannot be read is skipped with a reason in `itemErrorSample`, which lists up to 25 of them. Three failed businesses in a row stop the run as `FAILED`, because that points at a wider problem, and rows already saved stay.
- **Time.** With the default 5-minute timeout, one business gives about 5,000 reviews, and a search gives about 50 to 80 businesses, or about 20 with menus. The number depends on the query. When time runs out, saved rows stay and the run ends with `stopReason` `DEADLINE`. Raise the timeout for more.
- **Run budget.** Each run has internal limits on requests and bytes that grow with **Maximum results**, ending with `REQUEST_LIMIT` or `BYTE_LIMIT`. A single Yelp response over 8 MiB ends the run the same way.
- **Menus.** The menu is read directly, without paid unblocking. If Yelp refuses it, the profile stays with `menu` `null`.
- **Retries.** A failed search read is retried at most once, and other reads at most twice. A search page with no business data is read one more time, so one page can take up to 4 requests. You still pay for one page. A search result without profile data is skipped and counted in `searchRowsUnreadable`.
- **Small review runs.** Each review page costs one detail page, so 1 to 10 reviews cost more than a flat per-review price.
- **Not included.** Email lookup, AI summaries and custom scripts.

> **👉 [Try it now: open the input form](https://console.apify.com/actors/gneubWrrN8lvn56RD/input)**

### API, export and integrations

- **API:** start runs and read rows with the [Apify API](https://docs.apify.com/api/v2).
- **Export:** download CSV, Excel, JSON, XML or HTML from the **Output** tab.
- **Scheduling:** use [Apify schedules](https://docs.apify.com/platform/schedules) with **Only new results** for monitors.
- **Webhooks:** call your endpoint when a run ends with [Apify webhooks](https://docs.apify.com/platform/integrations/webhooks).
- **SDK:** use the [Python](https://docs.apify.com/api/client/python) or [JavaScript](https://docs.apify.com/api/client/js) client.

```bash
curl -X POST "https://api.apify.com/v2/acts/cliqtomedia~yelp-scraper/run-sync-get-dataset-items" \
  -H "Authorization: Bearer $APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"mode":"search","query":"coffee","location":"San Francisco","maxItems":10}'
```

#### Use with AI agents (MCP)

Connect the Apify MCP server at `https://mcp.apify.com?tools=cliqtomedia/yelp-scraper`.

- **Minimal input:** `{"mode":"search","query":"coffee","location":"San Francisco","maxItems":10}`
- **Key fields:** `name`, `rating`, `reviewsCount`, `address.formatted`, `phone`, `website`, `url`
- **Typical run:** 10 businesses, about a minute, about $0.044
- **Limits:** keep `maxItems` low, and read `RUN_SUMMARY` to tell empty results from skipped items.

> **👉 [Try it now: open the input form](https://console.apify.com/actors/gneubWrrN8lvn56RD/input)**

### Troubleshooting

#### The run fails right after it starts

**Symptom:** `stopReason` is `SEARCH_INPUT_REQUIRED`, `BUSINESS_INPUT_REQUIRED` or `STATE_NAME_REQUIRED`.

**Likely reason:** a search needs both a query and a location or a search link, the other modes need links or IDs, and a monitor needs a name.

**Check:** the input of the run.

**Action:** fill in the missing field. You pay only the start fee.

#### The dataset is empty

**Symptom:** the run succeeded with no rows.

**Likely reason:** the search has no matches, filters rejected every profile or review, or a monitor found nothing new.

**Check:** `filteredOut`, `skippedSeen` and `notFound` in `RUN_SUMMARY`.

**Action:** loosen the filters or the search. For a monitor, an empty dataset is a normal result.

#### The run failed on a link or input value

**Symptom:** `FAILED` with `stopReason` `INVALID_INPUT_OR_RUNTIME`.

**Likely reason:** a business link or a search link is not a Yelp link, or another input value is wrong.

**Check:** the links in the input. A business link has `/biz/` and a search link has `/search`.

**Action:** fix the value and start again. You pay only the start fee.

#### Some businesses are missing

**Symptom:** `status` is `partial` and `stopReason` is `ITEMS_SKIPPED`, or `itemErrors` is above 0 and `stopReason` is `MAX_ITEMS`.

**Likely reason:** Yelp returned an error or incomplete data for those businesses.

**Check:** `itemErrors` and `itemErrorSample` in `RUN_SUMMARY`.

**Action:** rerun with those IDs. Skipped businesses are not charged as business rows.

#### The run failed with a source code

**Symptom:** `FAILED` with `SEARCH_HTTP_ERROR`, `SEARCH_DATA_MISSING`, `NETWORK_ERROR`, `TRANSPORT_UNAVAILABLE`, `BUSINESS_HTTP_ERROR` or a `*_FORMAT_CHANGED` code.

**Likely reason:** Yelp blocked or changed that route, or three businesses failed in a row.

**Check:** the code in `RUN_SUMMARY`, and any rows already saved.

**Action:** retry later. If the same code repeats, send it through the Issues tab.

#### Fewer rows than requested

**Symptom:** `stopReason` is `CHARGE_LIMIT`, `DEADLINE`, `REQUEST_LIMIT` or `BYTE_LIMIT`.

**Likely reason:** the run reached the maximum cost, the timeout or an internal budget.

**Check:** `savedCount` and the run options.

**Action:** raise the maximum cost or the timeout, or split the job into smaller runs. Search takes about 4 to 6 seconds per business, and about 15 with menus.

#### Phone or website is empty

**Symptom:** `phone` or `website` is `null`.

**Likely reason:** the business lists none on Yelp. In a test search for coffee in San Francisco, about 6 of 10 profiles had a phone and 7 of 10 a website.

**Check:** the business page on Yelp.

**Action:** turn on **Businesses with a website** if you need that field. Rejected profiles still cost one detail page each.

> **👉 [Try it now: open the input form](https://console.apify.com/actors/gneubWrrN8lvn56RD/input)**

### FAQ

#### Do I need a Yelp account or API key?

No. You need only an Apify account.

#### Can I get owner emails?

No. The run saves the phone and website the business publishes on Yelp.

#### Can I get more than 240 businesses?

Yes, with several locations or queries. Each pair stops at 240 positions, and repeats inside a pair are removed, so expect about 200 different businesses.

#### Why do two identical searches differ?

Yelp reorders results between runs, repeats some businesses on later pages and adds sponsored positions. Use a larger **Maximum results** for a steadier list.

#### How do I get only new reviews?

Turn on **Only new results**, set a **State name**, and start the same input on a schedule.

#### Can I set a cost limit?

Yes. Set **Maximum cost per run** in **Run options**. Rows saved before the limit stay yours.

> **👉 [Try it now: open the input form](https://console.apify.com/actors/gneubWrrN8lvn56RD/input)**

### Related Actors

- [OpenTable Reviews & Restaurants Scraper, No Login](https://apify.com/cliqtomedia/opentable-reviews-scraper): restaurants and reviews from OpenTable.
- [OpenStreetMap POI Extractor: Cafes, Shops, Hotels by City](https://apify.com/cliqtomedia/openstreetmap-poi-extractor): local places from open map data.

> **👉 [Try it now: open the input form](https://console.apify.com/actors/gneubWrrN8lvn56RD/input)**

### Support

Use the **Issues** tab on this page. Include the run ID, the mode and the error code. Do not include tokens or cookies.

> **👉 [Try it now: open the input form](https://console.apify.com/actors/gneubWrrN8lvn56RD/input)**

# Changelog

This Actor's version history is a separate document: https://apify.com/cliqtomedia/yelp-scraper/changelog.md

# Actor input Schema

## `mode` (type: `string`):

Search for businesses, look up business profiles, or collect full reviews.

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

A business category, keyword, or name, such as coffee or Tartine Bakery. Find businesses needs this or More search queries, plus a location.

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

City, address, neighborhood, or ZIP code, such as San Francisco or 94103. Find businesses needs this or More search locations.

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

Yelp business page URLs or business aliases. Regional Yelp URLs are accepted.

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

Encoded Yelp IDs, such as WavvLdfdP6g8aZTtbBQHTw. Useful for reviews without a profile lookup.

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

Run each query in each location. Overrides Search query when supplied.

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

Run searches in each location. Overrides Search location when supplied.

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

Total business and review rows to save across the whole run.

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

Maximum unique businesses to process for each query and location.

## `searchSort` (type: `string`):

Order chosen by Yelp for search results.

## `category` (type: `string`):

Optional Yelp category alias, such as coffee or restaurants.

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

Match one or more price levels: 1 is $, 4 is $$$$.

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

Optional Yelp feature aliases, such as DogsAllowed or WiFi.free.

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

Keep only businesses open now. A business whose Yelp profile says closed is dropped and costs one detail page.

## `includeAds` (type: `boolean`):

Include sponsored businesses as well as organic search results.

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

Save separate review rows after each business profile. Both row types count toward Maximum results.

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

Maximum matching reviews to save for each business.

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

Order of the review feed.

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

Keep selected star ratings. Leave empty for all ratings.

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

Review language code, such as en or fr. Leave empty for all available languages.

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

Save reviews containing at least one of these words or phrases.

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

Inclusive date YYYY-MM-DD or relative period such as 30 days or 2 months.

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

Inclusive final date YYYY-MM-DD.

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

Optional language code. Adds Yelp-translated text in translatedText; text keeps the original review.

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

Include public reviewer display name, profile link, review count, and Elite year. No private contacts are collected.

## `maxPhotos` (type: `integer`):

Maximum business photos. The first 25 are available in the profile; larger values load additional pages.

## `maxQuestions` (type: `integer`):

Maximum community questions. Up to 2 includes the top-answer preview. Larger values load question and answer pages.

## `includeMenu` (type: `boolean`):

Include the structured menu and prices where Yelp publishes one, plus popular dishes and the profile menu link.

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

Skip business or review IDs saved in earlier runs using the same State name. Changed existing IDs are skipped too.

## `stateName` (type: `string`):

Name of an Apify key-value store for Only new results. Use a different name for unrelated jobs.

## `deliveryConnector` (type: `string`):

Your Slack, Notion or other MCP connector. After the run the Actor posts a short summary there. Connect services once in Apify Console → MCP connectors.

## `deliveryTarget` (type: `string`):

Where to post the summary: a Notion page link (each run is added on top of that page) or a Slack channel ID. Leave empty to let the connector decide.

## `searchUrls` (type: `array`):

Optional Yelp /search URLs with filters. These replace Search query and Search location; pagination starts at the first page.

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

Keep businesses with at least this average star rating. Does not filter individual reviews.

## `minReviews` (type: `integer`):

Keep businesses with at least this many recommended reviews.

## `onlyWithWebsite` (type: `boolean`):

Keep only profiles that publish a business website URL.

## `reviewType` (type: `string`):

Recommended reviews, reviews Yelp does not currently recommend (lowest stars first), or reviews marked removed but still publicly visible on Yelp. Sorting, language, and translation apply only to the recommended list.

## Actor input object example

```json
{
  "mode": "search",
  "query": "coffee",
  "location": "San Francisco",
  "maxItems": 10,
  "maxBusinessesPerSearch": 240,
  "searchSort": "recommended",
  "category": "",
  "openNow": false,
  "includeAds": false,
  "includeReviews": false,
  "maxReviewsPerBusiness": 100,
  "reviewsSort": "newest",
  "language": "en",
  "dateFrom": "",
  "dateTo": "",
  "translateTo": "",
  "includeReviewerDetails": false,
  "maxPhotos": 20,
  "maxQuestions": 2,
  "includeMenu": false,
  "onlyNew": false,
  "minRating": 0,
  "minReviews": 0,
  "onlyWithWebsite": false,
  "reviewType": "recommended"
}
```

# Actor output Schema

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

No description

## `summary` (type: `string`):

No description

## `reports` (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 = {
    "query": "coffee",
    "location": "San Francisco",
    "maxItems": 10
};

// Run the Actor and wait for it to finish
const run = await client.actor("cliqtomedia/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 = {
    "query": "coffee",
    "location": "San Francisco",
    "maxItems": 10,
}

# Run the Actor and wait for it to finish
run = client.actor("cliqtomedia/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 '{
  "query": "coffee",
  "location": "San Francisco",
  "maxItems": 10
}' |
apify call cliqtomedia/yelp-scraper --silent --output-dataset

```

## MCP server setup

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