# Yellow Pages Scraper (`tortuga/yellowpages-scraper`) Actor

Scrape Yellow Pages US by keyword and location: business name, phone, address, website, categories, hours, ratings, years in business and email. Build local B2B lead lists.

- **URL**: https://apify.com/tortuga/yellowpages-scraper.md
- **Developed by:** [Trevor Ortega](https://apify.com/tortuga) (community)
- **Categories:** Lead generation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.00 / 1,000 businesses

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?

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

## Yellow Pages Scraper

Scrape Yellow Pages US (yellowpages.com) business listings for any keyword and US location: business name, phone number, full address, website, categories, rating and review count, years in business, open status and weekly hours. Turn on profile details to also get the business email (when published), services, brands, payment methods, AKA names, extra phone numbers, social links and GPS coordinates. Built for local B2B lead lists, sales prospecting and local-market research.

Type what you are looking for (`plumber`, `dentist`, `roofing contractors`) and where (`Chicago, IL`, `Austin, TX`, `10001`). The Actor runs every search term in every location, walks the result pages (30 businesses per page), removes duplicate sponsored listings, and saves one clean record per business. You can also paste Yellow Pages search, category or business profile URLs.

Plain HTTP, no browser, no login. Export as JSON, CSV or Excel, or pull the dataset through the API into Google Sheets, a CRM or an LLM pipeline. You pay only for the businesses you get.

### What data does Yellow Pages Scraper extract?

Every business (from the search results, charged as `result`):

| Field | Description |
|---|---|
| `id`, `ypListingId` | Yellow Pages business id (ypid, stable) and the listing id of this placement |
| `name` | Business name |
| `url` | Yellow Pages profile URL |
| `phone` | Main business phone, e.g. `(312) 878-8062` |
| `website` | The business's own website |
| `address`, `addressText` | `{street, city, state, postalCode, country}` and a one-line address |
| `categories` | Yellow Pages categories shown on the listing |
| `rating`, `reviewCount` | Yellow Pages star rating (0-5) and number of reviews |
| `tripAdvisorRating`, `tripAdvisorReviewCount` | TripAdvisor rating shown on some listings (restaurants, bars, hotels) |
| `yearsInBusiness`, `yearsWithYellowPages` | Badges shown on the listing |
| `hoursText`, `isOpenNow` | Open status at scrape time (`open now`, `open 24 hours`, `closing soon`, `closed now`) |
| `hours`, `openingHours` | Weekly hours by day (`{"Monday": "6:30 am - 4:30 pm", ...}`) and the raw schema.org strings |
| `isAd`, `isSponsored`, `isPreferred`, `isClaimed` | Paid advertiser listing, sponsored ad block, "YP Preferred" badge, owner-claimed profile |
| `businessSnippet` | "From Business" description snippet (customer review quotes are not collected) |
| `thumbnailUrl`, `features` | Listing thumbnail and Yellow Pages feature flags (`website`, `reviews`, `open-24hr`, ...) |
| `searchTerm`, `searchLocation`, `rank`, `page` | Which search found the business and its position (organic rank across pages) |
| `sourceUrl`, `scrapedAt` | Where and when the record was scraped |

With **Open each business profile** (charged as `detail`, one extra request per business):

| Field | Description |
|---|---|
| `email` | Business email, only when the business publishes one on its Yellow Pages profile |
| `latitude`, `longitude` | GPS coordinates |
| `hours` | Full weekly hours including closed days |
| `categories` | All categories (search cards show only the first few) |
| `services`, `brands`, `paymentMethods`, `languages` | Services/products, brands carried, payment methods accepted, languages spoken |
| `aka` | Other names the business is listed under |
| `extraPhones` | `[{type: "phone" / "fax" / "toll free", number}]` |
| `socialLinks`, `otherLinks` | `{facebook, instagram, linkedin, ...}` and other websites listed |
| `slogan`, `generalInfo`, `description` | Slogan and the "General Info" text |
| `neighborhoods` | Neighborhoods the business belongs to |
| `yearEstablished`, `priceRange`, `bbbRating` | Founding year, price range and BBB grade when shown |
| `moreInfo` | Any other "More Info" rows, e.g. `{"Ownership": "Locally Owned", "Free Estimates": "Yes"}` |
| `detailsScraped` | `true` when the profile was opened |

Reviewer names, review texts and personal contact details are deliberately not collected; reviews appear only as a rating and a count.

### How to scrape Yellow Pages business listings

1. Enter one or more **Search terms** (for example `plumber`, `hvac`, `dentist`).
2. Enter one or more **Locations**: city and state (`Chicago, IL`), neighborhood or ZIP code (`10001`).
3. Set **Max businesses** to cap the run and the cost, and **Max pages per search** (30 businesses per page).
4. Turn on **Open each business profile** if you need emails, full hours, services and coordinates.
5. Click **Start**. Results appear in the **Dataset** tab; export from there or use the API.

### Input example

```json
{
  "searchTerms": ["plumber", "electrician"],
  "locations": ["Chicago, IL", "10001"],
  "maxItems": 500,
  "maxPagesPerSearch": 10,
  "includeDetails": true,
  "sortBy": "default",
  "proxyConfiguration": { "useApifyProxy": true, "apifyProxyGroups": ["RESIDENTIAL"], "apifyProxyCountry": "US" }
}
```

Start URLs work too:

```json
{
  "startUrls": [
    { "url": "https://www.yellowpages.com/chicago-il/plumbers" },
    { "url": "https://www.yellowpages.com/search?search_terms=dentist&geo_location_terms=Austin%2C+TX" },
    { "url": "https://www.yellowpages.com/chicago-il/mip/baethke-plumbing-15128363" }
  ],
  "maxItems": 200
}
```

### Output example

```json
{
  "id": "15128363",
  "ypListingId": "15128363",
  "name": "Baethke Plumbing",
  "url": "https://www.yellowpages.com/chicago-il/mip/baethke-plumbing-15128363",
  "phone": "(773) 276-5430",
  "website": "http://www.baethkeplumbing.com",
  "address": { "street": "3511 N Cicero Ave", "city": "Chicago", "state": "IL", "postalCode": "60641", "country": "US" },
  "addressText": "3511 N Cicero Ave, Chicago, IL 60641",
  "latitude": 41.94505,
  "longitude": -87.746765,
  "categories": ["Plumbers", "Home Improvements", "Major Appliances", "Plumbing Fixtures, Parts & Supplies"],
  "rating": 4.97,
  "reviewCount": 64,
  "yearsInBusiness": 33,
  "hoursText": "open 24 hours",
  "isOpenNow": true,
  "hours": { "Monday": "Open 24 Hours", "Tuesday": "Open 24 Hours", "Wednesday": "Open 24 Hours", "Thursday": "Open 24 Hours", "Friday": "Open 24 Hours", "Saturday": "Open 24 Hours", "Sunday": "Open 24 Hours" },
  "isAd": false,
  "isSponsored": false,
  "isClaimed": false,
  "email": "info@baethkeplumbing.com",
  "brands": ["bradford white", "rheem"],
  "paymentMethods": ["check", "debit", "amex", "discover", "mastercard", "visa"],
  "extraPhones": [{ "type": "phone", "number": "(773) 282-4340" }, { "type": "phone", "number": "(847) 965-8667" }],
  "neighborhoods": ["Northwest Side", "Portage Park"],
  "yearEstablished": 1993,
  "detailsScraped": true,
  "searchTerm": "plumber",
  "searchLocation": "Chicago, IL",
  "rank": 15,
  "page": 1,
  "scrapedAt": "2026-09-14T20:17:07Z"
}
```

### How much does it cost to scrape Yellow Pages?

Pay per event, no subscription and no start fee:

- **$0.002 per business** saved from search results ($2 per 1,000 leads).
- **$0.003 extra per business** whose profile page is opened (only with **Open each business profile**, or for profile start URLs).

1,000 plumbers with phone, address, website and rating cost $2; with emails, full hours and services $5. Platform usage (compute and proxy) is billed by Apify at cost and is small: a result page is ~300 KB. Apify's free plan is enough to try it.

### How many results can I get per search?

Yellow Pages shows at most 100 pages (3,000 businesses) for one search, and busy searches in big cities often hit that limit. To collect more, split the area: use several ZIP codes or neighboring cities as **Locations**. Duplicates across searches are removed automatically (by Yellow Pages business id), so overlapping areas never cost twice.

### Does it get emails from Yellow Pages?

Yes, when the business lists an email on its Yellow Pages profile (the "Email Business" link). Turn on **Open each business profile**; the `email` field is empty when the business has not published one. Only business contact details shown publicly by Yellow Pages are collected.

### Does Yellow Pages block scrapers?

Yellow Pages sits behind Cloudflare and answers bursts of requests from one IP with HTTP 429 challenge pages. The Actor uses real-browser TLS fingerprints, keeps concurrency low, detects challenge pages and retries them on a fresh proxy IP, so runs finish instead of silently returning nothing. Use Apify Proxy (residential, US) for large runs; without a proxy the Actor slows down to one request every ~3 seconds.

### Integrations and API

Use the run in Zapier, Make, n8n, Google Sheets or HubSpot, or call it from Python/Node with the Apify client. See the **API** tab for ready-made snippets. A typical lead workflow: scrape Yellow Pages, then enrich the `website` domains with a contact finder and verify emails before outreach.

### Is it legal to scrape Yellow Pages?

The Actor collects publicly available business listing data (business names, business phone numbers, addresses, websites, categories, hours and aggregate ratings) without logging in. It does not collect reviewer names, review texts or personal data about individuals. You are responsible for how you use the data and for complying with Yellow Pages' terms, anti-spam rules (CAN-SPAM, TCPA) and applicable law.

### Support

Found a bug or need a field added? Open an issue in the **Issues** tab; it is usually answered within a day.

# Actor input Schema

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

What to search for on Yellow Pages, e.g. plumber, dentist, roofing contractors, pizza. Every search term is combined with every location.

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

US cities ("Chicago, IL"), neighborhoods, states or 5-digit ZIP codes ("10001"). Required when you use search terms.

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

Optional Yellow Pages URLs instead of (or in addition to) search terms: search result pages (https://www.yellowpages.com/search?search\_terms=plumber\&geo\_location\_terms=Chicago%2C+IL), category pages (https://www.yellowpages.com/chicago-il/plumbers) or business profile pages (https://www.yellowpages.com/chicago-il/mip/baethke-plumbing-15128363). Profile URLs always include full details.

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

Stop after this many businesses in total (across all searches). Keeps cost predictable.

## `maxPagesPerSearch` (type: `integer`):

Result pages to read per search (30 businesses per page). Yellow Pages itself shows at most 100 pages (3,000 businesses) for one search; split big areas into several ZIP codes or cities to get more.

## `includeDetails` (type: `boolean`):

Also open every business's Yellow Pages profile for full weekly hours, all categories, services/products, brands, payment methods, languages, AKA names, extra phone numbers, social links, the business email (when the business publishes one), latitude/longitude, year established and the general info text. One extra request per business, charged as a `detail` event.

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

Order of search results, same as the sort menu on Yellow Pages. Applied to search terms; start URLs keep their own sort.

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

Yellow Pages is behind Cloudflare and rate-limits busy IPs. Apify Proxy (residential recommended for large runs) keeps runs reliable.

## Actor input object example

```json
{
  "searchTerms": [
    "plumber"
  ],
  "locations": [
    "Chicago, IL"
  ],
  "maxItems": 100,
  "maxPagesPerSearch": 10,
  "includeDetails": false,
  "sortBy": "default",
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "US"
  }
}
```

# Actor output Schema

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

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "searchTerms": [
        "plumber"
    ],
    "locations": [
        "Chicago, IL"
    ],
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ],
        "apifyProxyCountry": "US"
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("tortuga/yellowpages-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 = {
    "searchTerms": ["plumber"],
    "locations": ["Chicago, IL"],
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
        "apifyProxyCountry": "US",
    },
}

# Run the Actor and wait for it to finish
run = client.actor("tortuga/yellowpages-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 '{
  "searchTerms": [
    "plumber"
  ],
  "locations": [
    "Chicago, IL"
  ],
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "US"
  }
}' |
apify call tortuga/yellowpages-scraper --silent --output-dataset

```

## MCP server setup

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