# Yellow Pages Canada Scraper: Business Leads & Phones (`steadyscrape/canada-yellow-pages-scraper`) Actor

Scrape Yellow Pages Canada (yellowpages.ca) and PagesJaunes.ca business data by type and city or postal code: name, address, phone, website, rating, categories and coordinates; optionally each business page (hours, services, socials, fax). No login. Export to JSON, CSV or Excel, or via API.

- **URL**: https://apify.com/steadyscrape/canada-yellow-pages-scraper.md
- **Developed by:** [Steady Scrape](https://apify.com/steadyscrape) (community)
- **Categories:** Lead generation, Business
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.00 / 1,000 businesses

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?

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 Canada Scraper — business leads from yellowpages.ca and PagesJaunes.ca

Scrape **Yellow Pages Canada** (yellowpages.ca) and its French twin **PagesJaunes.ca** by business type and city or
postal code: every business as one clean row with **name, categories, full address, coordinates, phone (also in
E.164), other numbers, website, rating and rating count**, plus whether it **pays Yellow Pages for its listing**. One
optional step reads each business's own page:

- **Business page** (`includeDetails`): description, every category, all phone numbers with their labels (toll-free,
  fax), every website, Facebook / Instagram / LinkedIn / X / YouTube / TikTok profiles, opening hours per day, payment
  methods, products and services, brands carried, specialties, languages spoken and service areas.

Search `Plumbers` in `Toronto ON`, `Dentists` in `Calgary AB`, `Plombiers` in `Montréal QC` or `Restaurants` near
`M5V 2T6` — or paste results and business links straight from the site. You pay per business delivered; searches
without results and links that give nothing are free rows that say why.

### Who it is for

- **Local SEO and marketing agencies** prospecting Canadian small businesses: phone, website (or none), rating and
  whether the business already pays Yellow Pages for advertising.
- **B2B sales and lead generation in Canada**: businesses by category and city, with the address split into street,
  city, province and postal code for a CRM.
- **Quebec and bilingual markets**: the same directory in French through pagesjaunes.ca, with categories,
  descriptions and labels the way Quebec businesses write them.
- **Market research**: count and map the dentists, roofers or lawyers of a city (the site's own count is in every
  search row; coordinates come with every row).

### How it works

1. **Searches** open the site's own results page for a term in a place (`yellowpages.ca/search/si/1/Plumbers/Toronto+ON`),
   35 businesses a page, and follow the page's own **Next** link until your maximum. A postal code gives the businesses
   nearest to it, sorted by distance.
2. **Ads are counted once**: Yellow Pages shows paid placements above and between the results and again at their own
   place. Each business is delivered once per run, at its first position; the repeats are counted as `duplicates`.
3. **Business pages** (optional) are read with the listing's schema.org data first, then the page's own blocks.
4. **Links**: a results link is walked like a search from that page; a business link is read on its own page.

The Actor reads only pages the site's robots.txt leaves open to any crawler, at a visitor's pace, without a login.

### Input example

```json
{
    "searchTerms": ["Plumbers", "Dentists"],
    "locations": ["Toronto ON", "M5V 2T6"],
    "site": "yellowpages.ca",
    "maxResultsPerSearch": 100,
    "includeDetails": true
}
```

French categories and descriptions: `"site": "pagesjaunes.ca"` with `"searchTerms": ["Plombiers"]` and
`"locations": ["Montréal QC"]`. Links: `"startUrls": ["https://www.yellowpages.ca/search/si/1/Plumbers/Toronto+ON"]`.

### Output example

```json
{
    "rowType": "business",
    "site": "yellowpages.ca",
    "id": "101902936",
    "url": "https://www.yellowpages.ca/bus/Ontario/North-York/Drain-King-Plumbers/101902936.html",
    "name": "Drain King Plumbers",
    "categories": ["Sewer Line Inspection", "Sewer Contractors", "Plumbers & Plumbing Contractors"],
    "address": "100 Saint Regis Crescent, North York, ON M3J 1Y8",
    "street": "100 Saint Regis Crescent",
    "city": "North York",
    "province": "ON",
    "postalCode": "M3J 1Y8",
    "latitude": 43.7550621,
    "longitude": -79.4822464,
    "phone": "647-362-2109",
    "phoneInternational": "+16473622109",
    "otherPhones": [],
    "website": "http://www.drainkingplumbers.ca/",
    "rating": 5,
    "ratingCount": 8,
    "services": ["Plumbing Repairs", "Pipe Replacement", "Drain Cleaning", "…"],
    "snippet": "Drain King Plumbers is a locally-owned, 24/7 full-service plumbing and drain company…",
    "paidListing": true,
    "sponsored": true,
    "searchTerm": "Plumbers",
    "location": "Toronto ON",
    "searchUrl": "https://www.yellowpages.ca/search/si/1/Plumbers/Toronto+ON",
    "position": 1,
    "details": {
        "description": "Drain King is the premium choice when you're looking for quality craftsmanship…",
        "phones": [{ "number": "647-362-2109", "international": "+16473622109", "label": "Primary" }],
        "fax": null,
        "websites": ["http://www.drainkingplumbers.ca/"],
        "socials": { "linkedin": null, "facebook": "https://www.facebook.com/drainkingplumbers", "instagram": null, "youtube": null, "tiktok": null, "x": "https://x.com/drainkingGTA" },
        "openingHours": [{ "day": "Monday", "opens": "00:00", "closes": "23:59" }, "…"],
        "hoursNote": null,
        "paymentMethods": ["American Express", "Cash", "Cheque", "Mastercard", "Visa"],
        "brands": ["Moen", "American Standard", "Grohe", "…"],
        "specialties": ["Emergency Plumbing Service", "Residential", "Commercial", "…"],
        "languages": ["English"],
        "serviceAreas": [],
        "otherDetails": []
    },
    "scrapedAt": "2026-10-24T12:00:00.000Z"
}
```

#### Business fields (`rowType: business`, charged)

| field | what it is |
|---|---|
| `rowType`, `site`, `scrapedAt` | `business`, the site it was read from (`yellowpages.ca` or `pagesjaunes.ca`) and when |
| `id`, `url` | Yellow Pages listing id (the same on both sites) and its page |
| `name`, `categories` | as listed; with the page, every category the business is listed under |
| `address`, `street`, `city`, `province`, `postalCode` | the address on one line and split (some businesses list only a province) |
| `latitude`, `longitude` | from the results page itself, no extra request |
| `phone`, `phoneInternational`, `otherPhones` | the main number as shown and in E.164 (`+1…`), and other numbers the listing shows (with the page, faxes are moved to `details.fax`) |
| `website` | the business's own website as Yellow Pages links it (sometimes a Facebook page) |
| `rating`, `ratingCount` | Yellow Pages star rating (half stars) and number of ratings |
| `services`, `snippet` | products and services, and the listing's teaser text |
| `paidListing`, `sponsored` | the business pays Yellow Pages for its listing, and it was first shown as an "Ad" placement; `null` for business links |
| `searchTerm`, `location`, `searchUrl`, `position` | which search found it and where; `null` for business links |
| `details` | only with `includeDetails` (see above); `otherDetails` keeps any extra block (memberships, licences) under its own heading |

#### Free rows

- `rowType: search` — one per term and place: the site's own name for the search (`resolvedTerm`, `resolvedLocation`),
  how many businesses it lists (`totalListed`), pages read, businesses delivered, duplicates, and a `status`: `ok`,
  `no_results`, `disallowed` (a page robots.txt closes), `blocked`, `not_searched` (spending limit) or `unreadable`.
- `rowType: link` — a link that gave no business: `invalid`, `not_found` (the listing was removed), `blocked`,
  `not_read` or `unreadable`, with the reason.

### Pricing

Pay per event, no subscription:

| event | price | when |
|---|---|---|
| `business` | US$0.001 | a business from a results page |
| `business-with-details` | US$0.002 | a business with its own page read (instead of `business`), and every business link |

1,000 Toronto plumbers cost US$1, or US$2 with their pages. Search rows, link rows, ads repeated on a page and
businesses already delivered by an earlier search of the run are free. The run stops at your spending limit before
reading any page it could not pay for.

### Limits

- **No emails**: Yellow Pages Canada does not publish business email addresses (it offers a contact form). Every row
  carries the website where the business lists one, and the business page adds its social profiles.
- Residential listings (Canada411) are not included: only businesses.
- Sorted and filtered results (by distance, rating, "open now") and the review, map and photo subpages are closed to
  automated readers by the site's robots.txt; the Actor reads the default order, and postal codes sort by distance.
- Reviews are not extracted (`ratingCount` and `rating` are).
- If the site refuses the connection or shows a bot check, the run stops asking, ends successfully and says so in free
  `blocked` rows; nothing is charged for them.

### Is it legal?

The Actor reads public business listings that Yellow Pages publishes for anyone, without a login, only on paths its
robots.txt allows, at a visitor's pace, and never solves or bypasses a challenge. The data is about businesses, but a
listing can name a person (sole proprietors): if you process it in a way personal-data laws (PIPEDA, Quebec's Law 25,
GDPR) cover, you are responsible for having a lawful basis. Check the site's terms for your use case.

This Actor is **unofficial** and is **not affiliated with, endorsed or sponsored by Yellow Pages Limited, yellowpages.ca
or PagesJaunes.ca**. Yellow Pages and PagesJaunes are trademarks of their owners, named here only to say which site
the Actor reads.

### Feedback

Something missing or a page the Actor cannot read? Open an issue on the Actor's Issues tab; answers come within days.

# Actor input Schema

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

What to search, one per line, as you would type it on the site: <code>Plumbers</code>, <code>Dentists</code>, <code>Restaurants</code>, <code>Real Estate Agents</code>, <code>Lawyers</code>, <code>Roofing Contractors</code>, or a business name. Each term is searched in every place. Up to 50.

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

Where to search, one per line: a city with its province (<code>Toronto ON</code>, <code>Montréal QC</code>, <code>Calgary AB</code>, <code>Gander NL</code>), a neighbourhood (<code>North York ON</code>) or a postal code (<code>M5V 2T6</code>, results sorted by distance). Up to 200.

## `site` (type: `string`):

Both sites list the same businesses; pagesjaunes.ca gives categories, descriptions and labels in French (the way Quebec businesses write them). Links below keep their own site.

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

Links copied from yellowpages.ca or pagesjaunes.ca, one per line: a results page (<code>https://www.yellowpages.ca/search/si/1/Plumbers/Toronto+ON</code>) is walked like a search from that page on; a business page (<code>https://www.yellowpages.ca/bus/Ontario/Toronto/…/123456.html</code>) is read on its own and charged as a business with details. Sorted or filtered results, review and map pages are closed to automated readers by the site's robots.txt and are free rows. Up to 5,000.

## `maxResultsPerSearch` (type: `integer`):

Stop each term in each place (and each results link) after this many businesses. Toronto lists about 1,800 plumbers, 35 a page. The run's spending limit is respected too.

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

Also read every business's own Yellow Pages page: description, every category, all phone numbers with their labels (toll-free, fax), every website, Facebook / Instagram / LinkedIn / X / YouTube / TikTok profiles, opening hours per day, payment methods, products and services, brands, specialties, languages spoken and service areas. Charged as <code>business-with-details</code> instead of <code>business</code>.

## Actor input object example

```json
{
  "searchTerms": [
    "Plumbers"
  ],
  "locations": [
    "Toronto ON"
  ],
  "site": "yellowpages.ca",
  "maxResultsPerSearch": 10,
  "includeDetails": true
}
```

# Actor output Schema

## `rows` (type: `string`):

No description

## `summary` (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": [
        "Plumbers"
    ],
    "locations": [
        "Toronto ON"
    ],
    "maxResultsPerSearch": 10,
    "includeDetails": true
};

// Run the Actor and wait for it to finish
const run = await client.actor("steadyscrape/canada-yellow-pages-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": ["Plumbers"],
    "locations": ["Toronto ON"],
    "maxResultsPerSearch": 10,
    "includeDetails": True,
}

# Run the Actor and wait for it to finish
run = client.actor("steadyscrape/canada-yellow-pages-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": [
    "Plumbers"
  ],
  "locations": [
    "Toronto ON"
  ],
  "maxResultsPerSearch": 10,
  "includeDetails": true
}' |
apify call steadyscrape/canada-yellow-pages-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,steadyscrape/canada-yellow-pages-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/vycFewymq5a8Paad9/builds/EFvmsFsilU6FGXTDn/openapi.json
