YouTube Channel Finder: Score, Filter, Monitor
Pricing
from $0.50 / 1,000 results
YouTube Channel Finder: Score, Filter, Monitor
Search YouTube by keyword or results URL and save one row per public channel: profile, metrics, links, description e-mails, posting activity and a 0-100 opportunity score. Filter by subscribers, country, views and recency. Includes an HTML report and a compare-with-previous-run monitor mode.
Pricing
from $0.50 / 1,000 results
Rating
0.0
(0)
Developer
Sankov Vadim
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
3 days ago
Last modified
Categories
Share
🔎 YouTube channels for any keyword, scored 0-100 and ready to shortlist
0-100 opportunity score · HTML dashboard on every run · run-to-run monitoring · public contacts · checkpointed and retried
Type a topic, get back real channels: who they are, how big, where they are based, whether they still post, and how to reach them. The Actor searches YouTube for your keywords (or for search-result URLs you already have), opens each channel's public About page, and saves one clean row per channel. It needs no YouTube login, cookies, API key or browser. It reads public pages only.
🚀 Quick start in 3 steps
- Press Start. The input is pre-filled with one keyword and a cap of 10 channels, so the first run is a cheap test.
- Open the Output tab: the dataset holds the channels and the Report link opens the HTML dashboard.
- Replace the keyword, raise the limits, add filters, and turn on activity, contacts or monitoring when you need them.
✨ Why this Actor
| You get | Instead of |
|---|---|
| A 0-100 opportunity score per channel (recent activity, audience size, profile completeness, verification) | A flat list you have to rank by hand |
| A standalone HTML report with filters, histogram, top-10 cards and CSV export | Only raw rows |
| Monitor mode: new channels, subscriber changes and missing channels since the last run | One-off snapshots |
| Links and plain-text e-mails from the description, with hidden e-mails left alone | Guessed or invented contacts |
| Filters for subscribers, videos, views, country, verified badge and posting recency, applied before charging | Paying for rows you then delete |
| Checkpoints, retries and a spending-limit stop that keeps rows already saved | Lost work on a migration or early stop |
🎯 Use cases
- Build a niche creator list from topics, products or audience interests.
- Shortlist channels for influencer outreach, ranked by score instead of gut feeling.
- Run competitor and market research on a content category.
- Find small, active channels with the subscriber range, country and posting-recency filters.
- Pull public contact details (links and any e-mail written in the description) for outreach research.
- Monitor a niche on a schedule: see which channels are new and how subscriber counts moved since the last run.
📦 What you get
Each dataset row is one unique public channel:
channel: ID, handle, title, URL, description, verified flag, family-safe / unlisted / noindex signalsmetrics: subscribers, videos, lifetime views, plus the exact text YouTube showed ("2.56M subscribers")profile: country, join date text, keywords, tags, RSS feed URL, tabs, external links, country availabilityimages: thumbnail, avatar, banner, avatar sizesdiscoverySource: which keyword or URL found it, on which surface, at what ranksourceVideo: the video that surfaced the channel (when it came from video results)score: the 0-100 opportunity score, explained belowactivity: last upload, posting frequency, average views of recent uploads (optional)contacts: external links and e-mails found in the description (optional)monitor: new or existing, and the subscriber change since the last run (optional)scrapedAt: timestamp
Anything YouTube does not publish comes back as null or an empty list. The row is still saved. Export as JSON, CSV, Excel, XML or HTML, or read it through the Apify API.
📊 The HTML report
Open the Report link on the run's Output tab. It is one self-contained page with no external requests:
- a sortable table with text, subscriber, verified and country filters
- a subscriber histogram and a top-10 country breakdown
- cards for the ten highest-scoring channels
- an Export CSV button that exports whatever your filters currently show
- a monitor section (new, changed, missing channels) when comparison is on
- a short notes box listing anything that limited the run, such as a spending cap or channels without a readable About page
It follows your browser's light or dark theme. The report lives in the run's key-value store under the key REPORT.
▶️ How to run it
- Keep the sample keyword or replace it with your own. Add as many as 500, or upload up to 20 TXT/CSV files (one term per line; for CSV, only the first column is read).
- Optionally paste public
youtube.com/resultsURLs to repeat searches you already use. - Pick a discovery mode: video results, channel-only search, or both.
- Set limits and filters.
- Turn on activity, contacts or monitoring if you want them.
- Run it, then open the dataset or the report.
Discovery modes. Channel-only search uses YouTube's channel filter and returns channels directly. Video results reads the normal search page and takes the channel behind each video, which tends to surface smaller creators the channel filter buries. Both runs the two passes. If you paste a search URL, the mode is read from the URL's own filter when it is recognised; otherwise it is treated as video results.
One row per channel. The first match that passes your filters is saved. Later matches for the same channel ID, from another keyword or surface, are ignored, and the saved row keeps its first discovery evidence.
⚙️ Input
| Field | Type | What it does |
|---|---|---|
discoveryMode | enum | both (default), videoResults or channelFilter. Required. |
searchTerms | string list | Topics, products or creator types. Up to 500 including file terms. |
searchTermsFiles | file list | Up to 20 TXT or CSV files. Terms are de-duplicated. |
searchUrls | object list | Public youtube.com/results URLs, each as { "url": "..." }. |
maxChannelsPerSearchTerm | integer | Stop a source after this many saved channels. Empty means read until YouTube runs out. |
maxTotalResults | integer | Stop the run after this many saved channels. |
minSubscribers / maxSubscribers | integer | Public subscriber range. |
keepHiddenSubscribers | boolean | Keep channels that hide their count even when a subscriber filter is set. Their size score is 0. |
minVideos | integer | Minimum public video count. |
minTotalViews | integer | Minimum lifetime views (from the About panel). |
channelCountry | string | Two-letter code, for example GB. Matches the country shown on the About panel. |
activeWithinDays | integer | Keep channels whose newest video is at most this old. Turns activity on automatically. |
verifiedOnly | boolean | Only channels with YouTube's verification badge. |
excludedChannels | object list | @handle or /channel/UC... URLs to skip. Matched on ID and handle. |
sortBy | enum | relevance (default), subscribers, score, videos, lastVideo or views. |
includeActivity | boolean | Read each channel's Videos tab for posting recency, frequency and average views. One extra request per channel. |
recentVideosCount | integer | 3 to 30 newest videos to average. Default 10. |
includeContacts | boolean | Add e-mails found in the description to the contacts block. |
compareWithPrevious | boolean | Monitor mode. Compares with the last complete run. |
monitorKey | string | Names the history. Empty means derived from your sources and filters. |
languageHint / countryHint | string | Default en / US. See the notes below. |
maxConcurrency | integer | 1 to 10 sources in parallel. Default 5. |
proxyConfiguration | proxy | Apify Proxy datacenter by default. Switch to residential if YouTube starts blocking. |
Two things worth knowing about filters. Subscriber, video, view and country filters that need the About panel drop a channel when that figure is not published. And sortBy other than relevance holds all rows until the run ends, so the dataset fills at the end instead of as it goes.
Example input
{"discoveryMode": "both","searchTerms": ["coffee roasting"],"maxChannelsPerSearchTerm": 5,"maxTotalResults": 10,"includeActivity": true,"includeContacts": true,"recentVideosCount": 5,"languageHint": "en","countryHint": "US"}
🧾 Output
Channel fields
| Field | Type | Notes |
|---|---|---|
channel.id | string | Stable channel ID. |
channel.handle, title, url, description | string or null | Public identity. |
channel.isVerified | boolean | Verification badge in search results. |
channel.isFamilySafe, isUnlisted, isNoindex | boolean or null | Taken from the channel page when present. |
metrics.subscribers | integer or null | Parsed from the displayed text. |
metrics.subscriberText | string or null | What YouTube showed, for example 150K subscribers. |
metrics.subscriberCountIsExact | boolean or null | false when YouTube shortened the number. |
metrics.videos, videoText | integer / string | Public video count. |
metrics.totalViews, totalViewText | integer / string | Lifetime views. |
profile.country, joinedText, keywords | string or null | About panel. Often empty. |
profile.tags, tabs, externalLinks, availableCountryCodes, ownerUrls, alternateUrls | arrays | Empty when not shown. |
profile.rssUrl | string | Public video feed URL. |
images.thumbnailUrl, avatarUrl, bannerUrl, avatarImages | string / array | bannerUrl is null for channels without one. |
discoverySource.sourceKind | string | keyword or search_url. |
discoverySource.value, discoverySurface, rank, sourceUrl | mixed | video_results or channel_filter; rank starts at 1. |
sourceVideo | object or null | videoId, title, url, publishedText, viewText. Null for channel-only matches. |
score | integer or null | 0-100. Null when the About page could not be read. |
activity | object or null | Present only with includeActivity. |
contacts | object or null | Present only with includeContacts. |
monitor | object or null | Present only with compareWithPrevious. |
scrapedAt | string | ISO timestamp. |
The activity block
| Field | Meaning |
|---|---|
lastVideoAt | ISO date of the newest video. Approximate, see the limits section. |
lastVideoText | The age text YouTube showed, such as 3w ago. |
videosPerMonth | Upload rate estimated from the sampled videos. |
avgViewsRecent | Average views across the sampled videos. |
recentSampled | How many videos were actually read. |
The contacts block holds externalLinks (title and URL for each link on the About panel) and emails.
The monitor block holds status (new or existing), subscribersPrev and subscribersDelta.
Example row (shortened; from a local test run of the input above, with big arrays replaced by "...")
{"channel": {"id": "UC_t7lJPh4kpIxgdRmTFi1Qg","handle": "@FlairEspresso","title": "Flair Espresso","url": "https://www.youtube.com/@FlairEspresso","description": "...","isVerified": false,"isFamilySafe": true,"isUnlisted": false,"isNoindex": false},"metrics": {"subscribers": 150000,"subscriberText": "150K subscribers","subscriberCountIsExact": false,"videos": 355,"videoText": "355 videos","totalViews": 86775028,"totalViewText": "86,775,028 views"},"profile": {"country": "United States","joinedText": "Joined Oct 19, 2016","keywords": "...","tags": "...","rssUrl": "https://www.youtube.com/feeds/videos.xml?channel_id=UC_t7lJPh4kpIxgdRmTFi1Qg","tabs": "...","externalLinks": ["http://www.flairespresso.com", "http://www.instagram.com/flairespressomaker"],"availableCountryCodes": "...","ownerUrls": "...","alternateUrls": "..."},"discoverySource": {"sourceKind": "keyword","value": "coffee roasting","discoverySurface": "video_results","rank": 4,"sourceUrl": "https://www.youtube.com/results?search_query=coffee+roasting&hl=en&gl=US"},"sourceVideo": {"videoId": "q7aZpkQgbOc","title": "A Beginner's Guide To Coffee Roasting At Home","url": "https://www.youtube.com/watch?v=q7aZpkQgbOc","publishedText": "4y ago","viewText": "290,287 views"},"score": 77,"activity": {"lastVideoAt": "2026-09-25T14:29:25+00:00","lastVideoText": "1d ago","videosPerMonth": 2.51,"avgViewsRecent": 3040,"recentSampled": 5},"contacts": {"externalLinks": [{ "title": "flairespresso.com", "url": "http://www.flairespresso.com" },{ "title": "instagram", "url": "http://www.instagram.com/flairespressomaker" }],"emails": []},"monitor": null,"scrapedAt": "2026-09-26T14:29:25+00:00"}
🎯 How the score works
The score is a quick way to sort a long list. It is not a prediction of anything. Four parts, 100 points in total:
| Part | Points | How it is earned |
|---|---|---|
| Recent activity | 35 | Newest video within 7 days: 35, within 30: 25, within 90: 15, within 365: 5, older: 0 |
| Audience size | 30 | Grows with the log of subscribers, capped at 30. Roughly 13 at 1K, 21 at 100K, 30 at 10M. Hidden count: 0 |
| Profile completeness | 20 | Description 5, country 3, join date 3, handle 2, banner 3, at least one external link 4 |
| Verification | 15 | YouTube's verification badge |
With includeActivity off, the activity part cannot be measured, so the remaining 65 points are rescaled to 100 rather than counted as zero. Scores from a run with activity and a run without are therefore not directly comparable. If a channel's About page could not be read, its score is null.
🔁 Monitor mode
Switch on compareWithPrevious and schedule the run. Each run is compared with the last complete snapshot, kept in a named store called yt-channel-search-monitor-<monitorKey>.
- Rows are tagged
neworexisting, with the subscriber difference. - A
MONITOR_DIFFJSON record lists new, changed (subscriber delta) and missing channels, and the report shows the same. - Missing means "not in this run's results". It can just as well be a result limit or a filter as a real change, so treat it as a hint. Missing channels are never written to the dataset or charged.
- The snapshot is only overwritten after a run that read every source to the end. A run that stopped early leaves the old snapshot alone, so the next comparison is not distorted.
Leave monitorKey empty and identical searches share one history automatically. Set it yourself if you want two setups to share a history or keep apart.
🛡️ Reliability
- Rows are saved as they are found (unless you choose a sort order, in which case they are flushed sorted when the run ends, including when it is stopped early).
- Failed requests are retried up to four times with growing pauses, and the proxy session is swapped on blocks, rate limits, server errors and cookie-consent pages.
- One broken source does not sink the run. It is noted in the report and the others carry on.
- A checkpoint is written every 20 channels, so a restart or server migration does not charge for the same channel twice.
- The run reserves 30 seconds before its timeout to write the dataset tail, the report and the monitor diff.
- The Actor honours your maximum spend and stops at it.
💳 Pricing
Pay per event: $0.0005 per result row saved to the dataset, which is $0.50 per 1,000 results. Every channel written to the dataset counts as one result. Channels removed by your filters and repeat matches inside a run never reach the dataset, so they are not charged. Activity, contacts, score, report and monitoring add no extra per-result charge.
Each run also has a small one-time start fee of $0.0005 (one per GB of memory the run uses, at least one).
Platform usage (compute, proxy) is billed separately according to your Apify plan.
🚧 Limits
Read these before you rely on a field.
- E-mail is often missing. The Actor reads only e-mail addresses written in plain text in the channel description. The one YouTube hides behind "View email address" needs a signed-in human and is not reachable here. Expect many channels to return an empty
emailslist. country,bannerUrlandkeywordsare frequently null. Channels simply do not fill them in.- Subscriber counts are rounded by YouTube above 1,000. Check
subscriberCountIsExact. - Last-upload dates are approximate. YouTube shows "3 weeks ago", not a date, so
lastVideoAtis a rounded estimate. - Channels with hidden subscriber counts have
subscribers: null. A subscriber filter drops them unlesskeepHiddenSubscribersis on. - This is not a video scraper. It does not return video lists, comments or transcripts. You only get the one source video that surfaced a channel.
- No analytics or revenue. Only what any visitor can see.
languageHintshould stayen. Counts and relative dates are parsed in English. Other languages make those fields unreadable.- Avoid EU country hints. They can trigger YouTube's cookie-consent page. The Actor sends consent cookies and rotates sessions, but a non-EU hint like
USis safer. - YouTube changes its pages. If the search page turns into something this Actor cannot read, it degrades and reports it rather than pretending. Fewer rows than requested is normal: YouTube caps and localises results, and your filters cut more.
❓ FAQ
Do I need a YouTube API key?
No. It reads public search and channel pages. No login, cookies or key.
Can I paste search URLs instead of keywords?
Yes. Add youtube.com/results URLs on their own or together with keywords and uploaded lists.
Can the same channel show up twice?
No. Each channel ID is saved once per run, with the evidence from its first match.
How do I find small but active channels in one country?
Set maxSubscribers, channelCountry and activeWithinDays, use both discovery mode, and sort by score. Keep in mind that channels with no published country are dropped when channelCountry is set.
Why is my score different with activity on and off?
Without activity the score is rescaled from 65 to 100 points. Compare scores only within runs that use the same setting.
Will it find every email?
No. See the limits above. It finds what is written in the description, nothing else.
Why did my run return fewer channels than the limit?
Filters, the spending cap, and YouTube's own search caps all reduce it. The report's notes box says which one applied when it can tell.
Does it return videos?
No. Only the source video that first surfaced a channel, if any.
How do I stop paying for a run that grows?
Set a maximum spend on the run, or use maxTotalResults. The Actor stops at either.
📝 Changelog
v0.1
- Keyword and search-URL discovery through video results, the channel filter, or both.
- Public profile, metrics and first-match evidence per channel.
- Filters: subscribers, videos, lifetime views, country, verified, posting recency, exclusions, hidden-count handling.
- 0-100 opportunity score, activity metrics and contacts.
- Standalone HTML report and run-to-run monitoring.
- Checkpoints, retries with session rotation, and saved-row protection on early stops.
v0.2
- Input form reorganised into Search, Filters, Enrichment, Monitoring and Performance sections, with clearer titles and descriptions.
- Pre-filled test run: one keyword and a cap of 10 channels, so a first run costs a few cents.
- Billing fix: rows are now charged through the standard per-result event ($0.0005 per result, plus the $0.0005 start fee). Prices did not change. The spending-limit stop uses the same event.
🆘 Support
Something off, or a field you need? Open an issue from the Actor's Issues tab with a run link and a short description.
🔗 Related
The publisher's Store profile lists other YouTube and lead-generation Actors, useful when you already have a channel list and want more than a search can give.