# Yelp Business Listings Extractor (`kawsar/yelp-business-listings-extractor`) Actor

Yelp business scraper that pulls listings from any keyword and location search, so you get names, ratings, reviews, price, phone, and photos ready for SEO and lead lists.

- **URL**: https://apify.com/kawsar/yelp-business-listings-extractor.md
- **Developed by:** [Kawsar](https://apify.com/kawsar) (community)
- **Categories:** Lead generation, SEO tools, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.99 / 1,000 results

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#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 Business Listings Extractor

Pull business listings straight from Yelp search results, in bulk. Give it a keyword and a city, or paste your own Yelp search links, and it collects every business on the page: name, star rating, review count, price, categories, neighborhood, phone, and photos. It pages through the results on its own up to the limit you set.

Handy for local SEO research, lead lists, competitor tracking, and market sizing. Export the data to JSON, CSV, or Excel and drop it straight into your workflow.

### Why use this actor

Yelp is one of the largest directories of local businesses, but the site gives you no easy way to get that data out. Copying listings by hand is slow, and the page loads more results only as you scroll. This actor does the scrolling and paging for you and hands back clean, structured rows you can sort, filter, and import anywhere.

- No login, no cookies, no browser extensions to install
- Works from a plain keyword and location, or from search URLs you already have
- Reads both paid and organic listings on each page
- Skips duplicates when a business shows up on more than one page
- Runs on Apify, so you can schedule it, call it from the API, or chain it into a bigger pipeline

### What it does

- Searches Yelp by keyword and location, or by full search URL
- Reads every listing on each result page, ads and organic
- Follows pagination automatically until it reaches your item limit
- Pulls price, rating, and review count from the page even when they are not in the raw data
- Returns clean, structured records ready for a spreadsheet or a database
- De-duplicates businesses across pages by their Yelp ID

### Use cases

- **Lead generation:** build local prospect lists with names, phone numbers, categories, and ratings
- **Local SEO:** see who ranks for a keyword in a city and track movement over time
- **Competitor research:** compare ratings, review volume, and price level across a neighborhood
- **Market research:** measure how many businesses match a category in a given area, and at what price points
- **Data enrichment:** match Yelp ratings and review counts onto an existing list of businesses

### Input

Give the actor a keyword plus a location, or one or more full Yelp search URLs. Everything else is optional.

| Field | Type | Required | Default | Description |
|-------|------|----------|---------|-------------|
| `searchTerms` | list of strings | Yes, if no `searchUrls` | `["Restaurants"]` | Keywords to search, for example `Restaurants`, `Plumbers`, `Coffee`. Each keyword is combined with the location. |
| `location` | string | Yes, with `searchTerms` | `San Francisco, CA` | City, area, or ZIP to search in. |
| `searchUrls` | list of strings | Yes, if no `searchTerms` | empty | Full Yelp search URLs. Use these instead of keyword plus location when you already have exact links, for example ones with filters applied. |
| `maxItems` | integer | No | `15` | Max listings to collect per run across all searches, up to 1000. |
| `requestTimeoutSecs` | integer | No | `30` | Per-request timeout in seconds. |

You can mix `searchTerms` plus `location` with `searchUrls` in the same run. The actor merges them and removes duplicate searches.

#### Example input: keyword and location

```json
{
    "searchTerms": ["Restaurants", "Coffee"],
    "location": "San Francisco, CA",
    "maxItems": 50
}
```

#### Example input: your own search URLs

```json
{
    "searchUrls": [
        "https://www.yelp.com/search?find_desc=Bakeries&find_loc=Austin,+TX"
    ],
    "maxItems": 100
}
```

### Output

Each business becomes one record in the dataset. Fields that Yelp does not show for a given business come back as `null` or an empty list rather than a guessed value.

| Field | Type | Description |
|-------|------|-------------|
| `name` | string | Business name |
| `alias` | string | Yelp URL slug for the business |
| `bizId` | string | Yelp's internal business ID, stable across searches |
| `yelpUrl` | string | Link to the business page |
| `rating` | number | Star rating, 0 to 5 |
| `reviewCount` | integer | Number of reviews |
| `priceRange` | string | Price level, `$` to `$$$$`, or `null` when not shown |
| `phone` | string | Phone number when Yelp shows one |
| `categories` | list | Category labels, for example Steakhouses, Seafood |
| `neighborhoods` | list | Neighborhood names |
| `formattedAddress` | string | Address when available |
| `serviceArea` | string | Service area for businesses that list one |
| `isAd` | boolean | Whether the listing is a paid placement |
| `imageUrl` | string | First listing photo |
| `imageUrls` | list | All listing photos on the card |
| `reviewSnippet` | string | A short review excerpt shown on the card |
| `businessHighlights` | list | Yelp highlights, for example Outdoor seating |
| `rankingPosition` | integer | Position in the collected results |
| `searchTerm` | string | The keyword that produced this listing |
| `searchLocation` | string | The location that produced this listing |
| `searchUrl` | string | The search URL used |
| `scrapedAt` | string | UTC timestamp of the run, ISO 8601 |

#### Example output

```json
{
    "name": "Fog Harbor Fish House",
    "alias": "fog-harbor-fish-house-san-francisco-2",
    "bizId": "abcd1234",
    "yelpUrl": "https://www.yelp.com/biz/fog-harbor-fish-house-san-francisco-2",
    "rating": 4.4,
    "reviewCount": 13300,
    "priceRange": "$$",
    "phone": null,
    "categories": ["Seafood", "Bars"],
    "neighborhoods": ["Fisherman's Wharf"],
    "formattedAddress": null,
    "serviceArea": null,
    "isAd": false,
    "imageUrl": "https://s3-media0.fl.yelpcdn.com/bphoto/xxxx/ls.jpg",
    "imageUrls": ["https://s3-media0.fl.yelpcdn.com/bphoto/xxxx/ls.jpg"],
    "reviewSnippet": "Daniela was absolutely amazing...",
    "businessHighlights": ["Family-owned & operated", "Full bar"],
    "rankingPosition": 2,
    "searchTerm": "Restaurants",
    "searchLocation": "San Francisco, CA",
    "searchUrl": "https://www.yelp.com/search?find_desc=Restaurants&find_loc=San+Francisco,+CA",
    "scrapedAt": "2026-08-13T12:00:00+00:00"
}
```

### How to run it

1. Open the actor on Apify.
2. Enter your search terms and a location, or paste one or more Yelp search URLs.
3. Set `maxItems` to how many listings you want.
4. Click Start, or schedule the run.
5. When the run finishes, open the dataset and export to JSON, CSV, Excel, or HTML, or pull the results through the Apify API.

You can also start runs from the Apify API or the Apify client libraries for Python and JavaScript, which makes it easy to fold the actor into an existing workflow.

### How pagination works

Yelp shows 10 results per page and loads the next set with a `start` value in the URL. The actor walks through pages on its own, page by page, and stops when it reaches your `maxItems` limit or runs out of results. You do not need to build page URLs by hand. Set `maxItems` to the total you want across the whole search.

### Tips and best practices

- One keyword plus one location gives you a focused list. Add more keywords to widen the run.
- Keep `maxItems` close to what you actually need. Smaller runs finish faster and cost less.
- Pasting a search URL lets you carry over filters you set in the browser, such as price level or open now.
- Business IDs (`bizId`) are stable, so you can re-run a search later and match records to spot new or dropped listings.
- Run one search per city rather than trying to cover several cities in a single query.

### FAQ

**How many results can I get per search?**
As many as Yelp returns for that query, up to the `maxItems` you set. The actor stops when it reaches the limit or runs out of pages.

**Can I scrape several cities at once?**
Yes. Add one search URL per city to `searchUrls`, or run the actor once per location.

**Do I always get a phone number?**
Yelp lists a phone number for many businesses, and it comes through when present. Some organic cards do not expose a phone on the search page.

**Why is `priceRange` sometimes null?**
Because Yelp does not show a price for every business. When the page displays a price, the actor returns it. When it does not, the field is `null` rather than a made-up value.

**What is the difference between ads and organic results?**
Paid placements have `isAd` set to true. Both kinds are collected so you see the full page as a searcher would.

**What export formats are supported?**
JSON, CSV, Excel, and HTML from the dataset, plus the Apify API for programmatic access.

### Notes

Please use the data responsibly and in line with Yelp's terms and any laws that apply to you. This actor is intended for research, analytics, and lead generation on publicly visible listings.

# Actor input Schema

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

Keywords to search on Yelp, for example Restaurants, Plumbers, Coffee. Combined with the location below. Leave empty if you paste full search URLs instead.

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

City, area or ZIP to search in, for example San Francisco, CA. Used together with the search terms above.

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

Full Yelp search result URLs to extract from. Use this instead of search terms and location when you already have the exact search links.

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

Maximum number of business listings to collect per run across all searches.

## `requestTimeoutSecs` (type: `integer`):

Per-request timeout in seconds.

## Actor input object example

```json
{
  "searchTerms": [
    "Restaurants",
    "Coffee"
  ],
  "location": "New York, NY",
  "searchUrls": [
    "https://www.yelp.com/search?find_desc=Bakeries&find_loc=Austin,+TX"
  ],
  "maxItems": 15,
  "requestTimeoutSecs": 30
}
```

# Actor output Schema

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

All extracted Yelp business listings, one row per business.

# 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 = {
    "searchTerms": [
        "Restaurants"
    ],
    "location": "San Francisco, CA",
    "searchUrls": []
};

// Run the Actor and wait for it to finish
const run = await client.actor("kawsar/yelp-business-listings-extractor").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 = {
    "searchTerms": ["Restaurants"],
    "location": "San Francisco, CA",
    "searchUrls": [],
}

# Run the Actor and wait for it to finish
run = client.actor("kawsar/yelp-business-listings-extractor").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 '{
  "searchTerms": [
    "Restaurants"
  ],
  "location": "San Francisco, CA",
  "searchUrls": []
}' |
apify call kawsar/yelp-business-listings-extractor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,kawsar/yelp-business-listings-extractor"
        }
    }
}

```

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/9eAtAvcgob8HXjJEe/builds/KqZAfNFRokqfyded9/openapi.json
