YouTube Scraper: Search, Channels, Playlists & Videos avatar

YouTube Scraper: Search, Channels, Playlists & Videos

Pricing

from $2.00 / 1,000 video scrapeds

Go to Apify Store
YouTube Scraper: Search, Channels, Playlists & Videos

YouTube Scraper: Search, Channels, Playlists & Videos

Scrape YouTube search results, channels, playlists and individual videos in one run. Title, views, likes, duration, publish date, description, tags, channel stats and thumbnails. No API key, no daily quota, no OAuth — unlike the official Data API.

Pricing

from $2.00 / 1,000 video scrapeds

Rating

0.0

(0)

Developer

Arman Hossain

Arman Hossain

Maintained by Community

Actor stats

0

Bookmarked

1

Total users

0

Monthly active users

3 days ago

Last modified

Share

YouTube Scraper: Search, channels, playlists and videos in one run, exact view counts, duration, dates and tags

YouTube Scraper takes search terms, channel handles, playlist URLs and video URLs in the same run and returns one record shape for all of them: title, exact view count, exact like count, duration, publish date, full description, tags, channel stats and thumbnails.

Every record carries type, id and url, so a search result, a channel's upload history and a one-off video lookup all land in the same table. No API key, no daily quota, no OAuth, no proxy setup and no browser.

Agent skill: SKILL.md

https://api.apify.com/v2/key-value-stores/t7YoTxpZEJOWvw4Ug/records/youtube-scraper.md

What you get

One record per video, short, channel or playlist. type tells them apart; every key exists on every record, and null means YouTube does not publish that field for that item.

Output fieldMeaning
typevideo, short, channel or playlist
idVideo ID, channel ID or playlist ID. Your join key
urlCanonical YouTube link, built from the ID
titleVideo, channel or playlist title
inputThe search term or URL that produced this row
positionRank within that input
descriptionFull video description, the channel's About text, or the playlist blurb
viewCountExact when video details are on. viewCountIsExact tells you which you got
viewCountIsExacttrue for a precise figure, false for one parsed from a rounded label
likeCountExact like count. null when the creator has hidden likes, never 0
durationSeconds, duration213 and 3:33
publishedAtISO 8601 publish time. Present when video details are on
publishedTextYouTube's own relative string, e.g. 4 years ago
isLive, wasLiveCurrently streaming, and ever streamed
tagsThe uploader's own keywords. Video details only
categoryNameMusic, Education, and so on. Video details only
thumbnailUrlLargest thumbnail offered
channelId, channelName, channelHandle, channelUrlWho published it
subscriberCountApproximate. YouTube publishes only a rounded figure
badges4K, CC, LIVE
videoCountUploads on a channel, or entries in a playlist
totalViewCountLifetime views for a channel, or for a playlist
joinedDate, countryChannel only
avatarUrl, bannerUrl, isVerified, linksChannel only
playlistId, firstVideoIdPlaylist only
scrapedAtRun timestamp

There is no commentCount. Nothing this Actor reads publishes one, and a column that is permanently null is worse than an honest omission.

A RUN_SUMMARY record in the key-value store holds records saved by type, how many view counts were exact, how many videos were checked and found to have likes hidden, the filters that were applied, how many rows were removed by each filter and how many could not be date-checked at all, any input that ran into the paging ceiling before its cap was met, every failure with its reason, and any result card the parser did not recognise.

Input

FieldTypeDefaultNotes
searchQueriesarray[]Search terms, exactly as typed into YouTube's search bar
startUrlsarray[]Video, channel, playlist or @handle URLs, mixed freely. Bare IDs and youtu.be links work too
maxResultsPerInputinteger50Cap on the total records one query or URL may produce, across every requested resultTypes. The main cost control, since charging is per record
resultTypesarray["video"]Any of video, short, channel, playlist. Decides what a search keeps, and which of a channel's tabs are read
sortBystringrelevancerelevance, date, views, rating. Search terms only
uploadedAfterstringA date (2026-01-15) or a window (30 days)
videoDurationstringanyshort (under 4 min), medium (4 to 20), long (over 20). Search terms only
videoFeaturesarray[]hd, 4k, subtitles, creativeCommons, live, 360, hdr, combined with AND. Search terms only
includeVideoDetailsbooleantrueThe accuracy dial. On: exact view and like counts, full description, tags, category, exact publish date, one extra lookup per video. Off: faster and cheaper in time, with YouTube's rounded display counts and no publish date
countrystringUSTwo-letter code. Changes which results rank
languagestringenTwo-letter code. Changes YouTube's interface strings, including the wording of relative dates

At least one of searchQueries or startUrls is required. A run with neither fails with a named error rather than returning nothing.

{
"searchQueries": ["web scraping tutorial"],
"startUrls": ["https://www.youtube.com/@Apify"],
"maxResultsPerInput": 100,
"resultTypes": ["video"],
"uploadedAfter": "90 days",
"sortBy": "views"
}

Output

{
"type": "video",
"id": "dQw4w9WgXcQ",
"url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
"title": "Rick Astley - Never Gonna Give You Up (Official Video) (4K Remaster)",
"input": "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
"position": 1,
"description": "The official video for “Never Gonna Give You Up” by Rick Astley...",
"viewCount": 1802092331,
"viewCountIsExact": true,
"likeCount": 19322530,
"durationSeconds": 213,
"duration": "3:33",
"publishedAt": "2009-10-25T06:57:33.000Z",
"publishedText": null,
"isLive": false,
"wasLive": false,
"tags": ["rick astley", "Never Gonna Give You Up", "rickroll"],
"categoryName": "Music",
"thumbnailUrl": "https://i.ytimg.com/vi/dQw4w9WgXcQ/maxresdefault.jpg",
"channelId": "UCuAXFkgsw1L7xaCfnd5JJOw",
"channelName": "Rick Astley",
"channelHandle": "@RickAstleyYT",
"channelUrl": "https://www.youtube.com/channel/UCuAXFkgsw1L7xaCfnd5JJOw",
"subscriberCount": 4530000,
"badges": [],
"videoCount": null,
"totalViewCount": null,
"joinedDate": null,
"country": null,
"avatarUrl": null,
"bannerUrl": null,
"isVerified": false,
"links": [],
"playlistId": null,
"firstVideoId": null,
"scrapedAt": "2026-08-09T01:14:02.000Z"
}

A channel record fills the channel half of the same shape:

{
"type": "channel",
"id": "UCTgwcoeGGKmZ3zzCXN2qo_A",
"url": "https://www.youtube.com/channel/UCTgwcoeGGKmZ3zzCXN2qo_A",
"title": "Apify",
"channelName": "Apify",
"channelHandle": "@Apify",
"description": "Apify equips you and your AI agents with thousands of ready-to-run tools...",
"subscriberCount": 17400,
"videoCount": 268,
"totalViewCount": 11646145,
"joinedDate": "2017-01-04",
"country": "Czechia",
"avatarUrl": "https://yt3.googleusercontent.com/...",
"bannerUrl": "https://yt3.googleusercontent.com/...",
"isVerified": false,
"links": [{ "title": "Browse tools", "url": "apify.com/store" }]
}

Use cases

  • Creator discovery. Search a topic, keep channel results, and rank by subscribers and lifetime views.
  • Topic tracking. Run a set of queries on a schedule with uploadedAfter, and watch what gets published on a subject.
  • Channel analysis. Point at a handle and pull the whole upload history with exact view and like counts, then look at the trend.
  • URL enrichment. Hand it a list of video URLs from a spreadsheet and get structured metadata back, one row each.
  • Playlist inventory. Turn a course playlist into a table of videos, durations and view counts.

Limits and behaviour

  • Subscriber counts are rounded, by YouTube. 17.4K subscribers is the most precise figure published anywhere, so subscriberCount is 17400, not the true number. It cannot be made exact.
  • subscriberCount on a search result needs includeVideoDetails. A search listing does not carry it, so it is looked up once per channel and reused. With details off, search rows have subscriberCount: null; a channel's own pages always carry it either way.
  • maxResultsPerInput is a total, not a per-type quota. One channel URL asked for ["channel", "video", "short", "playlist"] with a cap of 200 returns at most 200 rows in all, filled in that order — not 200 of each. The cap is what you are charged for, so it is never exceeded.
  • View counts are exact only with includeVideoDetails on. With it off, viewCount comes from a display label such as 474K views and viewCountIsExact is false. Never round silently: check the flag.
  • likeCount needs includeVideoDetails. A listing carries no like figure at all, in any form, so with details off the field is null on every row rather than a rounded guess.
  • likeCount is null when the creator hides likes. That is not zero, and treating it as zero would misreport an unliked video.
  • publishedAt is null without video details. A listing only carries 4 years ago, and turning that into a timestamp would be precision this Actor does not have. publishedText carries YouTube's own wording instead.
  • uploadedAfter is exact with details on, approximate without. With details off it is applied against the relative string, so a video near the boundary can fall either way. If that string cannot be read at all — which is what happens when language is not en — the row is kept rather than dropped, and counted in RUN_SUMMARY.datesUnverifiable so a result set that overshoots the window says why. An uploadedAfter value the Actor cannot parse stops the run before anything is fetched or charged.
  • type is short only when the source said so. A /shorts/ URL or a card from a Shorts shelf. A short clip found through search stays video.
  • commentCount is not returned. See above.
  • A single input is walked for a bounded number of pages. Very large caps on a broad search can stop short of maxResultsPerInput; when that happens the input is listed in RUN_SUMMARY.truncatedByPageCap rather than quietly returning a short answer. Split the work across narrower queries to go deeper.
  • No video, audio or subtitle downloads. This Actor returns metadata. Nothing is streamed, saved or converted.
  • Deleted, private and region-locked videos are named failures, listed in RUN_SUMMARY.failures, not blank rows. One bad URL never ends a run.
  • Results churn. YouTube reorders its own search results between requests. Join on id and treat a single absence as noise.
  • Rows are deduplicated within an input, not across them. Two search terms that both surface the same video produce two rows, each with its own input and position. Deduplicate on id yourself if you merge inputs.
  • Non-English runs return YouTube's own strings. With language set to something other than en, publishedText comes back localised and any figure derived from a display label may be null. Turn video details on for language-independent numbers.
  • Public data only. No authentication, and nothing that gets around access controls.

FAQ

Do I need a YouTube API key or a Google Cloud project? No. You supply no credentials.

How does this compare with the official Data API's quota? There is no daily unit budget to plan against here. You are billed per record returned, so a 1,000-video run costs the same whether it is your first of the day or your fiftieth.

Why is a view count a few hundred off from what the web page shows? YouTube's own counters update on a delay and are not synchronised across surfaces. With includeVideoDetails on you get the precise figure YouTube itself reports for the video at that moment.

How do I scrape a whole channel? Put the channel URL or @handle in startUrls and raise maxResultsPerInput past the channel's upload count. Set resultTypes to ["video"] for uploads, add "short" for its Shorts, "playlist" for its playlists, or "channel" for a single row about the channel itself. Remember the cap covers all of them together, so raise it if you ask for more than one.

Can I get comments or transcripts? No. Those are separate products with a different shape.

Why is likeCount null on some videos? The creator switched likes off. The field stays null rather than reporting a zero that is not true.

Can I mix inputs? Yes. Search terms, channel handles, playlist URLs and video URLs can all go into one run, and they produce the same record shape.

Can I plug it into something else? Yes. Apify API, the client libraries, webhooks, scheduled runs, dataset exports to JSON, CSV or Excel, or MCP. The output is structured JSON.

API example

curl -X POST "https://api.apify.com/v2/acts/arman-bd~youtube-scraper/run-sync-get-dataset-items?token=YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"searchQueries": ["web scraping tutorial"],
"maxResultsPerInput": 50,
"resultTypes": ["video"],
"sortBy": "views",
"uploadedAfter": "365 days"
}'

JavaScript example

import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: 'YOUR_TOKEN' });
const run = await client.actor('arman-bd/youtube-scraper').call({
startUrls: ['https://www.youtube.com/@Apify'],
maxResultsPerInput: 200,
resultTypes: ['video'],
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
for (const v of items) console.log(`${v.title}${v.viewCount} views, ${v.likeCount ?? 'likes hidden'}`);