YouTube Transcript Scraper - Bulk & Whole Channels
Pricing
from $2.00 / 1,000 transcript delivereds
YouTube Transcript Scraper - Bulk & Whole Channels
Extract transcripts from thousands of YouTube videos in one run. Paste video URLs, a channel, or a playlist. Clean text, timestamped segments, SRT and WebVTT subtitles, or RAG-ready chunks. Any language, human or auto captions, plus video metadata. $2 per 1,000; videos without captions are free.
Pricing
from $2.00 / 1,000 transcript delivereds
Rating
0.0
(0)
Developer
DONGMIN KIM
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
4 days ago
Last modified
Categories
Share
YouTube Transcript Scraper — Bulk Subtitles to Text, SRT, VTT & RAG Chunks

Extract transcripts from thousands of YouTube videos in one run. Paste video URLs, a channel, or a playlist — get back clean text, timestamped segments, SRT/VTT subtitle files, or pre-chunked passages ready for embeddings. Video metadata is included in every row at no extra cost.
Built for people who hit the wall with other transcript scrapers: one URL at a time, silent failures when YouTube throttles, and no metadata.
What makes this one different
| This actor | Typical transcript scraper | |
|---|---|---|
| Input | Unlimited URLs + whole channels + playlists in one run | One video URL per run |
| Throttling | Datacenter → residential proxy escalation, per-video IP sessions | Fails, or silently returns nothing |
| Metadata | Title, channel, views, duration, publish date, keywords, thumbnail — free | Sold separately, or missing |
| RAG output | Merged chunks with timestamps + configurable overlap | Raw 2-second caption cues |
| Languages | Priority list, human tracks preferred over auto-generated | First track found |
| Failures | Row with a readable error, and you are never charged for it | Charged anyway, or the run dies |
Why the throttling part matters
YouTube's caption host (youtube.com/api/timedtext) rate-limits per IP address, and independently of the rest of the API. Once an IP is throttled, every caption format and every header combination keeps returning HTTP 429 — we measured this: 15 request variants, all blocked, for over 40 minutes on the same IP.
Most scrapers treat that as "retry and hope". This one treats a 429 as burn this IP and moves to a fresh proxy session. It also starts on cheap datacenter proxies and only escalates to residential once datacenter is provably blocked — which is exactly why it can be priced below the alternatives.
Input
Paste anything YouTube-shaped into YouTube URLs:
{"videoUrls": ["https://www.youtube.com/watch?v=8S0FDjFBj8o", // watch URL"https://youtu.be/jNQXAC9IVRw", // short link"https://www.youtube.com/shorts/abcdefghijk", // Shorts"dQw4w9WgXcQ", // bare video ID"@veritasium", // whole channel"https://www.youtube.com/playlist?list=PLZHQ..." // whole playlist],"maxVideos": 500,"languages": ["en", "es"],"outputFormat": "chunks","chunkMaxChars": 1200,"chunkOverlapChars": 100}
Channels and playlists are expanded to their videos automatically, up to Max videos.
Key settings
- Preferred languages — ISO-639-1 codes in priority order. A human-made track always beats an auto-generated one in the same language.
- Allow auto-generated captions — turn off if you only want reviewed subtitles.
- Output format —
text,chunks,segments,srt,vtt, orall. - Chunk size / overlap — only used by
chunks. Caption cues are ~2 seconds long and useless for embeddings; this merges them into passages. - Concurrency — default 10. Raise for speed.
Every option
The same wording you see in the Apify console, with the JSON key for API and MCP callers.
| Option | What it does | Default |
|---|---|---|
YouTube URLs — videoUrls (required) | Videos, channels or playlists. Paste any mix of: watch URLs, youtu.be links, /shorts/, /embed/, bare 11-character video IDs, @handles, /channel/UC…, or playlist URLs. Channels and playlists are expanded into their videos automatically. | — |
Max videos — maxVideos | Hard cap on how many videos this run will process, counting videos pulled out of channels and playlists. Leave empty for no cap. | 100 |
Preferred languages — languages | ISO-639-1 codes in priority order, e.g. en, es, ko. The first language the video actually has is used. A human-made track always wins over an auto-generated one in the same language. | ["en"] |
Allow auto-generated captions — allowAutoGenerated | Fall back to YouTube's speech-recognition captions when no human-made track exists. Turn this off if you only want reviewed subtitles. | true |
Fall back to any available language — anyLanguageFallback | If none of your preferred languages exist, take whatever track the video does have instead of returning nothing. | true |
Output format — outputFormat | text = one clean paragraph string. chunks = merged passages sized for RAG/embeddings. segments = raw timed cues. srt / vtt = subtitle files. all = every field at once. | "text" |
Chunk size (characters) — chunkMaxChars | Only used by the "chunks" format. Caption cues are ~2 seconds long and useless for embeddings; this merges them into passages of about this length. | 1200 |
Chunk overlap (characters) — chunkOverlapChars | Repeat this much of the previous chunk at the start of the next one, so a sentence split across a boundary still embeds well. | 0 |
Include video metadata — includeMetadata | Add title, channel, view count, duration, publish date, keywords and thumbnail to every row. Free — it arrives in the same request as the transcript. | true |
Include videos without captions — includeEmptyResults | Emit a row with an error field for videos that have no usable transcript, instead of skipping them silently. You are never charged for these rows. | true |
Concurrency — concurrency | How many videos to fetch in parallel. Raise it for speed, lower it if you see throttling on a small proxy pool. | 10 |
Proxy — proxyConfiguration | Leave the default. YouTube throttles caption downloads per IP, so the actor starts on cheap datacenter proxies and only escalates to residential when it actually gets blocked — that escalation is what keeps the price low. | {"useApifyProxy":true} |
Output
One row per video:
{"videoId": "8S0FDjFBj8o","url": "https://www.youtube.com/watch?v=8S0FDjFBj8o","title": "The Danger of Silence","description": "Clint Smith is a teacher, poet and doctoral candidate...","channelName": "TEDx Talks","channelId": "UCsT0YIqwnpJCM-mx7-gSA4Q","channelUrl": "https://www.youtube.com/channel/UCsT0YIqwnpJCM-mx7-gSA4Q","durationSeconds": 356,"viewCount": 15641909,"publishedAt": "2014-03-07","category": "Nonprofits & Activism","keywords": ["poetry", "education"],"isLive": false,"thumbnailUrl": "https://i.ytimg.com/vi/8S0FDjFBj8o/maxresdefault.jpg","language": "en","languageName": "English","isAutoGenerated": false,"segmentCount": 128,"wordCount": 1043,"transcript": "Hear that? That is the sound of ..."}
With outputFormat: "chunks" you also get:
"chunks": [{ "start": 0.0, "end": 58.4, "text": "Hear that? ..." },{ "start": 55.1, "end": 121.7, "text": "...continues here" }]
Videos with no captions come back as a row with transcript: null and a readable error — and are never billed.
Every field
You are billed per transcript delivered, so here is everything a row can contain. Which
fields appear depends on outputFormat and includeMetadata; a metadata field is also
absent when YouTube did not publish it for that video.
| Field | When | What it is |
|---|---|---|
videoId | always | The 11-character id. |
url | always | watch?v= URL. |
language | always | Caption language code of the track that was used, e.g. "en". |
languageName | always | Its display name, e.g. "English (auto-generated)". |
isAutoGenerated | always | true when the track is YouTube speech recognition rather than human-made. |
segmentCount | always | How many timed cues the track had. |
wordCount | always | Words in the transcript. |
transcript | text / all | One clean paragraph string. null on a row that carries an error. |
chunks | chunks / all | Passages merged to your character cap, each with start, end, text. Sized for embeddings. |
segments | segments / all | The raw cues: start, duration, text. |
srt | srt / all | A complete SRT subtitle file as a string. |
vtt | vtt / all | A complete WebVTT file as a string. |
title | metadata | Video title. |
description | metadata | The full video description. |
channelName | metadata | Uploading channel's display name. |
channelId | metadata | Its UC… id. |
channelUrl | metadata | Its canonical /channel/UC… URL. |
durationSeconds | metadata | Length in seconds. |
viewCount | metadata | Views at the time of the run. |
publishedAt | metadata | Upload date. Costs one extra request per video, which is why it follows includeMetadata. |
category | metadata | YouTube's own category label. |
keywords | metadata | The uploader's tags. |
isLive | metadata | true for a live or previously-live stream. |
thumbnailUrl | metadata | Largest available thumbnail. |
publishedText | channel/playlist input | The listing page's relative date, e.g. "3 weeks ago", kept from the expansion step. |
isShort | channel/playlist input | true when the video was listed as a Short. |
tab | channel input | Which channel tab it came from: "videos", "shorts" or "live". |
error | empty rows | Why this video produced no transcript. Only written when Include videos with no captions is on. |
availableLanguages | empty rows | Caption languages the video does have, so you can widen your language list and re-run. |
Pricing
Pay per event. Beyond $0.00002 for starting a run — the platform's $0.00001 minimum, charged once per GB of memory, on 2 GB — you are only charged for a transcript that is actually delivered. Videos without captions, throttled requests, and failed rows cost you nothing.
Run it on a channel of 500 videos and you pay for the transcripts you get back, not for the attempts.
Who this is for
- AI and RAG engineers — the
chunksformat drops straight into a vector store, so a channel becomes a corpus with no transcription bill. - Content marketers with a back catalogue — a year of video becomes the raw material for posts, newsletters and show notes in one run.
- Market and competitor researchers — transcribe a rival's whole channel and search what they actually say, not what they tagged.
- Localisation teams — bulk SRT and VTT export for re-uploading or translating.
Common uses
- RAG / AI knowledge bases —
chunksformat drops straight into a vector store. - Content repurposing — turn a back catalogue into blog posts, newsletters, show notes.
- Competitor & market research — transcribe a competitor's whole channel and search it.
- SEO — extract the language your audience actually uses, at scale.
- Subtitle files — bulk SRT/VTT export for re-uploading or translating.
- Datasets — build training or analysis corpora with metadata attached.
Other Actors in this family
Same engines, same billing, no account or API key on any of them.
YouTube & video
- YouTube Scraper — No API Key, Any URL or Search — Any YouTube URL or search term in, videos out — with subtitles, comments and sponsor deals as add-ons.
- Export YouTube Comments to CSV — Replies and Likes — Every comment and reply thread, with likes, authors and creator flags.
- List Every Video on a YouTube Channel — Export to CSV — A channel's whole back catalogue plus a subscriber and RSS summary row.
- Find YouTube Sponsors — Brand Deals, Codes & Links — Which brands pay which creators, with the campaign link, the code and the timestamp.
- YouTube Search API — Bulk Results, No Quota — Many search terms at once, every result as a row, filtered before you are billed.
- Track Deleted YouTube Videos & Title Changes — What a channel quietly changed: deleted videos, rewritten titles, view velocity.
- YouTube Creator Email Finder & Sponsor Lookup — A channel list into leads: the published email, audience bands, and who already sponsors them.
- Export a YouTube Playlist to CSV — Every Video — Any playlist as a table, with each video position in it.
Search demand
- AnswerThePublic Alternative — Autocomplete Keyword API — One seed into hundreds of real keywords from Google, YouTube and Amazon autocomplete.
- Google Trends API — Today's Trending Searches, No Key — Today's trending searches by country, with traffic bands and the news behind them.
E-commerce
- Export Any Shopify Store's Products to CSV or JSON — Any Shopify catalogue: variants, SKUs, live prices, stock, images, collections.
- New Shopify Product Alerts — Competitor Drop Tracker — Only what a store launched since the last run. Scanning is free.
- Shopify Store Email Finder — Qualified B2B Leads — A domain list into qualified leads: contact email, size, price band, and whether the shop still trades.
- Website Tech Stack & Email Finder for B2B Lists — Any domain list into leads: contact email, what the site runs on, and the marketing tags it carries.
Hiring
- Greenhouse, Lever & Ashby Job Scraper — No API Key — Paste a company domain, get its open roles from Greenhouse, Ashby, Lever or SmartRecruiters.
- Ghost Job Detector — Track Reposts, Closures & Edits — What changed on a careers page: opened, closed, quietly reposted, or a ghost job.
Run it from code
Nothing here needs a login to the source, only your Apify token.
HTTP — start a run and wait for the rows:
curl -X POST "https://api.apify.com/v2/acts/gganbukim~youtube-transcript-scraper/run-sync-get-dataset-items?token=$APIFY_TOKEN" \-H "content-type: application/json" \-d @input.json
JavaScript
import { ApifyClient } from 'apify-client';const client = new ApifyClient({ token: process.env.APIFY_TOKEN });const run = await client.actor('gganbukim/youtube-transcript-scraper').call(input);const { items } = await client.dataset(run.defaultDatasetId).listItems();
Python
from apify_client import ApifyClientclient = ApifyClient(os.environ["APIFY_TOKEN"])run = client.actor("gganbukim/youtube-transcript-scraper").call(run_input=input)items = client.dataset(run["defaultDatasetId"]).list_items().items
Scheduled or event-driven — attach a schedule to run it on a cron, or a webhook to push each finished run into your own endpoint. It also connects through Apify's Zapier, Make, n8n and LangChain integrations, and is reachable from an MCP server if you are driving it from an agent.
Standby / API mode — the run above is synchronous: one call in, rows out, no polling. That is the shape to use if you are calling this per request rather than in a batch.
Errors, limits and what you are charged for
- You pay for delivered rows only. A row your filters removed, a page that failed, a retry — none of it is billed. Starting a run costs $0.00001: the platform minimum, charged once per gigabyte, and this Actor runs on 512 MB.
- A run that delivers nothing still costs the start fee and nothing else. If the input resolved to zero items, the run fails loudly with the reason rather than finishing green on an empty dataset.
- Blocking is handled by changing address, not by waiting. The Actor starts on cheap datacenter proxies and moves up only after a tier has actually been refused several times in a row, then drops back down once the cheap tier answers cleanly again. You are not paying for residential bandwidth that was never needed.
- Rate limits belong to the source, not to this Actor. Very large inputs are worked through in batches; the run reports how many items succeeded, were filtered, and failed, so a partial result is never presented as a complete one.
- Dataset retention follows your Apify plan. Export what you need, or push it out with a webhook, if you want it past that window.
Is this legal?
This Actor reads pages and public endpoints that anyone can open in a browser without an account. It does not log in, does not defeat a paywall, and does not touch anything behind authentication.
Scraping public data is broadly lawful in the US and the EU, and courts have repeatedly said so — but "public" is not the same as "unrestricted", and what you may then do with the data is a separate question from whether you may collect it. Personal data pulls in the GDPR and similar regimes whatever the source, so if your rows contain people, you need a lawful basis for keeping them.
Apify publishes a fuller treatment in Is web scraping legal? and an ethical scraping guide. None of this is legal advice; if the use is commercial and the data is personal, ask someone qualified.
Something wrong, or missing?
Open an issue on the Actor's Issues tab — it goes straight to the developer and is the fastest route. Include the run ID; it carries the input and the log, which is usually enough to reproduce the problem without another round trip.
Sources change without warning, and a field that quietly goes null is worth reporting even if the run succeeded. A broken parser looks exactly like a quiet day in the data until someone says so.
FAQ
Will I get blocked, or my account banned? There is no account to ban — this Actor never signs in and sends no cookies. It reads the same caption endpoints the player uses, on cheap datacenter proxies, escalating to residential only once datacenter is provably blocked. YouTube signals throttling with an HTTP 200 and an error body rather than an error code, which is the trap that silently halves most scrapers' results; this one detects it by reason and rotates.
Does this need a YouTube API key? No. The official Data API will not return captions for videos you do not own; this does not use it.
What if a video has no captions?
You get a row with error explaining why, plus availableLanguages when there were tracks in other languages. You are not charged.
Can I get auto-translated captions?
Not currently. YouTube removed the tlang translation parameter from the caption endpoint. Pull the original language and translate downstream.
How fast is it? Concurrency 10 by default. A 500-video channel typically finishes in a few minutes.
Can I run it on a schedule? Yes — use Apify Schedules, or call it from the API. It is also available over MCP for AI agents.
Is scraping YouTube transcripts legal? This reads publicly available caption data, the same data the YouTube web player requests. You are responsible for how you use the output, including copyright in the underlying content.
How much does 1,000 transcripts cost? $2.00, plus $0.00002 for the run itself. Videos with no captions are not billed at all, so a list padded with them costs less than you budgeted rather than more.
Can I export the results to Excel or Google Sheets? Yes. Every run's dataset downloads as CSV, Excel, JSON, XML or RSS from the Storage tab, or straight from the API if you want a live link a spreadsheet can pull.
Can I connect it to Zapier, Make or n8n? Yes — Apify publishes integrations for all three, plus webhooks that fire when a run finishes. A common setup is a schedule here and a webhook into your own database or Slack.
Do I need to write code? No. Fill the form in the console and press Start. If you do want code, the Apify client libraries for Python and JavaScript call this the same way, and it is available over MCP so an AI agent can call it directly.
Integrations
Works with Apify's standard integrations: webhooks, Zapier, Make, n8n, Google Sheets, Airtable, LangChain, and the Apify MCP server for AI agents. Every run's dataset is available as JSON, CSV, Excel or XML via the API.