To see what a competitor's channel really publishes, you want every video in one table: upload date, length, views, likes, comments, and the channel's subscriber count. YouTube Studio covers your own channel, not someone else's, and copying titles from a channel page by hand stops being fun around video 40. The official YouTube Data API v3 returns all of it for any public channel. Here is how it works, where it bites, and a no-code way to run it.
What the YouTube Data API gives you
The YouTube Data API v3 is free and returns public data as JSON. Four resources matter for this job:
-
channels: title, subscriber count, total views, video count, and the ID of the channel's uploads playlist. -
playlistItems: the videos in a playlist, 50 per page. -
videos: details and statistics for up to 50 video IDs per call. -
search: keyword search. It can list a channel's videos too, but it is the wrong tool for that, as the next section explains.
Every API key has a daily quota of 10,000 units. Reading channels, playlists and videos is cheap, about 1 unit per 50 videos. Search is not: each search page costs 100 units.
Why you list uploads through the uploads playlist
The obvious approach is search filtered by channel. It costs 100 units a page, and YouTube caps search results at 500, so you cannot even reach the end of a large channel.
Every channel instead has an automatically maintained uploads playlist. Its ID is in the channels response under contentDetails.relatedPlaylists.uploads (it is the channel ID with the UC prefix swapped for UU). playlistItems pages through it newest first, with no 500-result cap, at a small fraction of search's cost.
The catch is that playlistItems returns IDs and titles, not statistics. So the loop is:
- Call
channelswith the handle or channel ID to get the uploads playlist ID and the subscriber count. - Call
playlistItemspage by page until there is nonextPageToken. - Send the video IDs to
videosin batches of 50 for views, likes, comments, duration and tags. - Add the channel's stats to every row.
Expect rough edges in the raw responses. Counts arrive as strings, duration is ISO 8601 (PT1H2M3S), likes and comments are missing when the owner hides them, and private or deleted videos show up in the playlist but not in videos.
Which columns are worth keeping
For competitor research a handful of fields does most of the work:
-
publishedAtanddurationSeconds: upload cadence, and short versus long formats. Shorts are ordinary uploads, so length is how you separate them. -
viewCount,likeCount,commentCount: raw performance. Compare channels per subscriber, not in absolute numbers. -
channelSubscribers: the denominator for views per subscriber. -
titleandtags: the topics and phrasing the channel bets on. -
categoryandliveStatus: keep live streams from skewing your averages.
These are today's numbers. The API does not return history, so to track growth, rerun the export on a schedule and keep every run with its scrapedAt timestamp.
The no-code version
Best Damn YouTube Scraper is an Apify Actor that runs the loop above against the official API (channels, playlistItems, search and videos). No browser runs and no login is used, so nothing breaks when YouTube changes its layout.
- Paste channel URLs,
@handlesor channel IDs into YouTube URLs. - Set Max results per channel, playlist or search to 0, which means all videos, newest first.
- Click Start, then download the Output tab as CSV or Excel, or connect an integration to push it to Google Sheets.
Even channels with thousands of uploads finish in a few seconds. Example input for two channels:
{
"startUrls": ["https://www.youtube.com/@YouTube", "https://www.youtube.com/@jawed"],
"maxResults": 0,
"maxDescriptionLength": 200
}
maxDescriptionLength trims descriptions so spreadsheet cells stay readable (0 keeps the full text). Add "publishedAfter": "90 days" to limit the export to recent uploads. If a video appears under more than one input, it is returned and billed once.
One record per video, trimmed from the real example in the Actor's docs:
{
"success": true,
"videoId": "jNQXAC9IVRw",
"title": "Me at the zoo",
"publishedAt": "2005-04-24T03:31:52Z",
"durationSeconds": 19,
"viewCount": 435887912,
"likeCount": 19914774,
"commentCount": 10626831,
"channelTitle": "jawed",
"channelSubscribers": 6610000
}
If you only need one row per channel, set "outputMode": "channels" and you get subscriberCount, viewCount, videoCount and country per channel instead of a list of videos.
From code
One HTTP call runs the Actor and writes the CSV:
curl -X POST "https://api.apify.com/v2/acts/josh99smith~youtube-scraper/run-sync-get-dataset-items?token=$APIFY_TOKEN&format=csv" \
-H "Content-Type: application/json" \
-d '{ "startUrls": ["https://www.youtube.com/@YouTube"], "maxResults": 0 }' \
-o channel-videos.csv
The same input works with the apify-client packages for Python and JavaScript.
Cost and limits
$0.001 per video delivered, so 1,000 videos cost $1.00 and a 500-video channel costs $0.50. In Channels only mode the price is the same per channel. There is no start-up charge, and private, deleted and unavailable videos, invalid inputs and quota errors cost nothing. Each run stops at the maximum cost you set.
Quota is the limit to plan around. By default the Actor uses a built-in API key shared by all its users, with the usual 10,000 units a day. Whole-channel exports are cheap, but search is expensive, so the shared key allows up to 5 search terms and 100 results per term per run. For heavy or scheduled work, create your own free key in the Google Cloud Console, enable "YouTube Data API v3", and paste the key into YouTube API key. When a quota runs out, the run stops cleanly and returns free rate-limited records. Quotas reset at midnight Pacific Time.
Other limits to know:
- Only public data. Private, unlisted, members-only and removed videos are not included, and nothing from a logged-in account is available.
-
likeCountandcommentCountarenullwhen the owner hides likes or turns comments off. - Subscriber counts are rounded by YouTube to three significant figures, and channels that hide the count return
null.
If this saves you time, a review on the Store page helps other people find it, and a star on GitHub helps too.
Disclosure: I built this Actor. Source: github.com/josh99smith/youtube-scraper. YouTube is a trademark of Google, and the Actor is not affiliated with Google.
Top comments (0)