# Canada411 Scraper (`automation-lab/canada411-directory-scraper`) Actor

Search public Canada411 people records by name, location, phone, address, or URL and export normalized contact data.

- **URL**: https://apify.com/automation-lab/canada411-directory-scraper.md
- **Developed by:** [Stas Persiianenko](https://apify.com/automation-lab) (community)
- **Categories:** Lead generation, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per event

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

## Canada411 Scraper

Search public Canada411 people records by name and location, run Canada411 reverse phone or address lookups, and export normalized contact records. Use it for repeatable Canadian contact verification, enrichment, research, and data-pipeline inputs without manually copying directory pages.

The Actor intentionally covers people records only. Canada411 business searches redirect to YellowPages.ca and are outside this product's scope.

### What can Canada411 Scraper do?

- Search a person's full or partial name in a Canadian city, province, or postal area.
- Reverse lookup one or many Canadian phone numbers.
- Reverse lookup streets or postal codes.
- Extract supplied Canada411 search and person-profile URLs.
- Follow server-rendered people-search pagination within your limits.
- Export normalized names, 10-digit phones, addresses, profile URLs, source modes, queries, and lookup statuses.
- Return an explicit `not_found` record when a lookup produces no Canada411 people result.
- Deduplicate the same public profile across lookup routes.

### Who is this Actor for?

**Contact operations teams** can verify whether existing Canadian contact details still match a public directory listing.

**Data enrichment teams** can add source-attributed public phone, address, and profile links to lawful internal records.

**Researchers and journalists** can turn bounded Canada411 searches into structured datasets with traceable source URLs.

**Automation builders** can schedule recurring Apify Tasks and send normalized records to spreadsheets, warehouses, or webhooks.

### Why use this Canada411 lookup workflow?

The Actor uses Canada411's lightweight server-rendered pages instead of a browser. That keeps runs fast and resource-efficient while preserving the useful public fields.

Each output row includes its source mode, query, source URL, extraction timestamp, and match status. These fields make downstream review and change comparison easier than un-attributed copied contact details.

Limits are explicit. The Actor stops at `maxItems` and `maxPages`; it never silently expands into business/category search.

### What data does it extract?

| Field | Type | Meaning |
| --- | --- | --- |
| `name` | string or null | Normalized public listed person name |
| `phone` | string or null | Public phone normalized to 10 digits |
| `address` | string or null | Normalized public listed address |
| `profileUrl` | string or null | Canonical Canada411 person profile URL |
| `sourceUrl` | string | Canada411 page fetched for the record |
| `sourceMode` | string | `people_search`, `reverse_phone`, `reverse_address`, or `url` |
| `query` | string | Lookup value or supplied URL |
| `lookupStatus` | string | `matched` or `not_found` |
| `scrapedAt` | ISO timestamp | Time the record was extracted |

Null contact fields are expected on `not_found` status rows.

### Getting started

1. Open the Actor in Apify Console.
2. Enter a person name and optional Canadian location, add phone numbers, add addresses, or provide Canada411 URLs.
3. Set `maxItems` to your desired dataset size.
4. Keep `maxPages` conservative for broad names.
5. Click **Start**.
6. Review the **Canada411 people records** dataset view.
7. Export JSON, CSV, Excel, XML, or RSS, or connect the dataset to your integration.

A simple first run is:

```json
{
  "name": "John Smith",
  "location": "Toronto ON",
  "maxItems": 10,
  "maxPages": 1
}
```

### Input parameters

#### `name`

A full or partial person name. Use it with `location` to narrow common names.

#### `location`

A Canadian city, province, or postal area. A location by itself is accepted, but a name plus location is usually more useful.

#### `phoneNumbers`

An array of Canadian 10-digit phone numbers. Formatting characters are removed automatically. Invalid lengths fail closed rather than producing misleading matches.

#### `addresses`

An array of objects with `street`, `city`, `province`, and `postalCode`. Each object must contain at least a street or postal code.

```json
{
  "addresses": [
    {
      "street": "21 Rainsford",
      "city": "Toronto",
      "province": "ON"
    }
  ]
}
```

#### `startUrls`

Canada411 people-search, reverse-search, or `/res/` person-profile URLs. Other hosts and unsupported Canada411 paths are rejected.

#### `maxItems`

Maximum output rows across all lookup jobs. Range: 1–10,000. Default: 100.

#### `maxPages`

Maximum people-search pages fetched per lookup. Range: 1–100. Default: 10.

### Output example

A matched record looks like this (example values are illustrative):

```json
{
  "name": "Sample Person",
  "phone": "4165550100",
  "address": "100 Sample Street Toronto ON M1A 1A1",
  "profileUrl": "https://www.canada411.ca/res/4165550100/Sample-Person/123456789.html",
  "sourceUrl": "https://www.canada411.ca/search/?stype=si&what=Sample+Person&where=Toronto+ON",
  "sourceMode": "people_search",
  "query": "Sample Person in Toronto ON",
  "lookupStatus": "matched",
  "scrapedAt": "2026-01-15T12:00:00.000Z"
}
```

A lookup without a people match returns one status row with null contact fields and `lookupStatus: "not_found"`.

### How much does it cost to extract Canada411 people records?

This Actor uses pay-per-event pricing: a one-time **$0.0007 run-start fee** plus one item event for each matched or not-found record saved. The current per-record tiers decrease with your Apify plan:

| Plan | Price per record |
| --- | ---: |
| Free | $0.000184 |
| Bronze | $0.000160 |
| Silver | $0.0001248 |
| Gold | $0.000096 |
| Platinum | $0.000064 |
| Diamond | $0.0000448 |

At Bronze pricing, 10 records cost about **$0.0023**, 100 records about **$0.0167**, and 1,000 records about **$0.1607**, including one start event. Platform compute is included in pay-per-event pricing, subject to Apify's current billing terms.

### Pagination, limits, and deduplication

People and reverse-address searches may have multiple pages. `maxPages` bounds work for every lookup, while `maxItems` bounds the whole run.

The Actor follows only Canada411 pagination links. It deduplicates by canonical person profile URL, or by normalized phone and address when no profile link exists.

When the same person matches several inputs, the first saved record is retained. This prevents duplicate downstream charges and rows.

### Reverse lookup behavior

Reverse phone accepts normalized Canadian 10-digit numbers. A public people listing can resolve directly to a person detail page.

Some numbers resolve to businesses and redirect to YellowPages.ca. Because business search is excluded, the Actor does not scrape that external page; it emits a `not_found` people-status record.

Reverse address supports street, city, province, and postal-code combinations exposed by Canada411's public form.

### Tips for useful results

- Add a city and province for common names.
- Begin broad searches with one page, inspect quality, then raise `maxPages`.
- Normalize your own input identifiers and retain `query` when joining outputs.
- Use smaller scheduled batches instead of one very large common-name search.
- Treat `not_found` as “no public Canada411 people match observed,” not proof that a person or phone does not exist.
- Keep `sourceUrl` and `scrapedAt` for auditability.

### Failure and retry behavior

The Actor retries transient network errors, HTTP 429 responses, and temporary server errors up to three times with a short backoff.

Malformed phone numbers, external URLs, and unsupported Canada411 paths fail the run immediately.

Challenge pages and unrecognized HTML fail visibly rather than being reported as empty results. External business redirects are handled as valid out-of-scope `not_found` people lookups.

### Scheduling contact verification

Create an Apify Task with a stable input set, then schedule it daily, weekly, or monthly. Send completed-run data through a webhook or integration.

For change detection, compare stable `profileUrl`, `phone`, and `address` fields between run datasets. The Actor does not itself maintain history or send change alerts.

### Export and integrations

The default dataset can be downloaded as JSON, CSV, Excel, XML, HTML, or RSS.

Common workflows include:

- Google Sheets contact-review queues;
- Make or Zapier enrichment automations;
- webhook delivery after a scheduled Task;
- BigQuery, Snowflake, or PostgreSQL ingestion;
- Python or JavaScript dataset post-processing;
- source-attributed CRM review, where lawful.

### Run through the Apify API with cURL

```bash
curl -X POST \
  "https://api.apify.com/v2/acts/automation-lab~canada411-directory-scraper/runs?token=$APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"phoneNumbers":["416-699-4961"],"maxItems":5}'
```

To wait for completion and receive dataset items:

```bash
curl -X POST \
  "https://api.apify.com/v2/acts/automation-lab~canada411-directory-scraper/run-sync-get-dataset-items?token=$APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name":"John Smith","location":"Toronto ON","maxItems":10,"maxPages":1}'
```

### Run with JavaScript

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

const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('automation-lab/canada411-directory-scraper').call({
  phoneNumbers: ['416-699-4961'],
  maxItems: 5,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items);
```

### Run with Python

```python
import os
from apify_client import ApifyClient

client = ApifyClient(os.environ['APIFY_TOKEN'])
run = client.actor('automation-lab/canada411-directory-scraper').call(run_input={
    'name': 'John Smith',
    'location': 'Toronto ON',
    'maxItems': 10,
    'maxPages': 1,
})
items = client.dataset(run['defaultDatasetId']).list_items().items
print(items)
```

### Use with Apify MCP

#### Claude Code

Add the Actor to Claude Code:

```bash
claude mcp add --transport http apify \
  "https://mcp.apify.com?tools=automation-lab/canada411-directory-scraper"
```

#### Claude Desktop, Cursor, and VS Code

Claude Desktop, Cursor, and VS Code can use the equivalent remote MCP configuration:

```json
{
  "mcpServers": {
    "apify": {
      "url": "https://mcp.apify.com?tools=automation-lab/canada411-directory-scraper"
    }
  }
}
```

Example prompts:

- “Run Canada411 Scraper for John Smith in Toronto ON, limited to 10 results.”
- “Reverse lookup these Canadian phone numbers and return names, addresses, match statuses, and source links.”
- “Check this list of Toronto addresses and format matched public Canada411 records as CSV.”

### Responsible use and legality

Canada411 exposes public directory information, but public availability does not remove privacy, contractual, or legal obligations.

Use the Actor only for lawful purposes. Follow Canada411's applicable terms, robots rules, rate expectations, and Canadian privacy and anti-spam laws. Do not use output for harassment, discrimination, stalking, identity theft, unsolicited messaging, or decisions that require consent or authoritative verification.

Minimize collection, secure exported data, set retention limits, and honor deletion or suppression obligations. Consult qualified counsel for your use case.

### Limitations

- People records only; business/category search is excluded.
- Results depend on what Canada411 publicly lists at run time.
- A missing match is not an authoritative identity or occupancy conclusion.
- Names may be common, abbreviated, stale, or shared.
- Address text is normalized for whitespace but not geocoded or independently verified.
- The Actor does not provide historical snapshots, monitoring alerts, or private/unlisted numbers.
- Canada411 markup or access behavior can change.

### FAQ

#### Can I search Canada411 Ottawa records?

Yes. Set a name and `location` such as `Ottawa ON`. Use a narrow name and conservative page limit for useful results.

#### Does it support Canada411 reverse address lookup?

Yes. Supply `addresses` with a street or postal code and optional city/province fields.

#### Why did a phone return `not_found`?

The number may have no public people listing, may be unlisted, or may redirect to an out-of-scope business record. Check `sourceMode`, `query`, and `sourceUrl` before drawing conclusions.

#### Why did my run fail instead of returning zero records?

Malformed inputs, unsupported hosts, upstream challenges, and unrecognized source pages fail visibly to avoid misleading empty datasets.

#### Can I scrape business listings?

No. Canada411 routes business lookup to YellowPages.ca. This Actor intentionally excludes that separate source and workflow.

#### How do I avoid too many common-name records?

Add a city and province, reduce `maxPages`, and begin with a small `maxItems` value.

### Related automation-lab Actors

- [AnyWho People Search Scraper](https://apify.com/automation-lab/anywho-people-search-scraper) for supported US people-directory workflows.
- [Business Reverse Phone Lookup](https://apify.com/automation-lab/business-reverse-phone-lookup) for public business-oriented phone resolution.

Choose the Actor whose source, country, and entity scope match your lawful workflow.

### Support

For reproducible problems, include the input shape (with sensitive values removed), run ID, expected mode, observed status, and whether the failure affected every lookup or one source record. Do not post private contact lists or credentials in support messages.

# Actor input Schema

## `name` (type: `string`):

Full or partial person name, for example John Smith.

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

Canadian city, province, or postal area used with the person name.

## `phoneNumbers` (type: `array`):

Canadian 10-digit phone numbers to look up.

## `addresses` (type: `array`):

Addresses to look up. Each entry needs a street or postal code.

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

Canada411 people search, reverse lookup, or person profile URLs.

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

Stop after this many matched or not-found records.

## `maxPages` (type: `integer`):

Safety limit for paginated people and address searches.

## Actor input object example

```json
{
  "name": "John Smith",
  "location": "Toronto ON",
  "maxItems": 10,
  "maxPages": 10
}
```

# Actor output Schema

## `overview` (type: `string`):

Normalized Canada411 people and lookup-status records.

# 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 = {
    "name": "John Smith",
    "location": "Toronto ON",
    "maxItems": 10
};

// Run the Actor and wait for it to finish
const run = await client.actor("automation-lab/canada411-directory-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 = {
    "name": "John Smith",
    "location": "Toronto ON",
    "maxItems": 10,
}

# Run the Actor and wait for it to finish
run = client.actor("automation-lab/canada411-directory-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 '{
  "name": "John Smith",
  "location": "Toronto ON",
  "maxItems": 10
}' |
apify call automation-lab/canada411-directory-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,automation-lab/canada411-directory-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/tMszJwCvijIbXiFAl/builds/vHjsUELGpWMmT2Biz/openapi.json
