# Yelp Scraper – Businesses, Reviews & Photos (`simple.actors/yelp-businesses`) Actor

Scrape Yelp businesses: full records with phone, website, hours, health scores and Yelp's own recent-demand counter, plus every photo and the filtered reviews Yelp sells through no API tier.

- **URL**: https://apify.com/simple.actors/yelp-businesses.md
- **Developed by:** [Simple Actors](https://apify.com/simple.actors) (community)
- **Categories:** Business, Lead generation, Travel
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $5.00 / 1,000 business records

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

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

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

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

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

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

# README

## Yelp Scraper – Businesses, Reviews & Photos

Yelp businesses as data. Give it a place to search, or paste business URLs, and
get one row per business: the full record, the photo gallery, and the reviews
Yelp's own filter took off the page.

It is built around one fact. Yelp ended free API access, and what it sells now
starts at **$229 a month** for a tier that returns *no photos and no review text
at all*. The middle tier is $299 and gives three photos and three truncated
review excerpts. Even the $643-a-month top tier stops at twelve photos and seven
excerpts. Several of the fields below — the recent-demand counter, the health
scores, the outbound website URL, the filtered reviews — are sold at no tier, at
any price.

### What you get

**Identity and location** — name, Yelp id, alias, Yelp URL, alternate names,
whether the listing is claimed, whether it is closed or closed until a date,
street address, city, state, postcode, country, neighbourhoods, timezone,
latitude and longitude.

**Contact** — phone, the business's own website (unwrapped from Yelp's redirect,
so you get the real domain), menu URL, whether Yelp messaging is on and how fast
the owner answers.

**Classification and standing** — categories, price band, Yelp's one-line
summary, the owner's own "specialties" text, year established, star rating,
review count, whether they advertise on Yelp, whether Yelp has a consumer alert
on them, and when their details were last verified.

**Demand** — how many people looked this business up recently, and Yelp's own
count of the searches it appeared in. This is the closest thing on Yelp to a
live busyness signal, and it exists in no API tier.

**Opening hours** — one row per day per interval, including the days they are
shut, with the timezone needed to read them.

**Health inspections** — score, grade, inspection date, the health department
behind it, and any itemised violations. US and Canada.

**Reviews Yelp filtered out** *(optional)* — two separate groups, tagged
`not_recommended` and `removed`, and they give you different things. The
**demoted** ones come with their star rating, date and **full text** — this is
the corpus Yelp sells nowhere. The **removed** ones, deleted for breaking Yelp's
terms, come with their rating and date but **no text**: Yelp replaces the body
with a notice, so `text` is empty on those by design rather than by omission.
Neither group counts towards the public rating or review count. Every row also carries both totals, so you can see the gap
between the public review count and the real one — for the restaurant used in
testing, 6,137 public reviews sat alongside 1,040 demoted and 419 deleted.

**Review highlights and amenities** — Yelp's extracted recurring phrases with
the number of reviews behind each, and the full "Amenities and more" panel.

**Ask the Community** — questions and their answers, with the total.

**Photos** *(optional)* — every photo's id, caption and dimensions, plus each
resolution Yelp serves it at, so you can pick your own size.

### What it does not do

**It does not return Yelp's recommended reviews.** Yelp loads those in the
browser from an endpoint that needs a logged-in session, and no amount of page
reading gets at them. The filtered reviews above are a different corpus — the
one Yelp hides — and they are the reviews this actor returns. If you need the
main review feed, this is not the tool.

### Two ways to ask

**Search a place.** Set *Where* to something you would type into Yelp — `San
Francisco, CA`, `Brooklyn, NY`, `London` — and optionally *What* (`pizza`,
`plumber`). Each result is then opened as a full business page. Turn on **Search
results only** to skip that and get just the thin result-page row, which is much
cheaper and much faster.

**Name the businesses.** Paste Yelp URLs into *Yelp business URLs*, or just the
alias from the end of one. `yelp.co.uk` and `yelp.ca` addresses work too.

Both inputs are read together, so you can do either or both.

### What it costs

You are charged for what you actually receive, not for the work behind it:

| You get | Price each | Per 1,000 |
|---|---|---|
| A search-result row | $0.002 | $2 |
| A full business record — all 64 fields | $0.005 | $5 |
| A filtered or removed review | $0.001 | $1 |
| A photo | $0.0005 | $0.50 |

So a thousand businesses as a lead list is **$2**, a thousand full records is
**$5**, and a thousand records with forty filtered reviews each is **$45**. For
comparison, Yelp's own API charges $229 a month before a single call and returns
no review text at all; its $643-a-month tier returns seven truncated excerpts.

**A row that could not be read is never charged.** Nor is anything you switched
off — reviews and photos are opt-in, and the two limit settings are your ceiling
on each.

### Reading the output

Every business is one row. A business that could **not** be read is also a row,
carrying `error` and `errorDescription` and **no `name` field at all** — so a
failed lookup can never be mistaken for a business with no name. Error codes are
`bad_input` (not a Yelp business address), `not_found` (no such business),
`blocked` and `read_failed`.

**The run stays green either way.** A bad URL or a missing business is an answer,
not a failure, so it does not turn the run red — the error rows are the failure
channel, and the run's status message counts them. If you schedule this, watch
the rows rather than the run status.

### Privacy

Reviewer names and their friend, review and photo counts are **off by default**.
Reviewers are private individuals rather than businesses, and the review itself —
rating, date, text — is what most callers need. Turn on **Include who wrote each
review** only if you have a reason to hold personal data.

### Unofficial

Not affiliated with, endorsed by, or connected to Yelp. Yelp's terms prohibit
automated access to its site; you are responsible for your own use of this
actor and for the data it returns.

# Actor input Schema

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

What you would type in Yelp's first box — "pizza", "plumber", "dentist". Leave it empty to get whatever Yelp considers the top businesses in the location. Needs "Where" to be set as well.

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

A place name, exactly as you would type it into Yelp's second box: "San Francisco, CA", "Brooklyn, NY", "London". Yelp resolves it — this actor does not need coordinates.

## `maxSearchResults` (type: `integer`):

Your ceiling on a search. Each result is opened as a full business record ($0.005 each) unless "Search results only" is on, in which case each is billed as a search row ($0.002 each). One Yelp search page carries about ten to twelve businesses.

## `searchOnly` (type: `boolean`):

Return the thin row Yelp puts on the results page — name, rating, review count, price band, categories, street and neighbourhood — without opening each business. Billed at $0.002 a row instead of $0.005, and it is four times faster. The right setting when you only want to know who is there. Note the search page carries no phone, no website, no hours and no state or postcode; those need the full record.

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

Businesses to read directly, one per entry. Paste the URL from your browser — https://www.yelp.com/biz/gary-danko-san-francisco — or just the alias from the end of it. yelp.co.uk and yelp.ca addresses work too. Each entry produces exactly one row.

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

The same thing as the list above, in the URL editor. Both inputs are read; giving either one is enough.

## `includeNotRecommendedReviews` (type: `boolean`):

Reads the reviews Yelp's recommendation software demoted, plus the ones it deleted for breaking its terms — two groups, tagged on every row. The demoted ones come with their star rating, date and full text, and are the corpus Yelp sells through no API tier at any price. The removed ones come with their rating and date but no text, because Yelp replaces the body with a notice. Neither counts towards the business's public rating or review count, and every row carries both totals, so you can see the gap between the public review count and the real one even at a low limit. Billed at $0.001 a review — set the limit below to cap it.

## `maxNotRecommendedReviews` (type: `integer`):

Your cost ceiling on reviews, at $0.001 each — the default of 40 is $0.04 a business, eight times the record itself, so set it to what you will actually read. Yelp renders twenty per page (ten demoted, ten deleted). The two totals are reported however low you set this.

## `includeReviewerProfiles` (type: `boolean`):

Adds the reviewer's display name and their friend, review and photo counts to every review row. Off by default on purpose: reviewers are private individuals rather than businesses, and the review itself — rating, date, text — is what most callers actually need. Turn it on only if you have a reason to hold personal data.

## `includePhotos` (type: `boolean`):

Reads the business's photo gallery — every photo's id, caption, dimensions and each resolution Yelp serves it at. Yelp's own API returns no photos at its base tier, three at the middle tier and twelve at the top. Billed at $0.0005 a photo, a quarter of the going rate — set the limit below to cap it.

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

Your cost ceiling on photos, at $0.0005 each. A busy restaurant can have thousands, so this matters: the default of 100 is $0.05 a business. Lower it and you are charged for fewer.

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

Leave this alone unless you know why you are changing it. Yelp sits behind DataDome, and measured on 2026-08-31 the Unblocker is the only Apify egress it answers — residential addresses get a challenge page instead of the business. This defaults to the Unblocker for that reason, and pointing it at a residential or datacenter group will make every row an error.

## Actor input object example

```json
{
  "searchTerm": "pizza",
  "location": "San Francisco, CA",
  "maxSearchResults": 10,
  "searchOnly": false,
  "businesses": [
    "https://www.yelp.com/biz/gary-danko-san-francisco"
  ],
  "startUrls": [],
  "includeNotRecommendedReviews": false,
  "maxNotRecommendedReviews": 40,
  "includeReviewerProfiles": false,
  "includePhotos": false,
  "maxPhotos": 100,
  "proxy": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "UNBLOCKER"
    ]
  }
}
```

# Actor output Schema

## `businesses` (type: `string`):

One row per business: who they are, where they are, how to reach them, and how they are rated.

## `raw` (type: `string`):

Every field of every row, exactly as pushed — reviews, photos, hours, amenities and all.

# 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 = {
    "businesses": [],
    "startUrls": []
};

// Run the Actor and wait for it to finish
const run = await client.actor("simple.actors/yelp-businesses").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 = {
    "businesses": [],
    "startUrls": [],
}

# Run the Actor and wait for it to finish
run = client.actor("simple.actors/yelp-businesses").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 '{
  "businesses": [],
  "startUrls": []
}' |
apify call simple.actors/yelp-businesses --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,simple.actors/yelp-businesses"
        }
    }
}

```

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/wPuXqnZNUlqDcFLWH/builds/y552RtWUDb2djewfL/openapi.json
