YouTube Channel Videos & Views Scraper - No Blocked Paths
Pricing
from $0.73 / 1,000 video returneds
YouTube Channel Videos & Views Scraper - No Blocked Paths
Turn monitoring on and every later run returns only the videos it has not returned before, so you are never charged twice. Every video on a channel with its view count, length and publish date, read only through paths YouTube's robots.txt allows, and every row names the channel that published it.
Pricing
from $0.73 / 1,000 video returneds
Rating
0.0
(0)
Developer
NeverEmpty
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
14 hours ago
Last modified
Categories
Share
YouTube Channel Videos & Views Scraper — No Blocked Paths
Turn monitoring on and every later run returns only the videos it has not returned before, so you are never charged for the same video twice.
Give it a handle. Get that channel's videos with view count, length and publish time — read only through paths YouTube's robots.txt allows.
Unofficial. Not affiliated with or endorsed by YouTube or Google.
🔴 What makes this one different
YouTube's robots.txt disallows /feeds/videos.xml and /youtubei/ — the channel RSS feed and the internal player API. Those two are what most YouTube scrapers are built on.
This Actor uses neither. It reads /@handle/videos and /watch?v=, which are not disallowed, and the URL builder physically refuses to construct a disallowed address — a test fails if it ever does.
The allowed path is also the better one: the videos tab returned 30 videos when measured on 2026-09-06; the RSS feed returns 15.
🔴 Every row tells you whose data it is
A YouTube channel page is full of recommendations from other channels. Taking the first "channelId" on the page gives you someone else's channel — a mistake that is invisible in the output, because the numbers still look like numbers.
So this Actor:
- reads the channel id only from the page's own
<link rel="canonical">, - reads video ids only from inside the videos grid, not the whole page,
- and then opens each video and records the channel that video itself says published it, next to the one you asked for.
That last one is the column ownerMatchesRequested. If it is ever false, the row is telling you the data does not belong to the channel you named. When the owner cannot be read it is null, not false — unknown is not the same as wrong.
What you get in every row
| Field | What it is |
|---|---|
channelInput, channelId, channelTitle | What you asked for, and what it resolved to |
videoId, videoUrl, title | The video |
viewCount, lengthSeconds | Views and runtime |
publishedAt, publishedAtRaw | ISO instant and the site's own string (2026-09-05T14:18:49-07:00), so you can check the conversion |
ownerChannelId, ownerChannelName, ownerMatchesRequested | Who actually published it, and whether that matches |
playabilityStatus, playabilityReason | Where the page reports one |
videoKey | What monitoring compares |
Pricing: per row, plus a monthly fee only if you monitor
- Per video returned — you pay for the rows you actually receive.
- $5 once per calendar month (UTC), charged on the first monitoring run of that month.
The monthly fee is what pays for watching on the days when nothing was posted. Those runs return no rows and cost you nothing else, so a channel that goes quiet for three weeks does not quietly stop being watched to save money.
Runs with monitoring turned off never trigger it — one-off pulls are per-row only. If a charge cannot be made (for example the run hits its own maximum total charge), nothing is recorded and it is attempted again on the next run, so it is never taken twice.
Monitoring: two meanings of "new"
- New videos only — a video is returned once, ever. Already-returned videos are skipped without opening their page, so a scheduled run on a quiet channel costs almost nothing.
- Any change — a video comes back when its view count or title changes, which is how you build a view-growth history.
Configure the run
{ "channels": ["@mkbhd"], "maxVideosPerChannel": 30, "maxVideos": 100 }
Follow several channels for new uploads:
{ "channels": ["@mkbhd", "@veritasium", "UCLA_DiR1FfKNvjuUpBHmylQ"], "monitoringMode": true, "monitorMode": "new-videos" }
Long-form only, from this year, tracking view growth:
{ "channels": ["@mkbhd"], "minLengthSeconds": 62, "publishedAfter": "2026-01-01", "monitoringMode": true, "monitorMode": "any-change" }
What this Actor refuses to guess
A mistyped handle comes back as no-such-channel, not a guess — YouTube's search (/results) is disallowed by robots.txt, so this Actor does not have a way to "find something close" and does not pretend to.
A bot check is reported as blocked, never as an empty result. Channels with no uploads, filters that matched nothing and unreadable pages each come back as their own row with the reason, and none of them are charged.
Input reference
Every field is optional; the defaults read the latest videos from one channel.
| Field | Type | Default | What it does |
|---|---|---|---|
channels | array | ["@mkbhd"] | Handles (@mkbhd), channel ids (UC...) or channel URLs. A mistyped handle is reported as 'no such channel' rather than guessed, because YouTube's robots.txt disallows… |
maxVideosPerChannel | integer | 30 | How far down the channel's videos tab to go. The tab holds about 30 videos (measured 2026-09-06); the RSS feed other scrapers use holds 15, and is disallowed by… |
maxVideos | integer | 100 | How many rows to return in total. You are charged for the rows you actually receive. Each video costs one extra page request for its view count. |
monitoringMode | boolean | false | Off = return the videos on the tab. On = remember what was returned and, on later runs, return only what is new. With 'new videos only' below, already-returned videos… |
monitorMode | string | new-videos | New videos only = a video is returned once, ever. Any change = a video is returned again when its view count or title changes, which is how you build a view-growth… |
resetMonitoringState | boolean | false | Clear the remembered videos before this run, so everything counts as new again. |
minViews | integer | 0 | Keep a video only if it has at least this many views. 0 = no limit. Videos whose view count could not be read are kept, because unknown is not the same as low. |
maxViews | integer | 0 | Keep a video only if it has at most this many views. 0 = no limit. |
minLengthSeconds | integer | 0 | Keep a video only if it runs at least this long. 0 = no limit. Use 62 to skip Shorts. |
maxLengthSeconds | integer | 0 | Keep a video only if it runs at most this long. 0 = no limit. Use 61 to keep only Shorts. |
publishedAfter | string | (empty) | Keep only videos published on or after this date. Videos with an unreadable publish time are kept. |
onlyOwnedByChannel | boolean | false | Every row already reports whether the video's own page names the channel you asked for. Turn this on to drop the ones that do not match. Rows where the owner could… |
keywords | array | [] | Keep a video only if one (Any) or all (All) of these appear in the title or channel name. |
keywordMatch | string | any | Any = at least one keyword. All = every keyword. |
excludeKeywords | array | [] | Drop a video if any of these appear in the same fields. |
useProxy | boolean | false | Off by default. If YouTube answers with a bot check, the Actor switches to a proxy session on its own and tries again; turning this on from the start avoids that… |
Pricing
Pay per result: you are charged for the video rows you actually receive, plus the $5 monthly access fee described above only when monitoring mode is on. Reading pages is free; explanation rows are never charged.
Every number in this README is checked
The fixtures in test/fixtures/ are the real pages this Actor was built from (2026-09-06). The test suite re-counts every figure quoted above — 30, 15, 3 — and fails if a disallowed URL can ever be built.