YouTube scraping means collecting the public data around videos: titles, view counts, likes, comment counts, upload dates, durations, channel statistics and existing subtitles. The fastest way is a ready-made Actor: paste a channel, playlist or search, set how many videos you want, and export the rows as JSON or CSV a few seconds later.
This guide shows which fields you get, how to run the scraper without code, and how to call it from curl, Python, JavaScript or an AI agent. It also covers what it costs, where it stops, the legal side and when the official YouTube Data API is the better choice. Every number below comes from a real run on 22 October 2026 that scraped the five latest videos from NASA's Jet Propulsion Laboratory channel.
What data you can get from YouTube
Each row is one public video, Short or stream. These are the fields most people use:
| Field | What it holds |
|---|---|
title | Video title |
url | Watch URL |
type | video, shorts or stream |
viewCount | Views, as a number |
likes | Like count |
commentsCount | Number of comments (not the comment text) |
date | Upload time with a UTC offset, e.g. 2026-10-12T16:25:11-07:00 |
duration | Length as HH:MM:SS |
text | Video description |
tags, category | Uploader tags and YouTube category |
channelName, channelId, channelUrl | The channel that posted it |
numberOfSubscribers | Channel subscriber count |
channelTotalVideos, channelTotalViews | Channel totals, on channel listings |
subtitleLanguages, subtitles | Caption tracks that exist, and their text when you ask for it |
Fields appear only when YouTube's page contains them, and a real 0 or false is kept. Comment bodies are not scraped, and there is no speech-to-text: you get subtitles only where a caption track already exists.
How to scrape YouTube without code
- Open the YouTube Scraper in the Scrape.ly Store.
- Pick the NASA channel videos preset. It fills in this input:
{
"startUrls": [
{
"url": "https://www.youtube.com/@NASAJPL"
}
],
"maxResults": 5,
"maxResultsShorts": 0,
"maxResultStreams": 0
}- Swap in your own channel, playlist, video or search URL, and change the numbers.
- Start the run. A five-video channel run finished in about 13 seconds.
- Export the results as JSON, CSV or Excel.
The input fields that matter most:
startUrls: YouTube video, channel, playlist, hashtag or search-results URLs. Non-YouTube URLs are rejected before the run starts. When URLs are set, search terms are ignored.searchQueries: search terms, typed the way you would in YouTube's search bar. Combine them withsortingOrder,dateFilter,lengthFilterand feature filters such ashasSubtitlesoris4K.maxResults(required): how many regular videos to keep per search, channel, playlist or hashtag. Default 10.maxResultsShortsandmaxResultStreams: separate caps for Shorts and streams. Both default to 0, so a channel run returns regular videos only unless you raise them.transcriptionAndSubtitle: set toALWAYS_SUBTITLESto download caption tracks that already exist, withsubtitlesLanguage(defaulten) andsubtitlesFormat(srt,vtt,xmlorplaintext).
For channels, sortVideosBy follows the Latest, Popular or Oldest buttons, and oldestPostDate keeps only videos published on or after a date.
How to scrape YouTube with the API
Get your token from Settings → API & Integrations in the Scrape.ly dashboard and export it as SCRAPELY_TOKEN. The Actor API docs cover every endpoint.
curl
This run takes well under the 45-second limit of the synchronous endpoint, so one call starts the run and returns the items as a JSON array. Add ?format=csv for CSV.
curl -X POST "https://api.scrape.ly/v2/actors/echofield~youtube-scraper/run-sync-get-dataset-items" \
-H "Authorization: Bearer $SCRAPELY_TOKEN" \
-H "Content-Type: application/json" \
-d '{"startUrls": [{"url": "https://www.youtube.com/@NASAJPL"}], "maxResults": 5, "maxResultsShorts": 0, "maxResultStreams": 0}'Bigger jobs can take longer than 45 seconds. The call then answers 408 while the run keeps going. Don't call again, because that starts a second run. Use the asynchronous flow in the Actor API docs or one of the clients below, and read the rows with the dataset API.
Python
Install the Python client with pip install scrapely-client-python. call() waits for the run however long it takes.
import os
from scrapely_client import ScrapelyClient
client = ScrapelyClient(os.environ["SCRAPELY_TOKEN"], api_url="https://api.scrape.ly")
run = client.actor("echofield/youtube-scraper").call(
run_input={
"startUrls": [{"url": "https://www.youtube.com/@NASAJPL"}],
"maxResults": 5,
"maxResultsShorts": 0,
"maxResultStreams": 0,
}
)
print(run.status) # SUCCEEDED, FAILED, ABORTED or TIMED-OUT
for item in client.dataset(run.default_dataset_id).iterate_items():
print(item["title"], item.get("viewCount"), item.get("likes"))Use item.get() for counts, since a field YouTube didn't send is left off the row.
JavaScript
Install the JavaScript client with npm install scrapely-client.
import { ScrapelyClient } from 'scrapely-client';
const client = new ScrapelyClient({ token: process.env.SCRAPELY_TOKEN, baseUrl: 'https://api.scrape.ly' });
const run = await client.actor('echofield/youtube-scraper').call({
startUrls: [{ url: 'https://www.youtube.com/@NASAJPL' }],
maxResults: 5,
maxResultsShorts: 0,
maxResultStreams: 0,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items.length, items[0]);MCP for AI agents
Scrape.ly runs a hosted MCP server at https://api.scrape.ly/mcp. In Cursor, add it to ~/.cursor/mcp.json:
{
"mcpServers": {
"scrapely": {
"url": "https://api.scrape.ly/mcp",
"headers": { "Authorization": "Bearer YOUR_TOKEN" }
}
}
}In Claude Code, run claude mcp add --transport http scrapely https://api.scrape.ly/mcp, then /mcp to sign in with OAuth. The agent finds the Actor with search-actors, reads its input with fetch-actor-details, runs it with call-actor and reads rows with get-actor-output. Try a prompt like: "Use scrapely to run echofield/youtube-scraper on https://www.youtube.com/@NASAJPL for the 5 latest videos and give me a CSV of title, views, likes and upload date."
A real run: NASA channel videos, 5 videos
We ran the preset on 22 October 2026. It saved 5 videos in 12.7 seconds on 512 MB of memory and was charged $0.0185 in total. All five rows have channelName "NASA Jet Propulsion Laboratory", so that column is left out here:
| title | viewCount | likes | commentsCount | date | duration | url |
|---|---|---|---|---|---|---|
| Welcome to Our Universe: Explore JPL 2026 | 22,219 | 448 | 30 | 2026-10-12T16:25:11-07:00 | 00:01:36 | youtube.com/watch?v=VQEQ0BuHNEY |
| NASA’s SkyFall Mars Helicopters | 296,672 | 4,739 | 446 | 2026-10-06T13:32:48-07:00 | 00:01:01 | youtube.com/watch?v=DOhJpThqrxs |
| JPL x SpaceX \ | NXT in Space: Episode 4 | 11,951 | 120 | 4 | 2026-10-01T15:36:00-07:00 | 00:39:24 | youtube.com/watch?v=gIURQuAEec4 |
| What's Up: October 2026 Skywatching Tips from NASA | 31,840 | 515 | 40 | 2026-10-01T09:57:06-07:00 | 00:02:42 | youtube.com/watch?v=0w5hBQcFYaw |
| JPL x Aerospace Corporation \ | NXT in Space: Episode 3 | 12,009 | 90 | 9 | 2026-09-10T16:00:57-07:00 | 00:40:25 | youtube.com/watch?v=hSFrdPXNwtw |
The console shows a short, clean run:
2026-10-22T15:22:59.875Z [Scrapely] Container started (setup 0.8 s)
2026-10-22T15:23:01.155Z [scrapely.actor] INFO [Scrapely] Initializing API storage for run 219d9585d3204549b
2026-10-22T15:23:01.300Z [scrapely.proxy_configuration] INFO Platform proxy access check succeeded.
2026-10-22T15:23:11.257Z [scrapely.actor] INFO [Status message]: Saved 5 results.
2026-10-22T15:23:11.834Z [Scrapely] Container state: status=exited exitCode=0 oomKilled=falseThe SkyFall Mars Helicopters video has 296,672 views, more than the other four combined. The two "NXT in Space" episodes run about 40 minutes, while the rest are under three. Note that date keeps YouTube's -07:00 offset, so convert to UTC before you join it with other data. The full record for the first video also carried channel data: 1,240,000 subscribers, 1,434 channel videos and isChannelVerified: true.
What it costs
The Actor charges per event:
- Result: $0.003 per saved video, Short or stream.
- Date filter: $0.0008 per result when
dateFilter(search) oroldestPostDate(channels) is set and applied.
This run saved 5 results with no date filter, so the result fees were 5 × $0.003 = $0.015. The run was charged $0.0185 in total because platform usage was added on top: $0.0031 of residential proxy traffic and $0.0004 of compute, plus a fraction of a cent for dataset writes.
For 1,000 videos you pay $3.00 in result fees, or $3.80 if a date filter applies to every one (1,000 × $0.0038). Platform usage comes on top. Subtitles don't add an event, and failed inputs, such as a channel that doesn't exist, are never charged.
Limits and common problems
- No comment text. You get
commentsCount, not the comments. If you need the text, the official API'scommentThreads.listreturns it (see Alternatives). - Shorts and streams are off by default.
maxResultsShortsandmaxResultStreamsdefault to 0. A search with all three caps at 0 stores no rows. - Missing inputs don't become rows. A missing channel or playlist is listed in the run's
OUTPUTrecord asfailedInputs(for exampleCHANNEL_DOES_NOT_EXIST) and the rest of the run continues. Check that record if a channel seems to be missing. - Fields can be absent. Counts and text are written only when the page has them. Code against missing keys rather than assuming every row has
likes. - Subtitles only where they exist.
ALWAYS_SUBTITLESdownloads existing caption tracks. Videos without one get none, and there is no transcription. - Long runs and the sync endpoint. This run took 13 seconds. Big channel pulls can pass 45 seconds, so use the clients or the asynchronous flow for those.
Is it legal to scrape YouTube?
The data in this guide is public: anyone can see it on YouTube without logging in. That does not settle the question. YouTube's Terms of Service say you may not access the service by automated means such as scrapers, except for public search engines following robots.txt or with YouTube's prior written permission. They also bar collecting information that might identify a person, such as usernames or faces, without that person's permission.
Channel names and descriptions can be personal data when the channel belongs to an individual, and then privacy laws like the GDPR and CCPA apply to how you collect, store and use them. Videos and thumbnails are also protected by copyright. This is not legal advice: if you plan to scrape YouTube for a business purpose, get advice from a lawyer for your specific case.
Alternatives
- The YouTube Data API v3. Google's official API returns videos, channels, playlists and comment threads as structured JSON. It is metered by quota: by default 10,000 units a day for most endpoints, plus a separate bucket of 100
search.listcalls a day. Avideos.listorchannels.listcall usually costs 1 unit, invalid requests cost at least 1, and quotas reset at midnight Pacific Time (quota costs). You can apply for more. It is the better choice when you need comment text or your own channel's data, or when a sanctioned source matters more to you than volume. - yt-dlp. An open-source Python command-line tool for downloading audio and video. It can also print per-video metadata. It is a good fit for one-off jobs on a handful of URLs from your own machine.
- scrapetube. A small MIT-licensed Python library for listing videos from channels, playlists and searches. Pick it if you only need video lists and will handle proxies and failures yourself.
- A headless browser. Playwright or Puppeteer give you full control over what you read. You also own the upkeep: YouTube's page markup changes, and at volume you need your own proxies.
FAQ
Can you scrape YouTube without the API?
Yes. The scraper reads the public pages and the same JSON those pages load, so it needs no API key and has no daily quota. You pay per saved video instead ($0.003 each), plus platform usage.
How do I scrape all videos from a YouTube channel?
Put the channel URL in startUrls and raise maxResults. Set maxResultsShorts and maxResultStreams too if you want Shorts and streams. Each record's channelTotalVideos (1,434 for NASA JPL on 22 October 2026) shows how many videos the channel reports. For large pulls, use the Python or JavaScript client so you don't hit the 45-second sync limit.
Can you scrape YouTube comments?
This Actor returns the comment count (commentsCount) but not comment bodies. For the comment text itself, the YouTube Data API's commentThreads.list method returns comments at a quota cost of 1 unit per call.
Can I download YouTube subtitles?
Yes, if the video already has a caption track. Set transcriptionAndSubtitle to ALWAYS_SUBTITLES and choose the language and format. Turn on saveSubsToKVS to also save each file in the run's key-value store. Auto-generated tracks count; set preferAutoGeneratedSubtitles if you want those first.
How much does YouTube scraping cost?
$3.00 per 1,000 videos in result fees, or $3.80 with a date filter, plus platform usage. Our five-video run cost $0.0185 in total.




