# N49 Email Scraper (`neuro-scraper/n49-email-scraper`) Actor

N49 Email Scraper SD - N49 Email Scraper is a lead generation tool that extracts leads with public contact emails, account names and profile URLs from N49 results by keyword, location and email domain - N49 email extractor.

- **URL**: https://apify.com/neuro-scraper/n49-email-scraper.md
- **Developed by:** [Neuro Scraper](https://apify.com/neuro-scraper) (community)
- **Categories:**
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.49 / 1,000 results

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

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

### N49 Email Scraper

The N49 Email Scraper extracts publicly indexed business emails from N49, a local business directory with deep Canadian coverage across `n49.com` and `n49.ca`. It was the single strongest performer in our benchmark of this Actor family.

In our measured Google run the N49 Email Scraper parsed 10 result blocks, named a business in all 10, resolved a profile URL for all 10, and produced 10 unique emails. A perfect ten across every metric.

That makes it the default choice if your territory is Canadian. Pair it with a US-focused sibling such as the [Yellow Pages Email Scraper](https://apify.com/leads-scraper/yellow-pages-email-scraper) when your market spans the border.

#### What the N49 Email Scraper does

The N49 Email Scraper builds Google queries with the `site:` operator against `n49.com` and `n49.ca`. It parses each result block structurally, locating the `<h3>` title and the smallest surrounding block.

A domain-filtered regex then extracts emails from the block text. Matches are normalised, deduplicated globally and pushed to your Apify dataset immediately.

The N49 Email Scraper never logs into N49, never uses an N49 API and never opens the N49 website. There is no browser, no JavaScript rendering, no authentication and no cookies.

#### Why the N49 Email Scraper is the pick for Canadian territories

Most local directory data is built for the United States and treats Canada as an afterthought. N49 does the opposite, with genuine depth across Ontario, Quebec, Alberta and British Columbia.

For a marketing agency selling retainers in Mississauga or a SaaS vendor targeting Calgary trades, the N49 Email Scraper reaches businesses that a US-first directory simply does not list.

Franchise developers assessing a Canadian territory get the same benefit. So do market researchers who need province-level density rather than a national average.

#### Features of the N49 Email Scraper

Everything in this table ships in the N49 Email Scraper today.

| Feature | What it means in practice |
|---|---|
| Google `site:` search over `n49.com` and `n49.ca` | Covers both N49 domains in one run |
| Query expansion | Base, quoted and `intitle:` variants plus one query per modifier; base queries run first |
| Domain filtering | Only emails ending in your `customDomains` values are kept |
| Global deduplication | Each email is emitted once per run across every query and page |
| Email normalisation | Handles `name [at] domain [dot] com`, `name (at) domain`, `name @ domain.com`, `domain .com`, zero-width characters and the full-width `＠` |
| Junk filter | Rejects `email@`, `yourname@`, `test@`, `xxx@` and single-character locals |
| Boundary-correct matching | `@gmail.com` does not match inside `@gmail.company` or `@gmail.com.br` |
| Soft-wrap repair | Drops a hit that is only the tail of another email in the same block |
| Structural block parsing | Works from the `<h3>` title, never from Google's CSS class names |
| Whole-page fallback parser | A markup change degrades to "emails without account details", not "no emails" |
| Concurrency control | `asyncio` worker pool with a shared stop signal on `maxEmails` |
| Retries and block detection | Up to 3 attempts per page, exponential backoff, fresh proxy session per request, CAPTCHA and consent pages detected and retried |
| Failed-query requeue | Blocked or failed queries are retried once at the end of the run |
| Resumable state | Key-value store state keyed by an input hash, saved on `PERSIST_STATE`, `MIGRATING` and `ABORTING` |
| Run summary logging | Pages fetched, blocked pages, retries and emails per page |

#### How the N49 Email Scraper works

A run of the N49 Email Scraper follows six steps from input to dataset.

1. Read your input: keywords, location, email domains and limits.
2. Build queries such as `site:n49.ca renovation contractor "@gmail.com" "Mississauga"`.
3. Fetch Google result pages through the Apify GOOGLE\_SERP proxy using async `aiohttp`.
4. Parse each result block structurally to isolate title, business label and snippet.
5. Extract and normalise emails with a domain-filtered regex.
6. Deduplicate globally and push each lead to the dataset immediately.

The N49 Email Scraper streams rows as it finds them, so aborting a long run never discards work already done.

#### Input fields for the N49 Email Scraper

These are the exact inputs the N49 Email Scraper accepts, with its shipped defaults.

| Field | Type | Default | Meaning |
|---|---|---|---|
| `keywords` | array (required) | `["local business", "contractor"]` | Search terms describing the businesses you want |
| `location` | string | `""` | Optional location phrase added to every query |
| `customDomains` | array | `["@gmail.com", "@yahoo.com"]` | Only emails on these domains are kept; `@` optional |
| `maxEmails` | integer 1-10000 | `20` | Stop after this many unique emails |
| `countryCode` | string | `""` | Two-letter country for the search proxy (US, GB, DE...) |
| `expandQueries` | boolean | `true` | Search each keyword x domain pair in several phrasings |
| `queryModifiers` | array | `["email", "contact", "enquiries", "owner", "get a quote"]` | Extra words combined with each keyword when expansion is on |
| `maxPagesPerQuery` | integer 1-50 | `30` | Page cap per query |
| `maxConcurrency` | integer 1-20 | `5` | Parallel queries |

#### Example input for the N49 Email Scraper

```json
{
  "keywords": ["renovation contractor", "roofing", "landscaping"],
  "location": "Mississauga, ON",
  "customDomains": ["@gmail.com", "@yahoo.ca", "@hotmail.com", "@rogers.com"],
  "maxEmails": 500,
  "countryCode": "CA",
  "expandQueries": true,
  "queryModifiers": ["email", "contact", "owner", "get a quote"],
  "maxPagesPerQuery": 30,
  "maxConcurrency": 5
}
```

#### Location: the highest-leverage input in the N49 Email Scraper

Canadian geography is concentrated, which plays to the N49 Email Scraper's strengths. A handful of well-chosen city runs covers a very large share of the addressable market.

Start with `"Toronto, ON"`, `"Mississauga, ON"`, `"Brampton, ON"`, `"Ottawa, ON"`, `"Calgary, AB"`, `"Edmonton, AB"`, `"Vancouver, BC"` and `"Surrey, BC"`.

Then fill in the second tier: `"Winnipeg, MB"`, `"Halifax, NS"`, `"Quebec City, QC"`, `"Saskatoon, SK"` and `"Victoria, BC"`.

Google caps a single query at roughly 300 results, so one city per run beats one province per run. Set `countryCode` to `CA` so the N49 Email Scraper searches from a Canadian vantage point.

For Quebec, try French-language keywords such as `"entrepreneur en renovation"` alongside the English terms.

#### Output fields from the N49 Email Scraper

Every dataset item written by the N49 Email Scraper carries all fourteen fields below.

| Field | Meaning |
|---|---|
| `network` | Platform name |
| `keyword` | The keyword that produced the lead |
| `query` | The exact Google query used |
| `title` | Raw result title |
| `accountName` | Account label Google prints |
| `fullName` | Display name parsed from a profile-style title; empty for post captions |
| `username` | URL-safe handle when the platform exposes one; otherwise `null` |
| `profileUrl` | Canonical account URL when a handle is known; otherwise empty |
| `url` | Direct platform link when exposed, else the profile URL |
| `description` | Bio snippet, cleaned of labels and engagement counters |
| `email` | Lower-cased email address |
| `emailDomain` | The matched domain |
| `possiblyTruncated` | `true` when Google's snippet ellipsis touched the email |
| `foundAt` | ISO 8601 UTC timestamp |

#### Example output from the N49 Email Scraper

```json
[
  {
    "network": "N49",
    "keyword": "renovation contractor",
    "query": "site:n49.ca renovation contractor \"@gmail.com\" \"Mississauga, ON\"",
    "title": "Lakeshore Renovations Inc - Mississauga, ON - N49",
    "accountName": "Lakeshore Renovations Inc",
    "fullName": "Lakeshore Renovations Inc",
    "username": "lakeshore-renovations-inc",
    "profileUrl": "https://www.n49.com/biz/lakeshore-renovations-inc/",
    "url": "https://www.n49.com/biz/lakeshore-renovations-inc/",
    "description": "Kitchen, bath and basement renovations across Peel Region. Free estimates: lakeshorereno.on@gmail.com",
    "email": "lakeshorereno.on@gmail.com",
    "emailDomain": "@gmail.com",
    "possiblyTruncated": false,
    "foundAt": "2026-08-31T18:04:52.310Z"
  },
  {
    "network": "N49",
    "keyword": "landscaping",
    "query": "site:n49.com landscaping \"@hotmail.com\" \"Mississauga, ON\"",
    "title": "Credit Valley Landscaping - N49",
    "accountName": "Credit Valley Landscaping",
    "fullName": "Credit Valley Landscaping",
    "username": "credit-valley-landscaping",
    "profileUrl": "https://www.n49.com/biz/credit-valley-landscaping/",
    "url": "https://www.n49.com/biz/credit-valley-landscaping/",
    "description": "Interlock, sodding and seasonal maintenance in Mississauga and Oakville. cvlandscaping@hotmail.com",
    "email": "cvlandscaping@hotmail.com",
    "emailDomain": "@hotmail.com",
    "possiblyTruncated": false,
    "foundAt": "2026-08-31T18:06:18.927Z"
  }
]
```

#### Use cases for the N49 Email Scraper

The N49 Email Scraper is the tool to reach for whenever the territory is Canadian.

| Use case | Who runs it | Typical setup |
|---|---|---|
| Canadian home-services agency lists | Local marketing agency | `["roofing", "renovation contractor"]`, `location: "Mississauga, ON"` |
| Field-service SaaS prospecting | B2B SaaS | `["hvac", "plumbing"]`, `location: "Calgary, AB"` |
| Franchise territory assessment | Franchise development | `["cleaning service"]`, several Ontario cities |
| Commercial insurance outreach | Insurance brokerage | `["landscaping", "snow removal"]`, `location: "Ottawa, ON"` |
| Provincial market sizing | Market researcher | One keyword, 12 city runs, compare unique counts |
| Bilingual campaign build | Agency serving Quebec | English and French keywords, `location: "Montreal, QC"` |
| Supplier recruitment | Distributor | `["auto repair"]`, `location: "Vancouver, BC"` |
| Cross-border list build | RevOps team | Merge N49 rows with Yellow Pages and BBB datasets |

#### Tuning the N49 Email Scraper for better yield

Use Canadian webmail domains, not just American ones. Add `@yahoo.ca`, `@rogers.com`, `@shaw.ca`, `@bell.net`, `@sympatico.ca` and `@telus.net` to `customDomains`.

Pick trade terms Canadians actually use. `"snow removal"`, `"interlock"`, `"eavestrough"` and `"reno"` behave very differently from generic American phrasing.

Leave `expandQueries` on so the N49 Email Scraper routes around Google's per-query ceiling. Base queries run first, so the strongest results arrive early.

Keep `maxConcurrency` near 5. Pushing higher raises the share of blocked pages that need retrying without much throughput gain.

#### What to expect from an N49 Email Scraper run

Our measured Google run of the N49 Email Scraper returned 10 parsed blocks, 10 identified businesses, 10 resolved profile URLs and 10 unique emails. Nothing else in the family matched that.

Practically, that means you can trust `profileUrl` here. Verification, enrichment and manual QA are all easier when almost every row links to a canonical listing.

Volume still varies with keyword, domain list and location, and no volume is guaranteed. A niche trade in Saskatoon returns less than a broad trade in Toronto.

#### Responsible use, CASL, GDPR and CAN-SPAM

Canada's anti-spam legislation is stricter than CAN-SPAM, and this matters for anything the N49 Email Scraper produces. This section is guidance, not legal advice.

CASL generally requires consent before sending commercial electronic messages, though it recognises implied consent where a business has conspicuously published an address without a statement refusing such messages, and where the message is relevant to that business role. Every message must identify the sender and offer a working unsubscribe.

CAN-SPAM applies to US recipients: accurate headers, an honest subject line, a physical postal address and a prompt opt-out. GDPR and UK GDPR apply if any of your contacts are European.

An owner's `firstname@gmail.com` is personal data even when published commercially. Suppress opt-outs, keep provenance records, and do not resell the raw dataset.

#### Limitations of the N49 Email Scraper

- Only finds businesses whose email is publicly visible in Google's index. Listings hiding contact details behind a form will not appear.
- Google caps a single query at roughly 300 results, which is why query expansion exists.
- `possiblyTruncated: true` means Google's snippet ellipsis touched the address - verify before sending.
- `username` and `profileUrl` are populated only when Google's result exposes a handle. Resolution was 10 of 10 in our measured run, but it is not guaranteed on every row. This is a Google limitation, not a bug.
- Requires the Apify GOOGLE\_SERP proxy; the N49 Email Scraper cannot run without Apify proxy credentials.
- Free Apify plans are capped at 100 emails per run; paid plans are uncapped.
- Coverage is strongest in Canada; US results are thinner than a US-first directory would give.
- Results vary with keywords, domains and location, and no volume is guaranteed.

#### N49 Email Scraper FAQ

**How many results should I expect from the N49 Email Scraper?**
Our measured run parsed 10 blocks, identified 10 businesses, resolved 10 profile URLs and produced 10 unique emails - the best result in this family. Totals scale with the cities and trades you queue.

**Which domains does it search?**
Both `n49.com` and `n49.ca`, in the same run.

**Is the N49 Email Scraper Canada-only?**
Coverage is strongest in Canada. It will return US rows, but a US-first directory such as Yellow Pages or Manta will do better south of the border.

**Does it log into N49?**
No. The N49 Email Scraper never logs in, never uses an N49 API and never opens the N49 website. Everything comes from publicly indexed Google results.

**How should I handle CASL?**
Take advice for your situation. In general, rely on published business addresses relevant to the recipient's role, identify yourself clearly, and always include a working unsubscribe.

**Can I target Canadian ISP domains?**
Yes. Add `@rogers.com`, `@shaw.ca`, `@bell.net`, `@sympatico.ca`, `@telus.net` or `@yahoo.ca` to `customDomains`.

**Does French-language search work?**
Yes. French keywords with `location: "Montreal, QC"` reach listings that English terms miss.

**What does `possiblyTruncated` mean?**
Google's snippet ellipsis touched the email, so the address may be cut short. Verify or exclude those rows before sending.

**Do I need Apify proxy credentials?**
Yes. The N49 Email Scraper runs on the Apify GOOGLE\_SERP proxy and cannot operate without it.

**How do I cover a whole province?**
Run the N49 Email Scraper one city at a time and merge datasets. That beats Google's per-query cap far better than a single provincial query.

**Is the free plan enough?**
For evaluation, yes - it caps a run at 100 emails. Paid plans remove the cap.

**Which sibling Actors pair best with this one?**
The [Better Business Bureau Email Scraper](https://apify.com/leads-scraper/better-business-bureau-email-scraper) also covers Canada, the [Cylex Email Scraper](https://apify.com/neuro-scraper/cylex-email-scraper) adds `cylex.ca`, and the [Brownbook Email Scraper](https://apify.com/neuro-scraper/brownbook-email-scraper) extends the same workflow worldwide.

### Related Actors

| Actor | What it collects |
|---|---|
| [N49 Phone Number Scraper](https://apify.com/neuro-scraper/n49-phone-number-scraper) | Public phone numbers from N49 |
| [Angi Email Scraper](https://apify.com/leads-scraper/angi-email-scraper) | Public contact emails from Angi |
| [Bark Email Scraper](https://apify.com/leads-scraper/bark-email-scraper) | Public contact emails from Bark |
| [Better Business Bureau Email Scraper](https://apify.com/leads-scraper/better-business-bureau-email-scraper) | Public contact emails from Better Business Bureau |
| [Bizapedia Email Scraper](https://apify.com/neuro-scraper/bizapedia-email-scraper) | Public contact emails from Bizapedia |
| [Brownbook Email Scraper](https://apify.com/neuro-scraper/brownbook-email-scraper) | Public contact emails from Brownbook |
| [Callupcontact Email Scraper](https://apify.com/neuro-scraper/callupcontact-email-scraper) | Public contact emails from CallUpContact |
| [Capterra Email Scraper](https://apify.com/leads-scraper/capterra-email-scraper) | Public contact emails from Capterra |
| [Clutch Email Scraper](https://apify.com/leads-scraper/clutch-email-scraper) | Public contact emails from Clutch |
| [Crunchbase Email Scraper](https://apify.com/leads-scraper/crunchbase-email-scraper) | Public contact emails from Crunchbase |
| [Cybo Email Scraper](https://apify.com/neuro-scraper/cybo-email-scraper) | Public contact emails from Cybo |
| [Cylex Email Scraper](https://apify.com/neuro-scraper/cylex-email-scraper) | Public contact emails from Cylex |
| [EC21 Email Scraper](https://apify.com/neuro-scraper/ec21-email-scraper) | Public contact emails from EC21 |
| [Europages Email Scraper](https://apify.com/leads-scraper/europages-email-scraper) | Public contact emails from Europages |
| [ExportHub Email Scraper](https://apify.com/neuro-scraper/exporthub-email-scraper) | Public contact emails from ExportHub |
| [FindUsLocal Email Scraper](https://apify.com/neuro-scraper/finduslocal-email-scraper) | Public contact emails from FindUsLocal |
| [Foursquare Email Scraper](https://apify.com/neuro-scraper/foursquare-email-scraper) | Public contact emails from Foursquare |
| [Fyple Email Scraper](https://apify.com/neuro-scraper/fyple-email-scraper) | Public contact emails from Fyple |
| [G2 Email Scraper](https://apify.com/neuro-scraper/g2-email-scraper) | Public contact emails from G2 |
| [Hotfrog Email Scraper](https://apify.com/leads-scraper/hotfrog-email-scraper) | Public contact emails from Hotfrog |
| [Houzz Email Scraper](https://apify.com/leads-scraper/houzz-email-scraper) | Public contact emails from Houzz |
| [Infobel Email Scraper](https://apify.com/neuro-scraper/infobel-email-scraper) | Public contact emails from Infobel |
| [Kompass Email Scraper](https://apify.com/leads-scraper/kompass-email-scraper) | Public contact emails from Kompass |
| [Lacartes Email Scraper](https://apify.com/neuro-scraper/lacartes-email-scraper) | Public contact emails from Lacartes |
| [Manta Email Scraper](https://apify.com/leads-scraper/manta-email-scraper) | Public contact emails from Manta |
| [MapQuest Email Scraper](https://apify.com/neuro-scraper/mapquest-email-scraper) | Public contact emails from MapQuest |
| [Porch Email Scraper](https://apify.com/neuro-scraper/porch-email-scraper) | Public contact emails from Porch |
| [Scoot Email Scraper](https://apify.com/neuro-scraper/scoot-email-scraper) | Public contact emails from Scoot |
| [Thomasnet Email Scraper](https://apify.com/leads-scraper/thomasnet-email-scraper) | Public contact emails from Thomasnet |
| [Thumbtack Email Scraper](https://apify.com/leads-scraper/thumbtack-email-scraper) | Public contact emails from Thumbtack |
| [Touch Local Email Scraper](https://apify.com/leads-scraper/touch-local-email-scraper) | Public contact emails from Touch Local |
| [TradeIndia Email Scraper](https://apify.com/leads-scraper/tradeindia-email-scraper) | Public contact emails from TradeIndia |
| [Trustpilot Email Scraper](https://apify.com/leads-scraper/trustpilot-email-scraper) | Public contact emails from Trustpilot |
| [Tupalo Email Scraper](https://apify.com/leads-scraper/tupalo-email-scraper) | Public contact emails from Tupalo |
| [Yalwa Email Scraper](https://apify.com/leads-scraper/yalwa-email-scraper) | Public contact emails from Yalwa |
| [Yellow Pages Email Scraper](https://apify.com/leads-scraper/yellow-pages-email-scraper) | Public contact emails from Yellow Pages |
| [Angi Email and Phone Number Scraper](https://apify.com/neuro-scraper/angi-email-and-phone-number-scraper) | Emails and phone numbers from Angi |
| [Bark Email and Phone Number Scraper](https://apify.com/neuro-scraper/bark-email-and-phone-number-scraper) | Emails and phone numbers from Bark |
| [Better Business Bureau Email and Phone Number Scraper](https://apify.com/leads-scraper/better-business-bureau-email-and-phone-number-scraper) | Emails and phone numbers from Better Business Bureau |
| [Bizapedia Email and Phone Number Scraper](https://apify.com/neuro-scraper/bizapedia-email-and-phone-number-scraper) | Emails and phone numbers from Bizapedia |
| [Brownbook Email and Phone Number Scraper](https://apify.com/neuro-scraper/brownbook-email-and-phone-number-scraper) | Emails and phone numbers from Brownbook |
| [CallUpContact Email and Phone Number Scraper](https://apify.com/neuro-scraper/callupcontact-email-and-phone-number-scraper) | Emails and phone numbers from CallUpContact |

# Actor input Schema

## `keywords` (type: `array`):

Search terms describing the N49 accounts you want (niche, job title, industry).

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

Optional location phrase added to every query (e.g. "New York").

## `customDomains` (type: `array`):

Only emails ending with one of these domains are collected. With or without the leading @. Each domain is searched separately, so more domains means more results but a longer run - remove some for a faster, narrower search, or add your own (e.g. @company.com).

## `maxEmails` (type: `integer`):

Stop once this many unique emails have been collected.

## `countryCode` (type: `string`):

Two-letter country code for the search proxy (e.g. US, GB, DE). Empty for any.

## `expandQueries` (type: `boolean`):

Search each keyword x domain pair with several phrasings. Recommended - Google caps a single query at ~300 results.

## `queryModifiers` (type: `array`):

Extra words combined with each keyword when Expand queries is on. Tuned for N49.

## `maxPagesPerQuery` (type: `integer`):

Google rarely returns more than ~30 pages for one query.

## `maxConcurrency` (type: `integer`):

How many queries run in parallel.

## Actor input object example

```json
{
  "keywords": [
    "local business",
    "contractor"
  ],
  "location": "",
  "customDomains": [
    "@gmail.com",
    "@yahoo.com",
    "@outlook.com",
    "@hotmail.com",
    "@icloud.com",
    "@aol.com",
    "@protonmail.com",
    "@live.com",
    "@gmx.com",
    "@mail.com",
    "@yandex.com",
    "@zoho.com"
  ],
  "maxEmails": 20,
  "countryCode": "",
  "expandQueries": true,
  "queryModifiers": [
    "email",
    "contact",
    "enquiries",
    "owner",
    "get a quote"
  ],
  "maxPagesPerQuery": 30,
  "maxConcurrency": 5
}
```

# Actor output Schema

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

Records produced by N49 Email Scraper, stored in the run's default dataset.

# 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 = {
    "keywords": [
        "local business",
        "contractor"
    ],
    "location": "",
    "customDomains": [
        "@gmail.com",
        "@yahoo.com",
        "@outlook.com",
        "@hotmail.com",
        "@icloud.com",
        "@aol.com",
        "@protonmail.com",
        "@live.com",
        "@gmx.com",
        "@mail.com",
        "@yandex.com",
        "@zoho.com"
    ],
    "countryCode": "",
    "queryModifiers": [
        "email",
        "contact",
        "enquiries",
        "owner",
        "get a quote"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("neuro-scraper/n49-email-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 = {
    "keywords": [
        "local business",
        "contractor",
    ],
    "location": "",
    "customDomains": [
        "@gmail.com",
        "@yahoo.com",
        "@outlook.com",
        "@hotmail.com",
        "@icloud.com",
        "@aol.com",
        "@protonmail.com",
        "@live.com",
        "@gmx.com",
        "@mail.com",
        "@yandex.com",
        "@zoho.com",
    ],
    "countryCode": "",
    "queryModifiers": [
        "email",
        "contact",
        "enquiries",
        "owner",
        "get a quote",
    ],
}

# Run the Actor and wait for it to finish
run = client.actor("neuro-scraper/n49-email-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 '{
  "keywords": [
    "local business",
    "contractor"
  ],
  "location": "",
  "customDomains": [
    "@gmail.com",
    "@yahoo.com",
    "@outlook.com",
    "@hotmail.com",
    "@icloud.com",
    "@aol.com",
    "@protonmail.com",
    "@live.com",
    "@gmx.com",
    "@mail.com",
    "@yandex.com",
    "@zoho.com"
  ],
  "countryCode": "",
  "queryModifiers": [
    "email",
    "contact",
    "enquiries",
    "owner",
    "get a quote"
  ]
}' |
apify call neuro-scraper/n49-email-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,neuro-scraper/n49-email-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/jidPyYmO5qojpLWLL/builds/WoKV1fTC0AnCE2oIz/openapi.json
