# Yelp Scraper — Business + Reviews + Menu + Photos in One Call (`godberry/yelp-scraper`) Actor

Extract a Yelp business profile + all reviews (auto-expanded, ISO dates) + menu + photos + amenities + hours in one call. Worldwide — any Yelp country domain, residential-proxy ready. No Fusion key, no 3-review cap. Pay-per-event: $0.001/business, $0.0002/review.

- **URL**: https://apify.com/godberry/yelp-scraper.md
- **Developed by:** [Tomas Lebedinskas](https://apify.com/godberry) (community)
- **Categories:** Lead generation, Travel
- **Stats:** 7 total users, 1 monthly users, 90.6% runs succeeded, 1 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.00 / 1,000 business profiles

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

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 — Business + Reviews + Menu in One Run, No API Key

Extract a complete Yelp business profile — the full listing, **all** the reviews you ask for (auto-expanded, with normalized dates), the menu, and the photo gallery — in a **single run**, in one record. No Yelp Fusion API key. No 3-review cap. Works on **any Yelp country domain**.

Maintained by Godberry Studios. A regional domain acting up, or a field you need that isn't here? Email <hello@godberrystudios.com> — a real person (the developer) replies, usually within one business day.

> **Part of the Godberry Reviews & Local-Data Suite** — pair it with the [Google Reviews Scraper](https://apify.com/godberry/google-reviews-scraper) (Google Maps reviews), the [Google Play Reviews Scraper](https://apify.com/godberry/google-play-reviews-scraper) (Android app reviews), and the [Google Maps Leads Scraper](https://apify.com/godberry/google-maps-leads-scraper) (local business leads — name, address, phone, website).

***

### What does this Actor do?

Paste one or more Yelp business URLs (or names, or slugs) and the Actor returns, **per business, in a single record**: the full business profile (~33 fields — address, normalized E.164 phone, website, rating, price level, categories, hours, amenities, photo gallery), every review you ask for (auto-expanded text plus a normalized ISO date), and the restaurant menu when one exists. It runs a real Chrome browser behind a residential proxy to get past Yelp's DataDome anti-bot, normalizes phones to E.164 and review dates across ~15 languages, and bills **pay-per-event** — you pay only for what actually comes back. The official Yelp Fusion API caps you at 3 reviews and needs a key; this needs neither.

### How to use (30 seconds)

1. Open any [Yelp](https://www.yelp.com) business in your browser.
2. Copy the URL from the address bar.
3. Paste it into **Yelp URLs** and click **Start**.

Add as many URLs as you like — they run in one batch. Free-text queries (`Joe's Pizza Bleecker Street New York`) and bare slugs (`the-original-pancake-house-portland`) also work — the Actor resolves them the way a human would on Yelp's search page.

Those non-URL inputs are resolved on the regional site set by **`searchDomain`** (default `yelp.co.uk`). If the same run also contains real Yelp URLs, their domain is inherited automatically — paste `yelp.de` URLs alongside `Burgermeister Berlin` and the query runs on the German site. Full URLs always keep their own domain. `searchDomain` deliberately does not default to `yelp.com`: DataDome blocks it from shared cloud IPs, so searches resolved there return nothing.

A malformed or non-Yelp entry costs only that entry — it is skipped with a warning and the rest of the batch continues.

**Which inputs are reliable.** Business URLs and bare slugs load `/biz/` pages directly and work consistently from Apify. Free-text queries are best-effort: Yelp returns 403 on its `/search` endpoint from shared cloud IP pools, so a query often fails where the equivalent business URL succeeds. Platform-verified 2026-07-26 — `dishoom-london` (slug) returned a full record, while `Dishoom Covent Garden` (query) was blocked at the search page. Pass a URL or slug where you can, or supply your own `proxyUrls`.

> **Pick the right domain.** The regional domains — `yelp.de`, `yelp.co.uk`, `yelp.fr`, `yelp.com.au`, `yelp.it`, `yelp.es`, … — are the reliable ones; set the **Proxy** country to match the domain (proxy `DE` for `yelp.de`) for clean runs. `yelp.com` and `yelp.ca` are the hard case — see the FAQ below.

### What you get

**Per business (~33 fields)**

| Field | Notes |
| --- | --- |
| `businessName`, `alias`, `businessUrl`, `domain` | Name, Yelp slug, canonical URL, regional domain |
| `addressLine1`, `city`, `state`, `zipCode`, `country` | Full structured address |
| `phoneE164`, `phoneFormatted` | `+442077284091` **and** `(020) 7728 4091` |
| `websiteUrl`, `extractedEmail` | Website; email when Yelp exposes one (often empty) |
| `ratingAverage`, `totalReviews`, `priceLevel` | `4.5`, `3010`, `$$$` |
| `categories` | e.g. `["Indian", "Bars"]` |
| `photos`, `heroImage` | Full-resolution gallery URLs |
| `hoursByDay` | Open/close per weekday + `closed` flag |
| `isClaimedByOwner`, `amenities` | Owner-claim flag, amenities list |
| `latitude`, `longitude`, `socialLinks`, `neighborhoods`, `ownerName`, `healthScore`, `establishedYear` | In the schema, but Yelp surfaces these inconsistently — usually empty (see *Field coverage*) |
| `scrapedAt` | ISO timestamp of the run |

**Per review (16 fields)** — `ratingStars`, `reviewText` (auto-expanded, full), `reviewRelativeDate` (`"3 weeks ago"`), `reviewDate` (normalized **ISO** date — see the date note below), `helpfulCount` / `coolCount` / `funnyCount`, `reviewPhotos`, and an owner response (`ownerResponse` + dates) when present. Reviewer-identity fields (`reviewerName`, `reviewerProfileUrl`, `reviewerEliteStatus`, `reviewerReviewCount`, `reviewerLocation`) are **off by default** and only included when you enable `includePersonalData` (see the GDPR FAQ).

**Per menu item (5 fields)** — `itemName`, `itemPrice`, `itemCategory`, `itemPhoto`, `itemDescription`. Restaurants with a Yelp menu page only.

> **About `reviewDate`.** Yelp usually shows reviews as a relative string (`"3 weeks ago"`). When that's the case, `reviewDate` is **computed from that relative string** and is therefore approximate (accurate to within roughly half the unit — half a week here — and anchored to the run time in `scrapedAt`). When a page exposes an absolute date instead, `reviewDate` is exact. The raw `reviewRelativeDate` is always preserved alongside it so you can see which you've got.

#### Field coverage — reliable vs. occasional

Populated on essentially every business: name, address, city/zip/country, phone, website, rating, review count, price level, categories, hours, amenities, photos, reviews. The **menu** populates for restaurants that have a Yelp menu page. The following are in the schema for completeness but Yelp surfaces them inconsistently — or no longer at all — so expect them empty more often than not: `latitude`/`longitude`, `socialLinks`, `neighborhoods`, `ownerName`, `healthScore`, `establishedYear`, `extractedEmail`, and `popularDishes`. We'd rather you know up front than be surprised in the dataset.

### Use cases

- **Restaurant intelligence** — bundle reviews + menu + photos in one record for chain-vs-chain or location-vs-location analysis.
- **Lead generation** — claimed-business data with a normalized E.164 phone (and an email where Yelp shows one) for local-business outreach. Pair with the [Google Maps Leads Scraper](https://apify.com/godberry/google-maps-leads-scraper) to widen coverage.
- **Reputation & review monitoring** — feed `reviewText` + `reviewDate` into a sentiment pipeline; the normalized dates make trend lines and date filters straightforward.
- **Competitive analysis** — pull a set of competitors in an area and sort by `ratingAverage` or review velocity.
- **AI / NLP training data** — full review text + normalized dates in clean JSON, privacy-safe by default.

### Input

**Minimal — just paste a URL:**

```json
{
  "urls": ["https://www.yelp.co.uk/biz/dishoom-london"]
}
```

**Full — every option set:**

```json
{
  "urls": [
    "https://www.yelp.co.uk/biz/dishoom-london",
    "https://www.yelp.de/biz/burgermeister-berlin-3",
    "https://www.yelp.com.au/biz/the-grounds-of-alexandria-alexandria",
    "Burgermeister Berlin"
  ],
  "maxReviewsPerBusiness": 100,
  "sortReviews": "newest",
  "onlyWithText": false,
  "includeMenu": true,
  "includePhotos": true,
  "includePersonalData": false,
  "flattenForSpreadsheet": false,
  "proxyConfiguration": { "useApifyProxy": true, "apifyProxyGroups": ["RESIDENTIAL"], "apifyProxyCountry": "GB" }
}
```

#### Input fields

| Field | Type | Default | Description |
| --- | --- | --- | --- |
| `urls` | string\[] | **required** | Yelp business URLs, slugs, or business-name/search queries — one per line |
| `maxReviewsPerBusiness` | int | 100 | Cap reviews per business (1–1000; Yelp paginates 10 per page) |
| `sortReviews` | enum | `newest` | `relevant` (Yelp Sort) / `newest` / `oldest` / `highest` / `lowest` |
| `onlyWithText` | bool | false | Skip star-only reviews with no text |
| `includeMenu` | bool | true | Extract the menu when the business has a Yelp menu page (restaurants only) |
| `includePhotos` | bool | true | Include full-resolution photo-gallery URLs |
| `includePersonalData` | bool | false | GDPR toggle — reviewer name, profile URL, location, Elite status, review count. **Off by default**; enable only with a lawful basis |
| `flattenForSpreadsheet` | bool | false | Joins array fields with `\|` and pushes reviews/menu as separate rows — clean CSV/Excel export |
| `proxyConfiguration` | object | Apify Residential | Standard Apify proxy input. Residential is the default because DataDome blocks datacenter IPs. **Set the proxy country to match the domain** (`apifyProxyCountry: "DE"` for `yelp.de`). For `yelp.com`/`yelp.ca`, supply your own residential `proxyUrls` |

### Output

One record per business. Trimmed sample (`includePersonalData: false`, so reviewer-identity fields are omitted):

```json
{
  "businessName": "Dishoom",
  "alias": "dishoom-london",
  "businessUrl": "https://www.yelp.co.uk/biz/dishoom-london",
  "domain": "yelp.co.uk",
  "addressLine1": "12 Upper St Martin's Lane",
  "city": "London",
  "state": "",
  "zipCode": "WC2H 9FB",
  "country": "United Kingdom",
  "latitude": null,
  "longitude": null,
  "phoneE164": "+442074200455",
  "phoneFormatted": "020 7420 0455",
  "websiteUrl": "https://www.dishoom.com/",
  "extractedEmail": "",
  "socialLinks": [],
  "ratingAverage": 4.5,
  "totalReviews": 3010,
  "priceLevel": "$$",
  "categories": ["Indian", "Bars", "Breakfast & Brunch"],
  "neighborhoods": [],
  "photos": [
    "https://s3-media0.fl.yelpcdn.com/bphoto/AbCdEf/l.jpg",
    "https://s3-media0.fl.yelpcdn.com/bphoto/GhIjKl/l.jpg"
  ],
  "heroImage": "https://s3-media0.fl.yelpcdn.com/bphoto/AbCdEf/l.jpg",
  "hoursByDay": {
    "monday":    { "open": "08:00", "close": "23:00", "closed": false },
    "tuesday":   { "open": "08:00", "close": "23:00", "closed": false },
    "wednesday": { "open": "08:00", "close": "23:00", "closed": false },
    "thursday":  { "open": "08:00", "close": "23:00", "closed": false },
    "friday":    { "open": "08:00", "close": "00:00", "closed": false },
    "saturday":  { "open": "09:00", "close": "00:00", "closed": false },
    "sunday":    { "open": "09:00", "close": "22:00", "closed": false }
  },
  "isClaimedByOwner": true,
  "ownerName": "",
  "amenities": ["Takes Reservations", "Outdoor Seating", "Vegetarian Friendly"],
  "healthScore": "",
  "establishedYear": null,
  "menu": [
    {
      "itemName": "Bacon Naan Roll",
      "itemPrice": "£6.50",
      "itemCategory": "Breakfast",
      "itemPhoto": "https://s3-media0.fl.yelpcdn.com/bphoto/MnOpQr/l.jpg",
      "itemDescription": "Smoked streaky bacon in a fresh-baked naan, cream cheese, chilli jam."
    }
  ],
  "reviews": [
    {
      "ratingStars": 5,
      "reviewText": "Best Indian in the West End. The black daal is unreal and the bacon naan roll at breakfast is a religious experience. Came back three times in one trip.",
      "reviewRelativeDate": "3 weeks ago",
      "reviewDate": "2026-05-28T09:14:02.118Z",
      "helpfulCount": 4,
      "coolCount": 1,
      "funnyCount": 0,
      "reviewPhotos": ["https://s3-media0.fl.yelpcdn.com/bphoto/StUvWx/l.jpg"],
      "ownerResponse": null,
      "ownerResponseDate": null,
      "ownerResponseRelativeDate": null
    }
  ],
  "popularDishes": [],
  "scrapedAt": "2026-06-18T09:14:02.118Z"
}
```

> `reviewDate` above is derived from `"3 weeks ago"` against `scrapedAt`, so it's approximate (see the date note above). When `includePersonalData: true`, each review additionally carries `reviewerName`, `reviewerProfileUrl`, `reviewerEliteStatus`, `reviewerReviewCount`, and `reviewerLocation`.

### How it works

1. **Resolve** — each URL, slug, or free-text query is resolved to a canonical Yelp business page (a search query resolves to the top result).
2. **Render** — a real Chrome browser (not a headless shell) loads the page behind a residential proxy, dismisses the cookie banner, and waits for the SPA to settle.
3. **Extract** — the business profile is read primarily from the page's JSON-LD (clean, structured), reviews are paginated via Yelp's `?start=N` offsets, and the menu is read from the `/menu/<slug>` route.
4. **Bill & deliver** — each business, review, and menu item is charged pay-per-event as it's pushed, so you're billed only for data that actually came back.

### Pricing

Pay-per-event — you pay only for what comes back.

| Event | Price |
| --- | --- |
| Per business returned | $0.001 |
| Per review returned | $0.0002 |
| Per menu item returned | $0.0001 |

**Worked example.** One restaurant with 50 reviews + 20 menu items = `$0.001 (business) + (50 × $0.0002) + (20 × $0.0001)` = **$0.013** in Actor charges. You pay only for what's returned — no run-start fee — so scraping 100 such restaurants ≈ **$1.30**.

Two things on total cost: (1) the default **Residential proxy** — needed to get past DataDome — is billed by Apify by the gigabyte, **separately** from the events above (usually a few cents per business); on most regional domains you can switch to the cheaper datacenter proxy. (2) Apify's free plan includes **$5/month of platform usage** — enough for tens to a few hundred small runs, plenty to decide whether this fits your workflow.

### FAQ

**Do I need a Yelp API key?**
No. There is nothing to register and no key to manage. The official Yelp Fusion API requires a key *and* caps you at 3 reviews per business — this Actor needs neither.

**Is scraping Yelp legal?**
The Actor reads publicly visible business pages. Reviewer personal data is **off by default** (`includePersonalData: false`) — the business profile, the main lead-gen value, is always returned regardless. If you enable personal data, you're responsible for processing it lawfully (GDPR included). As an EU-based operator we ship privacy-safe by default. Always review Yelp's Terms and your local law for your specific use case.

**Why did `yelp.com` or `yelp.ca` get blocked / return a 403?**
Those two domains are defended very aggressively by DataDome and are frequently 403'd from cloud platforms **even through a residential proxy**. This is a Yelp-side anti-bot reality, not a bug. The fix that works: supply a residential proxy on an IP **you control** via `proxyConfiguration.proxyUrls`. The regional domains (`.de`, `.co.uk`, `.fr`, `.com.au`, `.it`, `.es`, …) scrape reliably out of the box — set the proxy country to match the domain. We'd rather tell you this honestly than have a run fail unexplained.

**How accurate are the review dates?**
The raw `reviewRelativeDate` is exactly what Yelp shows (`"3 weeks ago"`). `reviewDate` is a normalized ISO date: **exact** when the page exposes an absolute date, and **approximate** (to within about half the unit) when it's computed from a relative string. Both are returned, so you always know which you have.

**I got fewer reviews than expected — why?**
Yelp's DataDome tends to rate-limit deep pagination after a few hundred reviews even on a residential proxy. When that happens the Actor returns **what it collected** rather than failing the whole run, and it always delivers the business profile. A business genuinely with no reviews returns an empty `reviews[]` — that's a real result, not an error. So a low review count is partial success by design, not a failed run.

**How fresh is the data?**
Live. Every record is scraped from Yelp at run time and stamped with `scrapedAt`. There's no cache between you and Yelp.

**What output formats can I get?**
JSON (default), plus CSV, Excel, HTML table, RSS, and XML via the Apify dataset export. For clean spreadsheets, set `flattenForSpreadsheet: true` to join array fields and split reviews/menu into rows.

**Does it work outside the US?**
Yes — that's its strength. ~31 country domains are pre-verified and any other `yelp.<tld>` still works (see *Worldwide support*). Phones are normalized to E.164 with the right country code and review dates are parsed across ~15 languages.

### Worldwide support

Works on **any Yelp country domain** — the regional domain is auto-detected from the URL, the phone is normalized to E.164, and review dates are parsed across ~15 languages (relative *and* absolute). Pre-verified domains (~31): `yelp.com` `.ca` `.co.uk` `.ie` `.fr` `.de` `.at` `.ch` `.it` `.es` `.pt` `.nl` `.be` `.pl` `.cz` `.dk` `.fi` `.no` `.se` `.com.au` `.co.nz` `.com.sg` `.com.ph` `.com.hk` `.com.tw` `.co.jp` `.com.br` `.com.mx` `.com.ar` `.cl` `.com.tr`. An unrecognized `yelp.<tld>` still works — it falls back to the page's structured data for the country.

### Anti-bot posture

Yelp uses DataDome (TLS/JA3 fingerprinting, JS challenges, IP-reputation blocking). This Actor:

- routes through **Apify Residential proxy by default** — DataDome blocks datacenter/cloud IPs, so a residential exit is required; match the proxy country to the regional domain for clean runs;
- runs the **real Chrome** binary, not a headless shell (which every modern anti-bot fingerprints);
- hides the `navigator.webdriver` flag and uses a desktop-class viewport and a current Chrome User-Agent;
- detects DataDome challenges — both redirect-style and the embedded-iframe kind served at the original URL — and retries with a fresh proxy session;
- on a deep review pull, returns what it collected if pagination gets rate-limited rather than failing the whole business; if retries are exhausted it still delivers the business profile.

None of this guarantees a bypass on the most aggressively defended domains — see the `yelp.com`/`yelp.ca` note below.

### Limits worth knowing

- **Search input resolves to the top result** — pass business URLs directly for a multi-business pull (Yelp caps search results at 240; narrow by neighborhood or zipcode for a list).
- **`yelp.com` / `yelp.ca` are the hard case** — see the FAQ; use your own residential `proxyUrls` there.
- **Deep review pulls** can be rate-limited past a few hundred reviews; the Actor returns partial data cleanly.
- **Relative review dates are normalized approximately** — see the date note above and the FAQ.
- **Free-plan Apify users** are capped at 1 business and 10 reviews per run — any paid Apify subscription unlocks the full output.
- **Selectors can shift** — a few of Yelp's `aria-label` strings differ across domains; if one breaks, email us and we patch quickly (they live in one `SELECTORS` constant).

### Reliability & maintenance

Actively maintained by a solo developer who answers the support inbox. The Actor degrades gracefully (partial results over failed runs) and detects anti-bot challenges rather than silently returning empty data. This Actor is still low-volume, so rather than headline a success-rate percentage off a small sample, we'll publish a rolling 30-day `SUCCEEDED` rate here once it's backed by enough runs to be meaningful — with the honest caveat that Yelp's strict anti-bot on the `.com`/`.ca` domains and genuinely review-less listings both pull it down (both documented above so you can avoid the failure cases).

Found this useful? A short rating on the Apify Store genuinely helps an independent developer — and tells us which features to build next.

### Support & contact

Questions, a broken regional domain, or a field request: <hello@godberrystudios.com>. The developer replies, typically within one business day.

**More Godberry actors:** [Google Reviews Scraper](https://apify.com/godberry/google-reviews-scraper) · [Google Maps Leads Scraper](https://apify.com/godberry/google-maps-leads-scraper) · [Google Play Reviews Scraper](https://apify.com/godberry/google-play-reviews-scraper)

### License

MIT. Author: Godberry Studios — <hello@godberrystudios.com>.

# Actor input Schema

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

One per line. Easiest: open a Yelp business in your browser and paste its URL. Also accepts business slugs (the-original-pancake-house-portland), Yelp search URLs (yelp.com/search?find\_desc=...), and free-text queries ("Joe's Pizza Bleecker Street"). Worldwide — works on any Yelp country domain: .com, .ca, .co.uk, .ie, .fr, .de, .at, .ch, .it, .es, .pt, .nl, .be, .pl, .cz, .dk, .fi, .no, .se, .com.au, .co.nz, .com.sg, .com.ph, .com.hk, .com.tw, .co.jp, .com.br, .com.mx, .com.ar, .cl, .com.tr. IMPORTANT: yelp.com and yelp.ca are heavily defended by DataDome and are frequently blocked from cloud platforms even with a residential proxy — the regional domains (.de, .co.uk, .fr, .com.au, .it, .es, …) are the reliable ones today; for yelp.com/.ca, a residential proxy you control gives the best odds. (A search URL or free-text query resolves to the top result only — pass business URLs directly for a multi-business pull. Yelp caps search results at 240.) RELIABILITY: business URLs and bare slugs are the dependable inputs — they load /biz/ pages directly. Free-text search queries are best-effort: Yelp 403s its /search endpoint from shared cloud IPs, so a query often fails where the equivalent URL succeeds. Use a URL or slug where you can, or supply your own proxyUrls.

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

Maximum reviews to extract per business (Yelp paginates 10 per page). Higher = longer run + higher pay-per-event cost. Note: Yelp's DataDome anti-bot tends to rate-limit deep pagination after a few hundred reviews even with a residential proxy — past that the actor returns what it got rather than failing. 1000 is the hard ceiling.

## `sortReviews` (type: `string`):

How to sort the reviews before extracting.

## `onlyWithText` (type: `boolean`):

Skip star-only reviews that have no text content.

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

Extract the menu (item name, price, category, photo, description) when the business has a Yelp menu page. Restaurants only — other business types return an empty menu.

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

Include the full photo-gallery URL list (full-resolution) on each business record.

## `includePersonalData` (type: `boolean`):

Reviewer name, profile URL, location, Elite status, and review count. OFF by default (privacy by default) — the business profile, the main lead-gen value, is always returned regardless. Turn this on only if you have a lawful basis to process reviewers' personal data; you are responsible for GDPR compliance when scraping EU data.

## `flattenForSpreadsheet` (type: `boolean`):

Recommended when exporting to CSV. Array fields (photos, categories, amenities) are joined with ' | '; reviews/menu are pushed as separate row series anchored to businessAlias. Leave off for JSON consumers.

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

Yelp uses DataDome anti-bot, which blocks datacenter IPs — so this defaults to Apify Residential. Best practice: set the proxy country to match the regional domain you're scraping (e.g. proxy DE for yelp.de, GB for yelp.co.uk). yelp.com / yelp.ca are the hard case — they're often blocked even through a residential proxy on a cloud platform; a residential proxy on an IP you control via proxyUrls is the best option there. You can also disable the proxy for local testing.

## `searchDomain` (type: `string`):

Which regional Yelp site to use when an input is NOT a full URL — a business slug, or a free-text query like "Burgermeister Berlin". Full URLs always keep their own domain, and if this run also contains Yelp URLs their domain is inherited automatically. Defaults to yelp.co.uk because yelp.com and yelp.ca are blocked from shared cloud IPs by DataDome, so searches resolved there return nothing.

## Actor input object example

```json
{
  "urls": [
    "https://www.yelp.co.uk/biz/dishoom-london",
    "https://www.yelp.de/biz/burgermeister-berlin-3",
    "https://www.yelp.com.au/biz/the-grounds-of-alexandria-alexandria",
    "Burgermeister Berlin"
  ],
  "maxReviewsPerBusiness": 100,
  "sortReviews": "newest",
  "onlyWithText": false,
  "includeMenu": true,
  "includePhotos": true,
  "includePersonalData": false,
  "flattenForSpreadsheet": false,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "GB"
  },
  "searchDomain": "yelp.co.uk"
}
```

# 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 = {
    "urls": [
        "https://www.yelp.co.uk/biz/dishoom-london"
    ],
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ],
        "apifyProxyCountry": "GB"
    },
    "searchDomain": "yelp.co.uk"
};

// Run the Actor and wait for it to finish
const run = await client.actor("godberry/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 = {
    "urls": ["https://www.yelp.co.uk/biz/dishoom-london"],
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
        "apifyProxyCountry": "GB",
    },
    "searchDomain": "yelp.co.uk",
}

# Run the Actor and wait for it to finish
run = client.actor("godberry/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 '{
  "urls": [
    "https://www.yelp.co.uk/biz/dishoom-london"
  ],
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "GB"
  },
  "searchDomain": "yelp.co.uk"
}' |
apify call godberry/yelp-scraper --silent --output-dataset

```

## MCP server setup

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