# YouTube Channel Contact Scraper — Emails, Socials & URLs (`arabiainsights/youtube-email-socials-urls-scraper`) Actor

Extract public YouTube channel emails, social profiles, and website links in batches with source evidence and optional recent video descriptions.

- **URL**: https://apify.com/arabiainsights/youtube-email-socials-urls-scraper.md
- **Developed by:** [Arabia Insights](https://apify.com/arabiainsights) (community)
- **Categories:** Lead generation, Social media
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.50 / 1,000 channel 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?

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

### Extract public YouTube channel emails, social profiles, and links in batch

Find **publicly published contact information** from [YouTube](https://www.youtube.com/) channels in bulk. Supply channel URLs, handles, or channel IDs and receive structured records with source attribution and public channel metadata. Optionally inspect recent public video, Shorts, and completed-stream descriptions for creator contacts and business inquiries.

### Why use this Actor?

- **Native bulk processing:** Process from 1 up to 1,000 channels in a single run. Aliases, handle variations, and duplicate URLs resolving to the same channel are automatically deduplicated while preserving your original input indexes.
- **Accurate source attribution:** Every extracted email, social link, and outbound URL includes the originating YouTube surface (About page, channel profile link, or specific video description) and extraction method.
- **No credentials or browser overhead:** Operates entirely over anonymous HTTP without requiring Google API keys, YouTube logins, browser automation, or pasted session cookies.
- **Data transparency:** Clear distinction between channel-published links and video descriptions (which may include sponsor or affiliate mentions).
- **Export ready:** Download data in JSON, CSV, or Excel formats, or integrate directly with CRMs, outreach sequences, and automated pipelines via the Apify API.

### Extracted data fields

| Field category | Extracted details |
| --- | --- |
| **Emails** | Addresses published in channel About descriptions or recent video descriptions, including standard obfuscated formats (e.g. `user [at] domain [dot] com`). |
| **Social links** | Recognized social profile links published by the channel (Twitter/X, Instagram, TikTok, LinkedIn, Facebook, Discord, Twitch, Patreon, etc.). Social account ownership and profile authenticity are not independently verified. |
| **Website links** | Outbound website destinations, merchandise stores, newsletters, and link aggregation hubs (Linktree, Beacons, etc.). |
| **Source evidence** | Detailed provenance array indicating whether each contact originated from the About tab, an external profile link, or a specific video description, with exact YouTube source URLs. |
| **Channel metadata** | Canonical channel ID, handle, channel title, description, avatar URL, country, and join date. |
| **Public statistics** | Subscriber count, view count, and video count, along with display precision indicators (`exact`, `rounded`, or `unavailable`). |
| **Coverage & status** | Execution status (`success`, `partial`, `not_found`, `blocked`, `unavailable`, `failed`), stop reason, descriptions requested vs. inspected, and surface breakdown. |

### 3-step quick start

1. **Input channel identifiers:** Enter channel handles (e.g. `@GoogleDevelopers`), channel URLs (e.g. `https://www.youtube.com/@TED`), or channel IDs.
2. **Configure scan depth:** Keep **Scan recent video descriptions** disabled for rapid About-only discovery, or enable it to inspect recent video descriptions (default 20 descriptions per channel, maximum 100).
3. **Run and download:** Start the Actor run and download your dataset as JSON, CSV, or Excel. Use JSON format if you require nested source provenance.

### Input configuration

```json
{
  "channels": [
    "@GoogleDevelopers",
    "https://www.youtube.com/@TED"
  ],
  "scanRecentDescriptions": false,
  "maxVideosPerChannel": 20,
  "allowResidentialFallback": false,
  "maxResidentialRequests": 10
}
```

#### Input parameters

- `channels` (*array of strings*, required): 1 to 1,000 YouTube channel URLs, `@handles`, or channel IDs. Aliases and duplicates resolving to the same canonical channel are merged into a single record. Video or playlist URLs are not accepted as channel identifiers. When description scanning is enabled, runs enforce a run-wide limit of 5,000 total planned descriptions (e.g. up to 250 channels at the default depth of 20 \[250 × 20 = 5,000], or up to 50 channels at the maximum depth of 100 \[50 × 100 = 5,000]). Invalid input combinations exceeding 5,000 planned descriptions are validated and rejected before scraping begins rather than silently clamped; split larger batches across sequential runs.
- `scanRecentDescriptions` (*boolean*, optional, default: `false`): When enabled, inspects recent public upload descriptions (videos, Shorts, completed streams) in addition to About pages.
- `maxVideosPerChannel` (*integer*, optional, default: `20`, min: `1`, max: `100`): Maximum public upload descriptions inspected per channel when description scanning is enabled.
- `maxRequests` (*integer*, optional, min: `1`, max: `250000`): Optional run-wide request limit covering direct requests, retries, redirects, and residential fallback. By default derived automatically from the channel batch size and configured description depth.
- `allowResidentialFallback` (*boolean*, optional, default: `false`): Opt in to paid residential proxy fallback only if standard direct requests encounter rate limiting.
- `maxResidentialRequests` (*integer*, optional, default: `10`, min: `0`, max: `1000`): Maximum allowance for paid residential proxy requests across the run.
- `maxRunSeconds` (*integer*, optional, default: `3600`, min: `30`, max: `14400`): Collection time limit. Completed channel records are preserved if a run reaches its deadline.
- `concurrency` (*integer*, optional, default: `5`, min: `1`, max: `10`): Number of channels processed concurrently.

### Output example

The Actor outputs structured JSON records matching the Apify dataset schema. Below is a representative record:

```json
[
  {
    "schemaVersion": "1.0",
    "recordKey": "UC_x5XG1OV2P6uZZ5FSM9Ttw",
    "id": "UC_x5XG1OV2P6uZZ5FSM9Ttw",
    "scrapedAt": "2026-09-23T10:00:00.000Z",
    "inputIndexes": [0],
    "inputValues": ["@example_creator"],
    "channelHandle": "@example_creator",
    "channelUrl": "https://www.youtube.com/channel/UC_x5XG1OV2P6uZZ5FSM9Ttw",
    "channelName": "Example Creator Studio",
    "description": "Weekly tutorials and technical explainers. Inquiries: contact@example.com",
    "avatarUrl": "https://yt3.googleusercontent.com/example/avatar.jpg",
    "country": "US",
    "joinedAt": "2018-01-15",
    "statistics": {
      "subscribers": {
        "value": 250000,
        "display": "250K subscribers",
        "precision": "rounded"
      },
      "views": {
        "value": 45000000,
        "display": "45,000,000 views",
        "precision": "exact"
      },
      "videos": {
        "value": 320,
        "display": "320 videos",
        "precision": "exact"
      }
    },
    "emails": [
      "contact@example.com"
    ],
    "socials": [
      "https://x.com/example_creator"
    ],
    "urls": [
      "https://example.com/store"
    ],
    "contacts": [
      {
        "type": "email",
        "value": "contact@example.com",
        "platform": null,
        "sources": [
          {
            "type": "channel_about",
            "url": "https://www.youtube.com/channel/UC_x5XG1OV2P6uZZ5FSM9Ttw/about",
            "label": null,
            "videoId": null,
            "method": "literal"
          }
        ]
      },
      {
        "type": "social",
        "value": "https://x.com/example_creator",
        "platform": "x",
        "sources": [
          {
            "type": "channel_link",
            "url": "https://www.youtube.com/channel/UC_x5XG1OV2P6uZZ5FSM9Ttw/about",
            "label": "Twitter",
            "videoId": null,
            "method": "structured_link"
          }
        ]
      },
      {
        "type": "website",
        "value": "https://example.com/store",
        "platform": null,
        "sources": [
          {
            "type": "channel_link",
            "url": "https://www.youtube.com/channel/UC_x5XG1OV2P6uZZ5FSM9Ttw/about",
            "label": "Store",
            "videoId": null,
            "method": "structured_link"
          }
        ]
      }
    ],
    "status": "success",
    "stopReason": "ABOUT_COMPLETE",
    "warnings": [],
    "coverage": {
      "about": "complete",
      "businessEmail": "not_inspected",
      "descriptionsRequested": 0,
      "descriptionsInspected": 0,
      "descriptionsFailed": 0,
      "videosSkipped": 0,
      "videosListed": 0,
      "order": "youtube_uploads_playlist",
      "recentScan": "not_requested",
      "historicalComplete": false,
      "stopReason": "ABOUT_COMPLETE"
    }
  }
]
```

### Pricing

The Actor uses Apify's **Pay-Per-Event (PPE)** model. It charges one dataset event for each delivered canonical channel row, including diagnostic rows such as `not_found`, `unavailable`, or `failed` results. Duplicate aliases for the same resolved channel are combined into one row, and the original input indexes are retained.

| Apify plan | Per delivered row | Per 1,000 rows |
| --- | ---: | ---: |
| Free | $0.00225 | $2.25 |
| Bronze | $0.00200 | $2.00 |
| Silver | $0.00175 | $1.75 |
| Gold | $0.00150 | $1.50 |

The Actor start event is **$0.002 per allocated memory GB**, with a minimum of one event each time an execution starts. At the default 1 GB allocation, that is $0.002 per start; resurrecting an interrupted run starts another execution and can incur another start event. Apify platform usage is billed separately and varies with the resources used by the run. Residential proxy fallback is disabled by default; if enabled, residential traffic is optional, bounded, and can add variable platform charges.

A run spending limit can stop a batch before every submitted channel has a result. Review the delivered rows and run status to see what completed. Current event rates are also shown in the **Pricing** tab above.

### Scope and limitations

- **Anonymous public YouTube only:** The Actor extracts only publicly published text and links visible without logging in. It does not access private, unlisted, or member-only information.
- **No automated "View email address" reveal:** YouTube's protected "View email address" feature may require account sign-in or an interactive challenge; this Actor does not access login-gated details. It extracts emails written directly in public About text or video descriptions.
- **No external site scraping:** The Actor records outbound URLs, profile links, and shorteners as published on YouTube; it does not crawl or visit external websites or third-party social platforms.
- **Video descriptions and sponsor mentions:** Video descriptions may include brand sponsorships, promotional partner emails, or agency contacts. The Actor extracts these as video mentions and preserves source attribution so you can review their context.
- **Absence of contacts:** An empty `emails: []` array indicates that no email was found on the inspected public YouTube surfaces; it is not a claim that the creator has no email address.
- **Batch limits and description bounds:**
  - About-only mode supports batches up to 1,000 channels per run.
  - Video description scanning is limited to a maximum of 5,000 planned descriptions per run to maintain performance and reliability. With the default setting of 20 descriptions per channel, a description-enabled run supports up to 250 distinct channels (250 × 20 = 5,000). At the maximum depth of 100 descriptions per channel, a run supports up to 50 distinct channels (50 × 100 = 5,000). Split larger lists into multiple runs.
- **No deliverability or ownership guarantees:** Contact deliverability, mailbox validity, and channel or external social account ownership are not independently verified.

### Frequently asked questions

##### How are email addresses detected?

The Actor inspects public channel About page text and recent video descriptions using pattern matching that detects standard email formats as well as common obfuscation patterns (such as `name [at] domain [dot] com` or `name(at)domain.com`).

##### Why does a channel have an empty email list?

Many creators do not write their business email directly in public text, instead relying solely on social links, external contact forms, or YouTube's login-gated business inquiry button. If an email is not in the public text surfaces, the `emails` array will be empty (`[]`).

##### How does the Actor handle channel aliases and handle changes?

If you supply multiple URLs or handles that point to the same underlying YouTube channel ID, the Actor identifies the canonical channel, merges the records into one output item, and retains all original input indices in `inputIndexes`.

##### Can I scan older videos across a creator's entire history?

No. The Actor inspects recent public uploads from the channel's uploads feed up to the configured limit (maximum 100 descriptions per channel). Historical complete channel archives are not supported.

##### How do I use this Actor programmatically?

You can trigger runs and retrieve dataset items via the Apify API using Python, JavaScript/TypeScript, or standard HTTP requests. Refer to the **API tab** on this page for code templates and webhooks setup.

### Support and feedback

If you encounter unexpected errors, missing data formats, or have feature requests, please submit an issue via the **Issues tab** on this Actor's Store page with your run ID and the affected channel identifier.

# Actor input Schema

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

Paste 1–1,000 channel URLs, @handles, or channel IDs. Aliases merge automatically. When scanning descriptions, capped at 5,000 total planned descriptions (e.g., 250x20 or 50x100); split larger batches.

## `scanRecentDescriptions` (type: `boolean`):

Also look for contacts in recent public videos, Shorts, and completed streams. This adds requests and costs. Off keeps the fastest and cheapest About-only mode.

## `maxVideosPerChannel` (type: `integer`):

Recent upload descriptions to inspect per channel (1–100). Ignored when description scanning is off. Subject to the 5,000 total planned descriptions run limit (e.g., 250x20 or 50x100).

## `allowResidentialFallback` (type: `boolean`):

Opt in to paid residential requests after direct requests are blocked. Bounded by the request allowance below. A proxy cannot unlock login-gated data.

## `maxResidentialRequests` (type: `integer`):

Run-wide allowance for paid fallback requests, including retries and redirects. Each response is limited to 6 MB decoded. No residential traffic when fallback is off.

## `maxRequests` (type: `integer`):

Optional run-wide ceiling covering direct requests, retries, redirects, and residential fallback. By default derived from batch size and selected description depth.

## `maxRunSeconds` (type: `integer`):

Collection time limit. Completed data is preserved and incomplete channels have explicit outcomes.

## `concurrency` (type: `integer`):

Keep the default for a balance of throughput and rate-limit exposure. Increasing this can increase blocking.

## Actor input object example

```json
{
  "channels": [
    "@GoogleDevelopers",
    "@TED"
  ],
  "scanRecentDescriptions": false,
  "maxVideosPerChannel": 20,
  "allowResidentialFallback": false,
  "maxResidentialRequests": 10,
  "maxRunSeconds": 3600,
  "concurrency": 5
}
```

# Actor output Schema

## `results` (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 = {
    "channels": [
        "@GoogleDevelopers",
        "@TED"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("arabiainsights/youtube-email-socials-urls-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 = { "channels": [
        "@GoogleDevelopers",
        "@TED",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("arabiainsights/youtube-email-socials-urls-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 '{
  "channels": [
    "@GoogleDevelopers",
    "@TED"
  ]
}' |
apify call arabiainsights/youtube-email-socials-urls-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,arabiainsights/youtube-email-socials-urls-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/fAtcphMpt7XWgWEzF/builds/gq7IJtBEV4gRaTk5L/openapi.json
