# YouTube Channel Email Finder (`vakitek/youtube-channel-email`) Actor

Find business emails of YouTube creators from channel links, keywords or video URLs. Checks the about page, linked websites, link-in-bio pages and video descriptions. 4.50 USD per 1,000 emails, channels with no email are free.

- **URL**: https://apify.com/vakitek/youtube-channel-email.md
- **Developed by:** [Brahim Sliti](https://apify.com/vakitek) (community)
- **Categories:** Lead generation, Social media
- **Stats:** 42 total users, 5 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $4.50 / 1,000 channel with email founds

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

## YouTube Channel Email Finder

Give it YouTube channels or search keywords, get back the business email of each creator when one is public. You get one row per channel, with the email, where it was found and whether its mail server is valid.

You only pay for channels where an email was found. A channel with no email still comes back in the dataset, for free.

### What people use it for

- **Influencer outreach.** Search a niche ("home espresso", "b2b saas") and get a list of creators with their contact email, subscriber count and country.
- **Sponsorship and partnership teams.** Paste the channels you already shortlisted and get the address to pitch.
- **Agencies building creator databases.** Run thousands of channels and keep only the ones with a reachable email.
- **Enriching a CRM.** You have channel URLs in a sheet, you want the emails next to them.

### How to use it

1. Add your creators in **Channels**, one per line. Any of these works:
   - a handle: `@mkbhd` or `mkbhd`
   - a channel URL: `https://www.youtube.com/@veritasium`
   - a channel id: `UCX6OQ3DkcsbYNE6H8uQQuVA`
   - a video URL (we find the channel that posted it)
2. Or add **Search keywords** to discover channels, and set **Max channels per keyword** (default 20).
3. Click **Start**. Export as JSON, CSV or Excel, or pull the results through the API.

```json
{
  "channels": ["@mkbhd", "https://www.youtube.com/@veritasium"],
  "searchQueries": ["home espresso"],
  "maxChannelsPerQuery": 20
}
```

### What you get

```json
{
  "name": "MKBHD",
  "url": "https://www.youtube.com/@mkbhd",
  "handle": "@mkbhd",
  "numberOfSubscribers": 21300000,
  "country": "United States",
  "emails": [
    {
      "email": "business@MKBHD.com",
      "source": "description",
      "sourceUrl": "https://www.youtube.com/@mkbhd/about",
      "mxValid": true
    }
  ],
  "primaryEmail": "business@MKBHD.com",
  "hasHiddenEmail": true,
  "links": [{ "title": "Twitter", "url": "https://twitter.com/MKBHD" }],
  "emailSource": "public"
}
```

- `primaryEmail`: the address to use. When a channel has several, we pick a valid business address (`business@`, `partnerships@`, `contact@`...) over a personal or utility one.
- `emails[]`: every email found, with `source` (about page, channel links, video descriptions, website, link-in-bio page) and the exact `sourceUrl`, so you can check it yourself.
- `mxValid`: whether the domain's mail server exists.
- `hasHiddenEmail`: `true` when the creator also has an email behind YouTube's "View email address" button.
- Subscribers, country and the channel's links come with every row.

### Where the emails come from

For each channel we look at:

1. the about page description and the links listed on the channel
2. the creator's own website (home page, then pages like `/contact` or `/about`) and link-in-bio pages such as Linktree, Beacons or Stan Store
3. if still nothing, the descriptions of the 10 most recent videos. We keep only an email that appears in several of them, so a sponsor's address in one video does not end up as the creator's
4. if still nothing, a deep search (see below)

We drop emails that belong to sponsors, brands or platforms the creator links to (Patreon, Skool, Gumroad...). You get the creator's address or nothing.

#### Deep search

When the creator publishes no email anywhere, we try to find their professional email from who they are, not from what they posted:

- if the channel links to the creator's personal LinkedIn profile, we use it to look up their work email;
- otherwise, we take the creator's name from the channel and the domain of their own website, or of the company their channel says they run (for example "CEO at Acme" with a link to `acme.com`), and look up the address at that domain.

We never search a sponsor's or a brand's domain, nor a platform the creator merely uses (Patreon, Skool, Gumroad, Shopify...). You are charged only when the lookup returns a valid email, and it becomes `primaryEmail` only with a high or medium confidence. When there is nothing to search with, the step is skipped and the channel comes back without email, for free.

These emails are marked `"source": "deep_search"` and `"emailSource": "deep_search"`, so you can tell them apart from the ones the creator published, and carry `verified` and `confidence` fields. Deep search runs automatically and costs 0.10 USD per email found, never on a miss (see Pricing).

### Pricing

- **4.50 USD per 1,000 channels with a public email found** (steps 1 to 3 above).
- **100 USD per 1,000 channels found by deep search** (0.10 USD each), charged only when it returns a valid email, and only on channels where nothing public was found.
- A channel is charged once at most. Channels with no email, and error rows, are free.

No monthly fee, no charge for the Apify platform usage on top. You can cap a run's spend with Apify's "max charge per run" setting.

Example: 1,000 channels where 400 have a public email and the deep search finds 50 more costs 1.80 + 5.00 = 6.80 USD.

### Good to know

- **We do not click "View email address".** That email sits behind a Google sign-in and often a captcha, and we never use logged-in accounts. Many large creators only publish their email there: you get `hasHiddenEmail: true` and no address for those.
- You don't need a proxy or a YouTube account.

### Use it from n8n, Make or an API

- **Small inputs**: call `run-sync-get-dataset-items` and read the items back directly. Set **Time budget (seconds)** (default 240) to how long you are willing to wait: the actor stops starting new channel lookups before that point and returns what it already has, so you never hit Apify's 300 second run-sync limit and lose the whole run. Any channel or keyword left unfinished comes back as a `TIME_BUDGET_EXCEEDED` row instead of being silently dropped.
- **Big inputs**: start the run with `POST /v2/acts/vakitek~youtube-channel-email/runs`, poll `GET /v2/actor-runs/<runId>` (or add `waitForFinish=60`) until the status is `SUCCEEDED`, then read `GET /v2/datasets/<datasetId>/items`. Set **Time budget (seconds)** to `0` (no limit) for this pattern.

### Errors

A bad input never crashes the run. It becomes a row with an `error` code, and you are not charged for it.

| `error` | What happened | Retry? |
| --- | --- | --- |
| `NOT_FOUND` | The handle, URL or id doesn't match a real channel | No |
| `NO_RESULTS` | A search query matched no channel | No |
| `INVALID_URL` | The channel input isn't a channel handle, id or URL | No |
| `INVALID_INPUT` | A query or option value is invalid | No |
| `DUPLICATE` | Two different inputs resolved to the same channel; the second one is free | No |
| `BLOCKED` | YouTube refused us for now, even after trying every proxy tier | Yes |
| `UPSTREAM_ERROR` | Something went wrong on YouTube's side or ours | Yes |
| `UPSTREAM_UNAVAILABLE` | Our API was unreachable | Yes |
| `TIME_BUDGET_EXCEEDED` | The time budget ran out before this channel or keyword finished | Yes |

Some rows also carry a `legacyError` field with the old, pre-unification code name (for example `CHANNEL_NOT_FOUND` or `LOGIN_REQUIRED`) so a pipeline still matching on it keeps working while it migrates to `error`.

### Reliability

Success rate, last 30 days: 99.0 % of 98 results across 36 runs (updated 2026-10-10). Failures counted: blocks, errors on our side, and runs that failed or timed out. Not counted: videos with no captions, private or deleted videos, bad links.

### FAQ

**Why do I get no email for a big creator I know has one?**
Their email is probably behind YouTube's "View email address" button, which needs a signed-in account. Check `hasHiddenEmail`: if it's `true`, that's the reason.

**Are the emails verified?**
We check that the domain has a working mail server (`mxValid`). That catches typos and dead domains, but it doesn't guarantee the inbox exists.

**I already use another YouTube email actor. Do I have to change my code?**
Probably not much. We use the same input `channels` and the same output fields `emails`, `primaryEmail` and `hasHiddenEmail`.

**Can I call it from my code or from an AI agent?**
Yes, like any Apify actor: REST API, the Python and JavaScript clients, or the Apify MCP server. The examples are in the API tab.

**Something broke or an email looks wrong?**
Open an issue on this page with the channel. We read every one and usually answer within a day.

# Changelog

This Actor's version history is a separate document: https://apify.com/vakitek/youtube-channel-email/changelog.md

# Actor input Schema

## `channels` (type: `array`):

YouTube channels, with or without @ (e.g. mkbhd or @mkbhd), full channel URLs, channel ids (UC...), or video URLs (resolved to their channel).

## `searchQueries` (type: `array`):

Each keyword runs a YouTube search and processes the channels behind the matching videos, up to "Max channels per keyword" each.

## `maxChannelsPerQuery` (type: `integer`):

Cap on distinct channels discovered per search keyword.

## `timeBudgetSecs` (type: `integer`):

Stop and return what is ready after this many seconds, so n8n/Make run-sync calls never time out. 0 = no limit.

## Actor input object example

```json
{
  "channels": [
    "@mkbhd"
  ],
  "searchQueries": [],
  "maxChannelsPerQuery": 20,
  "timeBudgetSecs": 240
}
```

# Actor output Schema

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

One item per channel: channel info, the creator's own emails, `primaryEmail` and `emailSource` (public or deep_search). Channels without an email are returned too, at no charge.

# 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 = {
    "channels": [
        "@mkbhd"
    ],
    "searchQueries": []
};

// Run the Actor and wait for it to finish
const run = await client.actor("vakitek/youtube-channel-email").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 = {
    "channels": ["@mkbhd"],
    "searchQueries": [],
}

# Run the Actor and wait for it to finish
run = client.actor("vakitek/youtube-channel-email").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 '{
  "channels": [
    "@mkbhd"
  ],
  "searchQueries": []
}' |
apify call vakitek/youtube-channel-email --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,vakitek/youtube-channel-email"
        }
    }
}
```

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/Xycevks3EWYeE8WWq/builds/epQhAXU9VC9P4xM5O/openapi.json
