# YouTube Channel Search Scraper \[$0.12/1K] (`memo23/youtube-channel-search-scraper`) Actor

Find YouTube channels from keywords or search URLs via video results, channel search, or both — with subscriber filters and first-match evidence.

- **URL**: https://apify.com/memo23/youtube-channel-search-scraper.md
- **Developed by:** [Muhamed Didovic](https://apify.com/memo23) (community)
- **Categories:** Social media, Lead generation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.12 / 1,000 channels

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?

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

## YouTube Channel Search Scraper

Discover YouTube channels from keywords or reusable `/results` URLs — from **video results**, **channel-only search**, or both — and get a full profile for each: exact subscriber, video and view counts, country, join date, links, and the first-match evidence (including the source video when a video result found the channel).

Feed it search terms or YouTube search URLs (they can run together), add subscriber/video/verified filters, and get a clean row per channel. Ideal for creator discovery, influencer research, and lead generation.

Filters run **before** billing — channels you filter out never cost you a thing.

![How it works](https://raw.githubusercontent.com/muhamed-didovic/muhamed-didovic.github.io/main/assets/how-it-works-youtube-channel-search.png)

### ✨ Why use this scraper?

- **Video-results discovery.** Find channels that uploaded a matching video, not only channels whose name matches the keyword. Channel-only search and both modes are available too.
- **Exact metrics per channel.** Real subscriber, video and view counts pulled from each channel's About page — not just the rounded "1.2M" from search.
- **Built-in audience filters.** Keep only channels within a subscriber range, above a video-count floor, or verified-only. Filtering is free.
- **Contact-ready output.** External links (Instagram, TikTok, website, email links) and RSS feed for every channel — straight into your outreach pipeline.
- **Bulk input.** Many search terms per run, or a file/Google Sheet of terms, or full YouTube search URLs.
- **Fast and predictable.** JSON or CSV, one row per channel, billed per result.

### 📋 Overview

This Actor turns YouTube keyword searches into a structured list of **channels**. For each keyword (or search URL) it collects the matching channels, then enriches each one from its public About page with exact counts, location, join date, keywords/tags, RSS feed, external links, avatar and banner.

It's built for marketers, agencies, and researchers who need to **find and qualify creators at scale** — by niche, size, and location — rather than scraping a single known channel.

The dataset shape is one row per channel. Non-matching channels (failed filters) are dropped before they are saved, so you only pay for channels you keep.

### 📥 Supported inputs

| Input type | Example | Notes |
|---|---|---|
| Search term | `coffee` | Any keyword or phrase. Best for discovery. |
| Multiple search terms | `coffee`, `home workout`, `k-drama` | One run, many niches. |
| Terms from a file | `https://.../terms.txt` or a public Google Sheet | One term per line. |
| YouTube search URL | `https://www.youtube.com/results?search_query=coffee` | Combined with terms. Discovery mode (video / channel / both) is applied to each URL. |

**Not supported:** full video lists, comments, transcripts, playlist contents, private/members-only channels, or anything behind a YouTube login. This Actor returns **channels**. When a video result is the first match, it also saves that video as `sourceVideo` evidence.

### 🎯 Use cases

| Audience | What they get |
|---|---|
| Influencer marketers | A shortlist of creators in a niche, filtered by subscriber size and country |
| Agencies | Lead lists of channels with external links and RSS for outreach |
| Brand / sponsorship teams | Verified channels above a subscriber floor in a category |
| Market researchers | The competitive creator landscape for any topic |
| SEO / content teams | Who owns a keyword space on YouTube, ranked by size |
| Data teams | Structured channel metrics feeding dashboards or CRMs |

### 🔄 How it works

1. **Search** — each keyword or search URL is sent to YouTube on the surfaces you chose (video results, channel-only, or both).
2. **Paginate** — the Actor walks result pages until your per-term / total cap is met, or until the source is exhausted if a cap is empty.
3. **Dedup** — the first eligible match per channel is kept, with rank, surface, and optional source-video evidence.
4. **Enrich** — each channel's About page is fetched for exact subscriber, video and view counts, country, join date, keywords, tabs, links, avatar and banner.
5. **Filter** — subscriber range, minimum videos, verified-only and exclusions are applied. Dropped channels are never billed.
6. **Save** — one clean row per surviving channel, in JSON or CSV.

### ⚙️ Input configuration

| Field | Type | Description |
|---|---|---|
| `discoveryMode` | string | `both` (default), `videoResults`, or `channelFilter`. |
| `searchTerms` | array | Keywords to search for (one per line). Combined with search URLs. |
| `searchTermsFiles` | array | URLs of text/CSV files or a public Google Sheet listing one term per line. |
| `searchUrls` | array | Full YouTube `/results` URLs. Combined with search terms. |
| `maxChannelsPerSearchTerm` | integer | Max channels returned per term / URL. Empty = exhaust that source. |
| `maxTotalResults` | integer | Global cap on channels across the run. Empty = exhaust every source. |
| `minSubscribers` | integer | Keep only channels with at least this many subscribers (0 = off). |
| `maxSubscribers` | integer | Keep only channels with at most this many subscribers (0 = off). |
| `minVideos` | integer | Keep only channels with at least this many videos (0 = off). |
| `verifiedOnly` | boolean | Keep only channels with the Verified badge. |
| `excludedChannels` | array | Handles (`@name`), channel IDs (`UC…`) or URLs to drop. |
| `languageHint` | string | YouTube language code `hl` (e.g. `en`). |
| `countryHint` | string | YouTube country code `gl` (e.g. `US`). |
| `maxConcurrency` | integer | Max parallel requests (default 10). |
| `proxy` | object | Proxy configuration. Defaults to Apify Residential (US). |

**Example — discover mid-size verified coffee channels:**

```json
{
  "discoveryMode": "both",
  "searchTerms": ["coffee roasting", "espresso"],
  "maxChannelsPerSearchTerm": 50,
  "minSubscribers": 100000,
  "verifiedOnly": true,
  "countryHint": "US"
}
```

**Example — from search URLs, capped:**

```json
{
  "discoveryMode": "videoResults",
  "searchUrls": ["https://www.youtube.com/results?search_query=home%20workout"],
  "maxTotalResults": 30
}
```

### 📊 Output overview

Each row is one channel: identity (handle, title, URL, channel ID), audience metrics (subscribers, videos, total views — as both parsed numbers and their original text), profile data (description, country, join date, keywords, tabs, family-safe flag, verified badge), assets (avatar, banner, RSS feed, titled external links), a `discoverySource` object (keyword or URL, surface, rank, results URL), and `sourceVideo` when a video result was the first match.

### 📦 Output sample

Real row (trimmed), from the search term `coffee`:

```json
{
  "type": "channel",
  "channelId": "UCpDzpaUTbIkdjkCZ9pmfMrA",
  "handle": "@CoffiChannel",
  "title": "Coffi Channel",
  "url": "https://www.youtube.com/@CoffiChannel",
  "description": "Игровой канал ...",
  "isVerified": true,
  "isFamilySafe": true,
  "subscribers": 8190000,
  "subscriberText": "8.19M subscribers",
  "videos": 8304,
  "videoText": "8,304 videos",
  "totalViews": 4259490490,
  "totalViewsText": "4,259,490,490 views",
  "country": "Russia",
  "joinedText": "Joined Jun 23, 2014",
  "joinedDate": "2014-06-23",
  "keywords": ["gta", "gta 5", "cs go", "open case"],
  "rssUrl": "https://www.youtube.com/feeds/videos.xml?channel_id=UCpDzpaUTbIkdjkCZ9pmfMrA",
  "externalLinks": [
    { "title": "Telegram", "url": "https://t.me/coffiYT" },
    { "title": "VK", "url": "https://vk.com/ocoffi" }
  ],
  "avatarUrl": "https://yt3.googleusercontent.com/ytc/…=s900-c-k-c0x00ffffff-no-rj",
  "bannerUrl": "https://yt3.googleusercontent.com/…=w2560-…-no-nd-rj",
  "discoverySource": {
    "sourceKind": "keyword",
    "value": "coffee",
    "discoverySurface": "video_results",
    "rank": 1,
    "sourceUrl": "https://www.youtube.com/results?search_query=coffee"
  },
  "sourceVideo": {
    "videoId": "abc12345678",
    "title": "Morning brew",
    "url": "https://www.youtube.com/watch?v=abc12345678",
    "publishedText": "2 weeks ago",
    "viewText": "12,345 views"
  },
  "scrapedAt": "2026-09-06T21:18:23.530Z"
}
```

### 🗂 Key output fields

| Group | Fields |
|---|---|
| Identity | `channelId`, `handle`, `title`, `url` |
| Audience | `subscribers`, `subscriberText`, `subscriberCountIsExact`, `videos`, `videoText`, `totalViews`, `totalViewsText` |
| Profile | `description`, `country`, `joinedText`, `joinedDate`, `keywords`, `tags`, `tabs`, `isVerified`, `isFamilySafe`, `isUnlisted`, `isNoindex` |
| Assets & contact | `avatarUrl`, `bannerUrl`, `thumbnailUrl`, `avatarImages`, `rssUrl`, `externalLinks`, `ownerUrls`, `availableCountryCodes` |
| Provenance | `discoverySource`, `sourceVideo`, `scrapedAt` |

### ❓ FAQ

**Does this scrape videos or comments?**
It returns channels. When the first match comes from a video result, that video is stored as `sourceVideo` evidence. It does not export a channel's full video list, comments, or transcripts.

**Are subscriber counts exact?**
YouTube publishes subscriber counts rounded (e.g. "8.19M"); `subscribers` is that value parsed to a number, and `subscriberText` keeps the original. Video counts and total views are exact.

**Why did I get fewer channels than my cap?**
Your filters may have dropped many candidates, or the keyword simply has few channels. The run's `RUN_SUMMARY` (in the key-value store) breaks down exactly how many were dropped by each filter.

**Do filtered-out channels cost me anything?**
No. Subscriber, video, verified and exclusion filters run before a row is saved, so you're only billed for channels you keep.

**Can I search in another language/country?**
Yes — set `languageHint` (`hl`) and `countryHint` (`gl`).

**What happens when I leave a result limit empty?**
The Actor keeps searching until that source (or the whole run) is exhausted.

**Can I paste terms and search URLs together?**
Yes. Both lists run in the same job. The first eligible match per channel is kept.

### 💬 Support

Found an issue or need a field that isn't here? Open an issue on the Actor's **Issues** tab and it will be looked at.

### 🛠 Additional services

Need a tailored export, a scheduled feed into your CRM, or channel enrichment (emails, socials) at scale? Custom work is available — reach out through the Issues tab.

### 🔎 Explore more scrapers

Search the Apify Store for the sibling YouTube Actors covering search results & video metrics, Shorts, and downloads.

### 🤖 For AI Agents & LLM Apps

- **Purpose:** discover YouTube **channels** by keyword/search URL and return per-channel metrics + links.
- **Minimal input (runs as-is):**
  ```json
  { "searchTerms": ["coffee"], "maxTotalResults": 20 }
  ```
- **Output fields:** `channelId`, `handle`, `title`, `url`, `description`, `isVerified`, `isFamilySafe`, `subscribers`, `subscriberText`, `subscriberCountIsExact`, `videos`, `videoText`, `totalViews`, `totalViewsText`, `country`, `joinedText`, `joinedDate`, `keywords[]`, `rssUrl`, `externalLinks[{title,url}]`, `avatarUrl`, `bannerUrl`, `discoverySource{sourceKind,value,discoverySurface,rank,sourceUrl}`, `sourceVideo|{videoId,title,url,publishedText,viewText}|null`, `scrapedAt`.
- **Behaviors:** one row per channel; `minSubscribers`/`maxSubscribers`/`minVideos`/`verifiedOnly`/`excludedChannels` filter before billing; `subscribers` is parsed from a rounded value while `videos`/`totalViews` are exact.
- **Billing:** pay per channel saved to the dataset (filtered channels are not billed).

***

### ⚠️ Disclaimer

This Actor is an independent tool and is not affiliated with, endorsed by, or sponsored by YouTube, Google LLC, or any of their subsidiaries or affiliates. All trademarks mentioned are the property of their respective owners.

The scraper accesses only publicly available YouTube channel pages — no authenticated endpoints, member-only content, or anything behind a YouTube login. Users are responsible for ensuring their use complies with YouTube's Terms of Service, applicable data-protection law (GDPR, CCPA, etc.), and any contractual obligations of their own organisation.

***

### SEO Keywords

youtube channel search scraper, scrape youtube channels, youtube channel finder, youtube channel discovery, youtube creator search, youtube influencer scraper, youtube channel data api, find youtube channels by keyword, youtube subscriber count scraper, youtube channel list scraper, creator discovery tool, influencer research youtube, youtube lead generation, youtube channel metrics, youtube niche research, youtube channel export, bulk youtube channel scraper, youtube channel search api, verified youtube channels scraper, youtube channel search scraper alternative

# Actor input Schema

## `discoveryMode` (type: `string`):

Video results find channels that uploaded a matching video (best for influencer discovery). Channel-only search finds channels whose name matches. Both runs the two surfaces and keeps the first eligible match per channel.

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

Keywords to search for, one per line (e.g. 'coffee roasting', 'home workout'). Can be combined with search URLs in the same run.

## `searchTermsFiles` (type: `array`):

URLs of text/CSV files (or a public Google Sheet) that list one search term per line. Loaded and merged with Search terms.

## `searchUrls` (type: `array`):

Public YouTube /results URLs to run again. Combined with search terms. The discovery mode (video / channel / both) is applied to each URL.

## `maxChannelsPerSearchTerm` (type: `integer`):

Stop after this many saved channels for each search term or search URL. Leave empty to keep going until that source is exhausted. Filtered-out channels do not count.

## `maxTotalResults` (type: `integer`):

Stop after this many saved channels in the whole run. Leave empty to keep going until every source is exhausted. Filtered-out channels do not count.

## `minSubscribers` (type: `integer`):

Keep only channels with at least this many subscribers. 0 = no minimum.

## `maxSubscribers` (type: `integer`):

Keep only channels with at most this many subscribers (useful for finding smaller/micro creators). 0 = no maximum.

## `minVideos` (type: `integer`):

Keep only channels that have uploaded at least this many videos. 0 = no minimum.

## `verifiedOnly` (type: `boolean`):

Keep only channels that carry YouTube's 'Verified' badge.

## `excludedChannels` (type: `array`):

Channel handles (e.g. @mkbhd), channel IDs (UC...) or channel URLs to drop from results.

## `languageHint` (type: `string`):

YouTube interface/content language code, e.g. 'en', 'es', 'fr'. Affects joined-date wording and result ranking.

## `countryHint` (type: `string`):

Two-letter country code YouTube should search from, e.g. 'US', 'GB', 'DE'.

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

Maximum number of requests processed in parallel.

## `proxy` (type: `object`):

Proxy used for all requests. Residential US is recommended for YouTube. Defaults to Apify Residential (US).

## Actor input object example

```json
{
  "discoveryMode": "both",
  "searchTerms": [
    "coffee roasting"
  ],
  "searchUrls": [
    "https://www.youtube.com/results?search_query=coffee"
  ],
  "maxChannelsPerSearchTerm": 10,
  "maxTotalResults": 10,
  "minSubscribers": 0,
  "maxSubscribers": 0,
  "minVideos": 0,
  "verifiedOnly": false,
  "languageHint": "en",
  "countryHint": "US",
  "maxConcurrency": 10,
  "proxy": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "US"
  }
}
```

# Actor output Schema

## `results` (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 = {
    "discoveryMode": "both",
    "searchTerms": [
        "coffee roasting"
    ],
    "searchUrls": [
        "https://www.youtube.com/results?search_query=coffee"
    ],
    "maxChannelsPerSearchTerm": 10,
    "maxTotalResults": 10,
    "proxy": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ],
        "apifyProxyCountry": "US"
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("memo23/youtube-channel-search-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 = {
    "discoveryMode": "both",
    "searchTerms": ["coffee roasting"],
    "searchUrls": ["https://www.youtube.com/results?search_query=coffee"],
    "maxChannelsPerSearchTerm": 10,
    "maxTotalResults": 10,
    "proxy": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
        "apifyProxyCountry": "US",
    },
}

# Run the Actor and wait for it to finish
run = client.actor("memo23/youtube-channel-search-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 '{
  "discoveryMode": "both",
  "searchTerms": [
    "coffee roasting"
  ],
  "searchUrls": [
    "https://www.youtube.com/results?search_query=coffee"
  ],
  "maxChannelsPerSearchTerm": 10,
  "maxTotalResults": 10,
  "proxy": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "US"
  }
}' |
apify call memo23/youtube-channel-search-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,memo23/youtube-channel-search-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/aiHBNIoQwxpxTEtzP/builds/sCL33E3o8cPxcgpoB/openapi.json
