If you run a YouTube channel, or build tools for people who do, sooner or later you want the numbers in a spreadsheet instead of clicking through YouTube Studio one video at a time. The YouTube Data API v3 gives you public stats (views, likes, comment counts, titles, publish dates) for any public video, and it is free within a daily quota.
This post walks through a small Python script that lists every upload on a channel and saves its stats to a CSV file.
Note: this guide was written with the help of AI tools and is based on the official YouTube Data API documentation. Check the docs linked at the end for the latest details.
What you can and cannot get
The Data API returns public information. For each video that means:
- title, description, tags and publish date (
snippet) - view count, like count and comment count (
statistics) - duration and definition (
contentDetails)
It does not return private analytics such as watch time, audience retention, click through rate or revenue. Those live in the separate YouTube Analytics API, which needs OAuth and the channel owner's permission. For many dashboards and research scripts, the public numbers are enough.
Step 1: Create an API key
- Open the Google Cloud Console and create a project (or pick an existing one).
- Go to APIs and Services, then Library, search for YouTube Data API v3 and enable it.
- Go to Credentials, click Create credentials, then API key.
- Restrict the key to the YouTube Data API v3 so it is less useful to anyone who finds it.
Keep the key out of your code. An environment variable is the simplest option:
export YT_API_KEY="paste-your-key-here" Step 2: Install the client library
pip install google-api-python-client Step 3: Find the channel's uploads playlist
Every channel has a hidden playlist that contains all of its public uploads. Reading that playlist is far cheaper than using the search endpoint, so it is the right way to list videos.
import os from googleapiclient.discovery import build API_KEY = os.environ["YT_API_KEY"] youtube = build("youtube", "v3", developerKey=API_KEY) def get_uploads_playlist(channel_id): resp = youtube.channels().list( part="contentDetails", id=channel_id, ).execute() return resp["items"][0]["contentDetails"]["relatedPlaylists"]["uploads"] If you only know the channel's handle (the @name part of the URL), recent versions of the API accept forHandle="@name" in place of id=channel_id.
Step 4: Collect every video ID
playlistItems.list returns at most 50 items per call, so loop with pageToken until there are no more pages.
def get_video_ids(playlist_id): ids, token = [], None while True: resp = youtube.playlistItems().list( part="contentDetails", playlistId=playlist_id, maxResults=50, pageToken=token, ).execute() ids += [item["contentDetails"]["videoId"] for item in resp["items"]] token = resp.get("nextPageToken") if not token: return ids Step 5: Fetch stats in batches of 50
videos.list accepts up to 50 comma separated IDs per request, which keeps the number of calls small.
def get_stats(video_ids): rows = [] for i in range(0, len(video_ids), 50): batch = video_ids[i:i + 50] resp = youtube.videos().list( part="snippet,statistics,contentDetails", id=",".join(batch), ).execute() for v in resp["items"]: s = v.get("statistics", {}) rows.append({ "video_id": v["id"], "title": v["snippet"]["title"], "published": v["snippet"]["publishedAt"], "duration": v["contentDetails"]["duration"], "views": int(s.get("viewCount", 0)), "likes": int(s.get("likeCount", 0)), "comments": int(s.get("commentCount", 0)), }) return rows Two details worth knowing:
-
likeCountandcommentCountcan be missing when a creator hides likes or turns comments off, which is why the code uses.get()with a default. -
durationcomes back in ISO 8601 format, such asPT4M13S. Theisodatepackage can turn it into seconds if you need to separate Shorts from long videos.
Step 6: Save to CSV
import csv def save_csv(rows, path="channel_stats.csv"): with open(path, "w", newline="", encoding="utf-8") as f: writer = csv.DictWriter(f, fieldnames=rows[0].keys()) writer.writeheader() writer.writerows(rows) if __name__ == "__main__": channel_id = "UC_your_channel_id_here" playlist = get_uploads_playlist(channel_id) ids = get_video_ids(playlist) rows = get_stats(ids) rows.sort(key=lambda r: r["views"], reverse=True) save_csv(rows) print(f"Saved {len(rows)} videos") Open the CSV in Excel or Google Sheets and you can sort by views, compare titles, or chart performance over time.
Mind the quota
New projects get a default quota of 10,000 units per day. Each channels.list, playlistItems.list and videos.list call costs 1 unit, so even a channel with a few thousand videos only uses a few hundred units with this approach.
The search.list endpoint costs 100 units per call, which is why this script avoids it. If you search for videos by keyword, a hundred searches will use the whole day's quota.
Ideas to take it further
- Run the script daily (cron or a scheduled GitHub Action) and store each run with a date, so you can see how views grow after upload.
- Compare your channel with a few channels in the same niche to see which topics and title styles get the most views.
- Split Shorts from long videos by duration and look at them separately, since they behave very differently.
If you would rather not write code, creator tools such as vidIQ and TubeBuddy show many of these public stats inside YouTube for you. But if you want the raw numbers in your own spreadsheet or app, a short script like this does the job.
Useful links
- YouTube Data API overview: https://developers.google.com/youtube/v3/getting-started
- Quota costs: https://developers.google.com/youtube/v3/determine_quota_cost
- Python client library: https://github.com/googleapis/google-api-python-client
