YouTube Channel Scraper – Videos, Views & Likes
Pricing
from $0.50 / 1,000 videos
YouTube Channel Scraper – Videos, Views & Likes
Scrape the latest videos from any public YouTube channel — title, link, exact view count, likes, publish date, duration, description and thumbnail — one row per video. No login, no cookies, no API key and no browser: a channel listing costs one request. Unofficial.
Pricing
from $0.50 / 1,000 videos
Rating
0.0
(0)
Developer
Simple Actor
Maintained by CommunityActor stats
0
Bookmarked
5
Total users
4
Monthly active users
4 days ago
Last modified
Categories
Share
Scrape the latest videos from any public YouTube channel — title, link, exact view count, likes, publish date, duration, description, category and thumbnail — one row per video. Built for channel monitoring, competitor and content research, influencer vetting and video dataset building.
No login, no cookies, no API key and no browser. Everything on a channel listing is in a JSON object inside the page YouTube serves to a logged-out reader, so a whole channel costs one request.
Unofficial. Not affiliated with, endorsed by, or sponsored by YouTube or Google.
Features
- Latest videos per channel — up to 30, newest first, read from the page YouTube serves a logged-out reader.
- Exact view counts and publish dates — not YouTube's rounded "53K views" and "3 days ago", but 53,674 and the real date.
- Like counts and descriptions — which appear nowhere on the channel listing — with every link in the description written out in full.
- Every address form works —
@handle,/channel/UC…, and the legacy/c/and/user/forms, so a list saved a decade ago still resolves. - Bare handles and channel IDs accepted — paste a spreadsheet column straight in.
- Channel context on every row — name, id, handle, subscriber count and the channel's total video count, so you can tell 30-of-30 from 30-of-6,100.
- Rounded figures are always labelled —
viewCountIsApproximateandpublishedAtIsApproximatemean you are never silently misled. - A cheap freshness mode — turn details off and a whole channel is one request.
- Incremental polling —
onlyVideosNewerThantakes7 days,3 monthsor an ISO date, and refuses rather than returning a misleading short list. - No browser, 256 MB — fast and light.
- Runs stay green. A nonexistent channel or a pasted video URL is a row.
Input
{ "handles": ["NASA"], "maxVideos": 30 }
All four of YouTube's address forms work, so a list saved at any point in the last decade still resolves:
{"startUrls": [{ "url": "https://www.youtube.com/@NASA" },{ "url": "https://www.youtube.com/channel/UCLA_DiR1FfKNvjuUpBHmylQ" },{ "url": "https://www.youtube.com/user/NASAtelevision" }]}
| Field | Type | Default | What it does |
|---|---|---|---|
startUrls / handles | array | — | The channels. handles also takes bare handles (NASA) and channel IDs (UCLA_…). |
maxVideos | integer | 30 | Newest first. 30 is the ceiling — see What it cannot do. |
includeVideoDetails | boolean | true | Exact views, likes, description and publish date. One request per video, and what the price turns on — see What it costs. |
onlyVideosNewerThan | string | — | 7 days, 3 months, or an ISO date. |
proxy | object | Apify datacenter | What it is built and measured on. Residential is available but rarely worth it — see the FAQ. |
Output
{"type": "video","videoId": "FkgVB19I6xw","url": "https://www.youtube.com/watch?v=FkgVB19I6xw","title": "NASA's Roman Space Telescope: A New Perspective on the Cosmos","viewCount": 53674,"viewCountIsApproximate": false,"likeCount": 1839,"publishedAt": "2026-08-24T21:00:22.000Z","publishedText": "3 days ago","publishedAtIsApproximate": false,"durationSeconds": 46,"category": "Science & Technology","thumbnailUrl": "https://i.ytimg.com/vi/FkgVB19I6xw/hq720.jpg","channelName": "NASA","channelId": "UCLA_DiR1FfKNvjuUpBHmylQ","channelHandle": "@NASA","subscriberCount": 15100000,"channelVideoCount": 6100,"scrapedAt": "2026-08-28T15:40:29.000Z"}
Store channelId, not the handle. A channel's owner can change its handle;
the UC… id never changes.
Exact figures, and when you get them
YouTube rounds everything it displays. A channel listing says "53K views" and
"3 days ago" — 53,674 and 53,001 both print as 53K. The exact numbers live only
on each video's own page, which is what includeVideoDetails fetches, along
with the like count and description that exist nowhere else.
A video's page carries those figures twice: once in the data the page itself is drawn from, and once in YouTube's player data. The Actor reads whichever arrives. The page's own data comes with nearly every read; the player data is withheld from most datacenter requests, and it is the only place the publish time, the category and the keywords appear.
So every row says which it got:
viewCountIsApproximate | likeCount | publishedAt | publishedAtIsApproximate | category | |
|---|---|---|---|---|---|
| read with player data | false | a number | the exact instant | false | set |
| read without it | false | a number | the publish day, at 00:00 UTC | true | null |
| page could not be read | true | null | from "3 days ago" | true | null |
The publish day is the calendar day YouTube displays, which is the day in Pacific time. A video less than a day old keeps the listing's "2 hours ago" instead, which places it more precisely than a bare day would.
Only the last row is not charged the detail fee. You are never misled: a rounded figure is always flagged as one.
A video with no public view count at all — a members-only upload, say —
comes back with viewCount: null and viewCountIsApproximate: null. A null
flag means there is no figure to describe, not a rounded one waiting to be
improved.
How to use
From Apify Console
- Open the Actor and click Try for free / Start.
- Paste channel addresses into Channels, or a column of bare handles and channel IDs into Channels (plain list) — both are read together. Give a channel, not a video.
- Leave Exact views, likes and dates on for real figures, likes and descriptions. Turn it off for a cheap freshness sweep across many channels — a channel then costs one request.
- To poll for what is new, set Only videos newer than to a window shorter than the gap between your runs.
- Click Start, then open the Dataset tab and export as JSON, CSV or Excel.
Store channelId, not the handle — the handle can change, the UC… id
cannot.
From the API
curl -s "https://api.apify.com/v2/acts/simple.actor~youtube-channel-videos/run-sync-get-dataset-items?token=$APIFY_TOKEN" \-H 'Content-Type: application/json' \-d '{"handles": ["NASA"], "maxVideos": 30}'
A cheap daily freshness check across many channels, with the JavaScript client:
import { ApifyClient } from 'apify-client';const client = new ApifyClient({ token: process.env.APIFY_TOKEN });const run = await client.actor('simple.actor/youtube-channel-videos').call({handles: ['NASA', 'veritasium', 'UCLA_DiR1FfKNvjuUpBHmylQ'],includeVideoDetails: false, // one request per channel, rounded figuresonlyVideosNewerThan: '2 days',});const { items } = await client.dataset(run.defaultDatasetId).listItems();for (const row of items) {if (row.error) { console.warn(row.error, row.errorDescription); continue; }console.log(row.channelName, row.title, row.publishedText);}
Use cases
- Monitor channels for new uploads — poll a list on a schedule with
onlyVideosNewerThanandincludeVideoDetails: falsefor a cheap check, then read the details of anything new. - Competitor and content research — titles, durations, descriptions and exact view counts across rival channels.
- Influencer vetting — subscriber count, total video count and real engagement on recent uploads, rather than YouTube's rounded display figures.
- Video performance benchmarking — exact views and likes per video, loaded straight into a spreadsheet or warehouse.
- Building a video dataset — metadata for a channel's latest 30 uploads with
stable
videoIdandchannelIdkeys. - Media and brand monitoring — watch newsroom, agency and brand channels for what they published today.
Usage notes
What it costs
| each video returned | $0.0005 |
| each video read for exact figures | $0.0010 on top |
So $1.50 per 1,000 videos with exact views, likes, descriptions and publish dates, and $0.50 per 1,000 for titles, links, durations, thumbnails and rounded figures.
That split is the real cost, passed on: a channel listing is one request for up
to thirty videos, while the exact figures are a request each. If you are
watching a lot of channels to see what is new, turn includeVideoDetails off
and a channel costs one request.
Nothing else is charged. A channel that could not be read, a video with no detail page available, a run whose every input was unusable — none of them bill.
What it cannot do
Thirty videos per channel. That is what a channel page renders to a
logged-out reader; going further needs YouTube's internal browse API with a
signed continuation token, which is a far more fragile surface than reading a
page. Every row carries channelVideoCount, so you can always tell whether you
are seeing all of a channel's videos or the latest thirty of many.
If you ask for a window reaching further back than those thirty
(onlyVideosNewerThan: "10 years"), the channel comes back as an error row
(window_too_wide) rather than a short list that would look like a complete
answer for that window.
Failures
The run always succeeds. A channel that does not exist, a string that could never be a handle, a video URL pasted where a channel belongs — each is a row, and the run's status message counts them. Only a bug in this Actor fails a run.
A run finishes inside its timeout. It stops reading shortly before the
timeout you set and delivers what it holds. Videos it had no time to read
exactly keep the listing's figures, flagged and not charged; channels it never
reached each get a timed_out row.
Act on the presence of an
errorfield, never on the run status. A channel read fine that has posted nothing produces no rows; a channel that could not be read produces exactly one row, carryingerrorand novideoId.
error | what happened |
|---|---|
not_found | no such channel |
bad_input | the text given could never be a channel, or is a video/playlist URL |
window_too_wide | the window reaches further back than one page of videos shows |
read_failed | YouTube could not be reached, or served a page in a language this Actor could not read |
timed_out | the run reached its timeout before this channel was read — raise the timeout, or give fewer channels per run |
parse_failed | the Actor hit an error it did not expect on this channel; the other channels in the run are unaffected |
FAQ
Is scraping YouTube legal? This Actor reads only the data YouTube already serves to a logged-out visitor in the page itself — it does not log in, use cookies, or reach private or members-only content. YouTube's Terms of Service restrict automated collection, so check the platform's ToS and your own obligations before using it.
Do I need a YouTube Data API key or a Google Cloud project? No. There is no key, no OAuth and no quota of your own to manage.
Can I get more than 30 videos per channel?
No. Thirty is what a channel page renders to a logged-out reader; going further
needs YouTube's internal browse API with a signed continuation token, which is a
far more fragile surface than reading a page. Every row carries
channelVideoCount, so you can always tell whether you are seeing all of a
channel's videos or the latest thirty of many.
Does it support pagination?
Not beyond that first page, for the reason above. To follow a channel over time,
run it on a schedule with onlyVideosNewerThan.
Why is viewCount rounded on some rows?
Because the exact figure lives only on each video's own page, and that page
could not be read — YouTube or the proxy did not answer in the time allowed.
Those rows keep the listing's rounded figures and say so via
viewCountIsApproximate: true, with likeCount: null, and are not charged the
detail fee. You are never silently given a wrong number.
Why is publishedAt a date at midnight on some rows, and category null?
The publish time of day, the category and the keywords come only with YouTube's
player data, which it withholds from most datacenter requests. Those rows carry
the publish day — exact to the day, flagged publishedAtIsApproximate: true
because it is not the instant — with the exact views, likes and description
beside it.
What does viewCountIsApproximate: null mean?
That there is no figure to describe at all — a members-only upload, for example,
publishes no view count. A null flag is not a rounded number waiting to be
improved.
Should I turn on residential proxy? Only if you need the publish time of day, the category or the keywords on more rows. It does not improve the view or like counts, which are exact on datacenter, and it costs roughly ten times as much per video.
Should I store the handle or the channel ID?
The channelId. A channel's owner can change its handle at any time; the UC…
id never changes.
Why did my run succeed when a channel was not read?
By design. A channel that does not exist, a string that could never be a handle,
or a video URL pasted where a channel belongs are each answers about that input,
not faults — so each is a row and the run stays green. Act on the presence of an
error field, never on the run status.