The official YouTube Data API v3 is the reliable way to get YouTube data: no page scraping, no proxies, no blocks. The catch is the work around it. You have to batch video IDs 50 at a time, page through uploads playlists, call a second endpoint to get stats for search results, handle reply threads, and stop gracefully when the quota runs out.
The ActorForge YouTube actors do that client work for you, but they do not hide the key: every run uses your own API key and quota. There is no shared or built-in key, ActorForge never holds or pools keys, and the data is fetched under your key into your own dataset. What you skip is the code, not the Google Cloud step.
This guide walks through creating the key, choosing the right actor and mode for your job, budgeting quota, and post-processing the results. ActorForge is not affiliated with or endorsed by YouTube or Google.
Step by step
Create a free YouTube Data API v3 key
Open the Google Cloud Console, sign in with any Google account and create a project. Under APIs & Services, open the Library, search for YouTube Data API v3 and enable it. Then go to Credentials, create an API key and copy it; it starts with AIza. You do not need to add a billing account. If you restrict the key, allow YouTube Data API v3 but leave out HTTP-referrer and IP restrictions, because Apify runs on changing server IPs.
Pick the actor that matches your job
All four actors share the same
modefield and the same key. Use YouTube Scraper for details and stats on a list of video URLs or IDs, YouTube Channel Scraper for a channel's stats plus its uploads, YouTube Search Scraper for ranked keyword results, and YouTube Comments Scraper for comments and replies with author fields stripped. The listings differ mainly in default mode and pricing: video rows are $0.40 per 1,000 on the scraper and channel actors, while the search actor charges $0.30 per 1,000 results.Budget your daily quota before a big run
Each Google Cloud project gets 10,000 free units a day, reset at midnight Pacific Time. Video lookups cost 1 unit per 50 videos, channel mode about 1 unit per channel plus about 2 per 50 videos, comments 1 unit per 100, and search 101 units per page of 50. In practice that is about 500,000 video lookups, 250,000 channel videos, 1,000,000 comments, or only about 5,000 search results a day. The run log prints an estimate before any call is made, so check it on your first run.
# Rough quota estimate for a planned run (units per the actor README) import math def quota_units(videos=0, channels=0, channel_videos=0, comments=0, search_results=0): units = math.ceil(videos / 50) units += channels + 2 * math.ceil(channel_videos / 50) units += math.ceil(comments / 100) units += 101 * math.ceil(search_results / 50) return units print(quota_units(channels=20, channel_videos=4000)) # 180 print(quota_units(search_results=2000)) # 4040 print(quota_units(comments=50000)) # 500Run channel mode and compute engagement
A common first job is to export a channel's recent uploads and rank them by engagement. Channel mode returns one row with
typechannel and then one row per video. Likes can be null when a creator hides them, so convert to numbers before dividing.import os import pandas as pd from apify_client import ApifyClient client = ApifyClient(os.environ["APIFY_TOKEN"]) run = client.actor("actor-forge/youtube-channel-api").call(run_input={ "apiKey": os.environ["YOUTUBE_API_KEY"], "mode": "channel", "channels": ["https://www.youtube.com/@googledevelopers"], "maxVideosPerChannel": 200, "publishedAfter": "2026-01-01", }) rows = list(client.dataset(run["defaultDatasetId"]).iterate_items()) videos = pd.DataFrame([r for r in rows if r.get("type") == "video"]) for col in ["viewCount", "likeCount", "commentCount"]: videos[col] = pd.to_numeric(videos[col], errors="coerce") videos["engagement"] = (videos["likeCount"].fillna(0) + videos["commentCount"].fillna(0)) / videos["viewCount"] print(videos.sort_values("engagement", ascending=False)[["title", "viewCount", "engagement"]].head(10))Use search mode sparingly and split big topics
Search is where quota goes fastest, and YouTube returns at most about 500 results per query. Rather than asking for 500 results on one broad term, run several narrower queries or slice by date with
publishedAfterandpublishedBefore. Duplicates across queries are removed, so overlapping queries do not double-bill the same video.{ "apiKey": "AIzaSy...your-own-key", "mode": "search", "searchQueries": ["n8n tutorial", "n8n workflow automation", "n8n vs zapier"], "maxResultsPerQuery": 100, "order": "viewCount", "publishedAfter": "2026-01-01", "videoDuration": "medium" }Export comments for text analysis
For sentiment or topic work, switch to comments mode. Commenter names, channel IDs and avatars are stripped from every row, and replies arrive as their own rows linked by
parentId. KeepmaxRepliesPerCommentmodest so one huge thread does not dominate the dataset.import os, csv from apify_client import ApifyClient client = ApifyClient(os.environ["APIFY_TOKEN"]) run = client.actor("actor-forge/youtube-comments-api").call(run_input={ "apiKey": os.environ["YOUTUBE_API_KEY"], "mode": "comments", "videoUrls": ["https://www.youtube.com/watch?v=jNQXAC9IVRw"], "maxCommentsPerVideo": 300, "includeReplies": True, "maxRepliesPerComment": 10, }) with open("comments.csv", "w", newline="", encoding="utf-8") as f: w = csv.writer(f) w.writerow(["videoId", "isReply", "likeCount", "publishedAt", "text"]) for r in client.dataset(run["defaultDatasetId"]).iterate_items(): if r.get("type") == "error": continue w.writerow([r.get("videoId"), r.get("isReply"), r.get("likeCount"), r.get("publishedAt"), r.get("text")])Schedule refreshes and respect the 30-day rule
YouTube's Developer Policies require stored API data to be refreshed or deleted at least every 30 days, and stats such as views change constantly anyway. Create an Apify schedule that re-runs the actor with the same input, for example weekly, and set a retention period on the datasets you keep. ActorForge keeps no copy of the data after the run.
Sample input
{
"apiKey": "AIzaSy...your-own-key",
"mode": "videos",
"videoUrls": [
"https://www.youtube.com/watch?v=dQw4w9WgXcQ",
"https://youtu.be/jNQXAC9IVRw"
]
}Sample output
In videos mode, each URL or ID comes back as one row with full stats, like these:
| title | channelTitle | publishedAt | durationSec | viewCount | likeCount | commentCount | categoryId | isShort | searchQuery |
|---|---|---|---|---|---|---|---|---|---|
| Rick Astley - Never Gonna Give You Up (Official Video) (4K Remaster) | Rick Astley | 2009-10-25T06:57:33Z | 214 | 1828596530 | 19490833 | 2460128 | 10 | false | |
| Me at the zoo | jawed | 2005-04-24T03:31:52Z | 19 | 445426986 | 20095698 | 10642771 | 1 | true | |
| PSY - GANGNAM STYLE(강남스타일) M/V | officialpsy | 2012-07-15T07:46:32Z | 253 | 6098344051 | 32321298 | 5465487 | 10 | false | |
| Web Scraping with Python - Beautiful Soup Crash Course | freeCodeCamp.org | 2020-11-18T16:05:43Z | 4103 | 1827575 | 39425 | 1102 | 27 | false | web scraping tutorial |
Run it from code
cURL
curl -X POST "https://api.apify.com/v2/acts/actor-forge~youtube-api-scraper/run-sync-get-dataset-items" \
-H "Authorization: Bearer $APIFY_TOKEN" \
-H "Content-Type: application/json" \
-d '{"apiKey": "AIzaSy...your-own-key", "mode": "videos", "videoUrls": ["https://www.youtube.com/watch?v=dQw4w9WgXcQ", "https://youtu.be/jNQXAC9IVRw"]}'JavaScript (Node.js)
// Node.js 18+ (built-in fetch). Set APIFY_TOKEN in your environment.
const input = {
"apiKey": "AIzaSy...your-own-key",
"mode": "videos",
"videoUrls": [
"https://www.youtube.com/watch?v=dQw4w9WgXcQ",
"https://youtu.be/jNQXAC9IVRw"
]
};
const res = await fetch(
"https://api.apify.com/v2/acts/actor-forge~youtube-api-scraper/run-sync-get-dataset-items",
{
method: "POST",
headers: {
Authorization: `Bearer ${process.env.APIFY_TOKEN}`,
"Content-Type": "application/json",
},
body: JSON.stringify(input),
}
);
const items = await res.json();
console.log(items.length, items[0]);Python
# pip install apify-client (set APIFY_TOKEN in your environment)
import os
from apify_client import ApifyClient
client = ApifyClient(os.environ["APIFY_TOKEN"])
run_input = {
"apiKey": "AIzaSy...your-own-key",
"mode": "videos",
"videoUrls": [
"https://www.youtube.com/watch?v=dQw4w9WgXcQ",
"https://youtu.be/jNQXAC9IVRw"
]
}
run = client.actor("actor-forge/youtube-api-scraper").call(run_input=run_input)
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
print(item)The run-sync-get-dataset-items endpoint waits for the run (up to 5 minutes) and returns the dataset rows directly. For longer runs, start the run asynchronously and read the dataset when it finishes, as the Python example does. Replace APIFY_TOKEN with your own token from the Apify console.
What it costs
Looking up 1,000 videos by ID costs 1,000 × $0.0004 = $0.40 and about 20 quota units. Exporting one channel with 500 uploads costs $0.0005 for the channel row plus 500 × $0.0004 = $0.20, so $0.2005 in total, plus the small actor start fee.
| Charged for | When | Price | Per 1,000 | Worked example |
|---|---|---|---|---|
| Video result | Charged per video row delivered (full details and stats) | $0.0004 | $0.40 | 1,000 videos = $0.40 (streamers/youtube-scraper: $4.00 per 1,000) |
| Channel result | Charged per channel row delivered (stats, country, uploads playlist) | $0.0005 | $0.50 | 100 channels = $0.05; their videos are video-result rows |
| Comment result | Charged per comment or reply row delivered (author fields stripped) | $0.0005 | $0.50 | 10,000 comments = $5.00 (streamers/youtube-comments-scraper: $20) |
| Search page | Charged per search page of up to 50 results that returned rows (search mode; it costs 100 of your quota units) | $0.002 | $2 | 50 search results = $0.002 + 50 × $0.0004 = $0.022 |
| Actor Start (platform start fee) | Charged when the Actor starts running. Number of events charged depends on Actor memory (one event per GB, minimum one event). | $0.00005 | — | One run at 256 MB = $0.0000125 |
Ready to try it? YouTube Scraper (Official API) — Videos, Search & Stats runs on Apify, pay per result.
Run on Apify → Read the full actor pageTips and pitfalls
- Without a key the run stops at once with instructions and nothing is charged, so a missing key will not cost you anything.
- A
403 quotaExceedederror stops the run cleanly and keeps the rows already delivered; wait for the midnight Pacific reset rather than re-running immediately. - Quota is per Google Cloud project, not per actor, so the four YouTube actors all draw from the same 10,000 daily units when they use the same key.
- Do not expect dislike counts, watch time, revenue or subscriber lists: the public API does not return them, and hidden like counts come back as null.
isShortis a heuristic (3 minutes or less and not live); turning offincludeShortsin channel mode also drops regular videos of that length.
FAQ
Is the YouTube Data API free to use?
Yes, within the quota. Each Google Cloud project gets 10,000 units per day at no charge and no billing account is needed. The ActorForge actors charge per row delivered on top of that, but never for the API itself.
Can I use these actors without creating my own API key?
No. There is no built-in or shared key; every run uses your own key and quota. ActorForge sells the API client, not access to someone else's key.
Is my API key safe in the actor input?
The apiKey field is a secret input, so Apify stores it encrypted. The actor uses it only for that run's calls to googleapis.com and never logs it or writes it to the output. You can revoke or rotate it at any time in the Google Cloud Console.
Which method gets the most data from a free key?
Video lookups and comments are cheap in quota (1 unit per 50 videos or per 100 comments), while search costs 100 units per page. If you already have video IDs, look them up in videos mode instead of re-finding them through search.
Actors used in this guide
YouTube Scraper (Official API) — Videos, Search & Stats
Bring your own free YouTube API key. Get video details and stats (views, likes, comments, duration, tags), YouTube search results, channel uploads…
$0.40 per 1,000 · video resultYouTube Channel Scraper (Official API) — All Videos & Stats
Bring your own free YouTube API key. Get any channel's stats (subscribers, total views, video count, country) and every upload with views, likes…
$0.40 per 1,000 · video resultYouTube Search Scraper (Official API) — Videos by Keyword
Bring your own free YouTube API key. YouTube search by keyword with sort, date, region, language and length filters — every result enriched with…
$0.30 per 1,000 · video resultYouTube Comments Scraper (Official API) — No Usernames
Bring your own free YouTube API key. Export YouTube comments and replies (text, likes, reply count, dates) for any video via the official YouTube…
$0.50 per 1,000 · comment resultRelated guides
How to Track Google Trends Trending Searches by Country
Run the ActorForge Google Trends actor with a list of country codes, schedule it daily with only-new mode, and keep a small pandas history to see…
How to Monitor Competitor Ads in Google Ads Transparency Center
List your competitors' domains or advertiser names, run the ActorForge Ads Transparency actor daily with only-new mode, and route the new ads into…