YouTube Transcript Scraper — Subtitles & Captions API
Pricing
from $3.25 / 1,000 transcripts
YouTube Transcript Scraper — Subtitles & Captions API
Scrape YouTube transcripts, subtitles and captions from videos, Shorts, channels, playlists and search. Any language with fallback; text, timestamps, SRT, VTT or chunks for AI, plus title, views, likes, date and channel. Works with MCP, n8n and Make. No captions, no charge.
Pricing
from $3.25 / 1,000 transcripts
Rating
0.0
(0)
Developer
Anuar Bakty
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
21 hours ago
Last modified
Categories
Share
Scrape the transcript of any YouTube video, Short, channel, playlist or search, with the video's details in the same row. Paste links in any form, pick your languages, and get clean text, timestamped segments, paragraphs, chunks for AI, SRT, VTT or XML. You pay only for transcripts delivered: videos without captions, private or removed videos and blocked requests are free rows, and there is no start fee.
What does YouTube Transcript Scraper do?
- Takes every kind of YouTube link. Videos (
watch?v=,youtu.be,/live/,/embed/, mobile and music links, bare ids), Shorts, channels (@handle,/channel/UC…,/c/,/user/), channel tabs (/shorts,/streams), playlists, search pages and plain search words — all in one list. - Gets the captions you ask for. Author captions or YouTube's auto-generated ones, in your languages in order of preference, with a fallback to the language spoken in the video. Each row says which language and kind it got and why.
- Returns the formats you need. Timestamped segments, one plain text string, readable paragraphs, chunks for AI with a link to their second of the video,
[1:23]-style timestamped text, SRT, VTT and XML, with[Music]-style labels removed and'turned back into characters. Word-level timestamps for auto-generated captions. Optional.srt,.vttand.txtfiles with download links. - Adds the video details. Title, channel, @handle, channel avatar, subscribers, exact publish time, duration, views, likes, comment count, category, tags, description, thumbnail, Shorts and live flags.
- Reads 8 videos at a time and moves on to a fresh address by itself whenever YouTube refuses one.
- Explains every video it could not transcribe in a free row with a code (
NO_CAPTIONS,LANGUAGE_NOT_FOUND,PRIVATE,AGE_RESTRICTED…), a plain-English message, the languages the video does have, and whether running it again may help. - Runs inputs made for other transcript Actors. Field names of the most used ones (
youtube_url,videoUrls,startUrls,channel_url,max_videos,transcript_type,output_formats,language…) are read as they are, so a saved input or an n8n flow keeps working.
What YouTube data can you extract?
| Group | Fields |
|---|---|
| Transcript | transcript (lines with start, duration, end, text, optional words), text, paragraphs, chunks, timestampedText, srt, vtt, xml, fileUrls, segmentCount |
| Language | language, languageName, captionType (manual / auto), isAutoGenerated, languageMatch (requested / fallback / original / all), availableLanguages, requestedLanguages |
| Video | videoId, url, title, description, keywords, category, thumbnailUrl, durationSeconds, duration, publishedAt, publishDate, isShort, isLive, wasLive, isUnlisted, isFamilySafe |
| Engagement | viewCount, likeCount, commentCount |
| Channel | channelName, channelId, channelUrl, channelHandle, channelThumbnailUrl, subscriberCount |
| Run | status, errorCode, message, retryable, inputType, input, position, scrapedAt, runTag |
What can you use YouTube transcripts for?
- AI and RAG. Feed lectures, interviews and product videos to ChatGPT, Claude or a vector database; the timestamps let an answer link to the exact second.
- Content research. Read what a channel says across its last 50 videos without watching them: health channels, clinics, physical therapists, software tutorials, conference talks.
- Subtitles for editing. SRT and VTT files ready for Premiere, DaVinci Resolve, CapCut or a web player.
- SEO and repurposing. Turn videos into articles, show notes, summaries and quotes.
- Monitoring. Schedule a run on a channel with "published after: 1 day" to get each new video's transcript.
- Accessibility and translation work. See which languages a channel already offers, for free, before ordering captions.
How to scrape YouTube transcripts
- Paste one or more links or video ids into YouTube links or video ids, or type Search words.
- Set Languages (default
en; the original language is taken when none of yours exists). - Choose Transcript formats and, for channels and searches, Videos per channel tab, playlist or search.
- Click Start. Each video becomes one row; download it as JSON, CSV, Excel or HTML, or read it through the API.
One video
{ "urls": ["https://www.youtube.com/watch?v=arj7oStGLkU"] }
Many videos at once, with SRT
{"urls": ["https://youtu.be/arj7oStGLkU", "https://www.youtube.com/shorts/eW5Oi91m4SY", "jNQXAC9IVRw"],"outputFormats": ["segments", "text", "srt"]}
Spanish first, then English, author captions only
{ "urls": ["https://www.youtube.com/watch?v=arj7oStGLkU"], "languages": ["es", "en"], "captionType": "manualOnly" }
The last 30 days of a channel, videos and Shorts
{ "urls": ["https://www.youtube.com/@TED"], "channelTabs": ["videos", "shorts"], "publishedAfter": "30 days", "maxVideosPerSource": 0 }
A playlist
{ "urls": ["https://www.youtube.com/playlist?list=PL8dPuuaLjXtNlUrzyH5r6jN9ulIgZBpdo"], "maxVideosPerSource": 100 }
A search, this week only
{ "searchTerms": ["physical therapy after knee replacement"], "publishedAfter": "7 days", "maxVideosPerSource": 20 }
Chunks for ChatGPT, Claude or a vector database
{ "urls": ["https://www.youtube.com/watch?v=arj7oStGLkU"], "outputFormats": ["chunks"], "chunkWords": 200 }
Each chunk comes with start, end, wordCount and a url that opens the video at that second, so an AI answer can cite the moment it came from.
Subtitle files to download
{ "urls": ["https://www.youtube.com/watch?v=arj7oStGLkU"], "saveFiles": true }
The row gets fileUrls with links to the .srt, .vtt and .txt files.
Which languages does a video have? (free)
{ "urls": ["https://www.youtube.com/watch?v=arj7oStGLkU"], "listLanguagesOnly": true }
Every language of a video
{ "urls": ["https://www.youtube.com/watch?v=arj7oStGLkU"], "allLanguages": true, "outputFormats": ["text"] }
How much does it cost to scrape YouTube transcripts?
You pay per transcript delivered; see the Pricing tab for the price on your plan.
- No start fee. One video per run costs the same as one video in a batch, which matters for n8n, Make and API calls made video by video.
- Free rows. Videos without captions, without your language, private, removed, age-restricted, members-only, upcoming, or blocked after every retry cost nothing.
- Video details are included in the transcript price: date, likes, comment count and subscribers are not extra.
- Free language lists.
listLanguagesOnlyreturns the details and languages of any number of videos without charge. - Spending limits that hold.
maxItemsstops the run after that many transcripts, and the run's cost limit in Apify is respected to the cent.
Input
| Field | What it does | Default |
|---|---|---|
urls | Videos, Shorts, channels, channel tabs, playlists, search pages, video ids, @handles | — |
searchTerms | Search words, one search per line | — |
languages | Language codes or names in order of preference; en matches en-US and en-GB | ["en"] |
fallbackToAnyLanguage | Take the video's original language when none of yours exists | true |
captionType | manualFirst, autoFirst, manualOnly, autoOnly | manualFirst |
allLanguages | One row per caption language of the video | false |
listLanguagesOnly | Only details and languages, no transcript, free | false |
outputFormats | Any of segments, text, paragraphs, chunks, timestampedText, srt, vtt, xml | ["segments", "text"] |
chunkWords | Words per chunk in the chunks format | 150 |
saveFiles | Also save .srt, .vtt, .txt files and put their links in fileUrls | false |
removeNonSpeech | Remove [Music], [Applause], music notes and [ __ ] | true |
wordTimestamps | Start and end of every word (auto-generated captions) | false |
includeDetails | Exact publish time, likes, category, Shorts flag, @handle | true |
includeEngagement | Comment count and channel subscribers | true |
maxVideosPerSource | Videos per channel tab, playlist or search; 0 = all | 50 |
channelTabs | videos, shorts, streams | ["videos"] |
publishedAfter, publishedBefore | 2026-09-01, or 30 days, 2 weeks, 6 months | — |
maxItems | Most transcripts in the whole run; 0 = no limit | 0 |
includeErrorRows | Free rows for videos without a transcript | true |
deduplicate | Each video once per run | true |
failIfAllInputsFail | End the run as failed when no transcript came, for alerts | false |
strictInput | Stop before the first request on an unknown field name | true |
runTag | Text copied into every row | — |
proxyConfiguration | Leave as it is; the Actor picks addresses itself | Apify Proxy |
Output
One row per transcript (and one free row per video without one). A shortened example:
{"status": "ok","videoId": "arj7oStGLkU","url": "https://www.youtube.com/watch?v=arj7oStGLkU","title": "Inside the Mind of a Master Procrastinator | Tim Urban | TED","channelName": "TED","channelId": "UCAuUUnT6oDeKwE6v1NGQxug","channelUrl": "https://www.youtube.com/channel/UCAuUUnT6oDeKwE6v1NGQxug","channelHandle": "@TED","channelThumbnailUrl": "https://yt3.ggpht.com/ytc/AIdro_koIFcCOrvh0KThLNOiazAIDu6hcs…","subscriberCount": 27900000,"publishedAt": "2016-04-06T16:59:35.000Z","publishDate": "2016-04-06","durationSeconds": 844,"duration": "14:04","viewCount": 62071153,"likeCount": 2055271,"commentCount": 79000,"category": "People & Blogs","keywords": ["TED Talk", "TED Talks", "Tim Urban", "procrastination"],"description": "Tim Urban knows that procrastination doesn't make sense, but he's never been able to shake his habit of waiting until th…","thumbnailUrl": "https://i.ytimg.com/vi/arj7oStGLkU/sddefault.jpg","isShort": false,"isLive": false,"wasLive": false,"isUnlisted": false,"isFamilySafe": true,"language": "en","languageName": "English","captionType": "manual","isAutoGenerated": false,"languageMatch": "requested","availableLanguages": [{ "code": "ar", "name": "Arabic", "type": "manual", "isDefault": false },{ "code": "en", "name": "English", "type": "manual", "isDefault": true },{ "code": "en", "name": "English (auto-generated)", "type": "auto", "isDefault": false }],"segmentCount": 286,"transcript": [{ "start": 12.645, "duration": 1.37, "end": 14.015, "text": "So in college," },{ "start": 15.349, "duration": 1.564, "end": 16.913, "text": "I was a government major," },{ "start": 16.937, "duration": 2.462, "end": 19.399, "text": "which means I had to write a lot of papers." }],"text": "So in college, I was a government major, which means I had to write a lot of papers. Now, when a normal student writes a paper…","paragraphs": null,"chunks": null,"timestampedText": null,"srt": null,"vtt": null,"xml": null,"fileUrls": null,"requestedLanguages": ["en"],"errorCode": null,"message": null,"retryable": null,"inputType": "video","input": "https://www.youtube.com/watch?v=arj7oStGLkU","position": null,"scrapedAt": "2026-10-17T20:10:00.000Z","runTag": null}
Every row has the same fields in the same order, so a spreadsheet or an n8n flow reads transcripts and free rows alike. A run summary by input is saved in the key-value store as SUMMARY.
Status and error codes
status | errorCode | Meaning | Charged |
|---|---|---|---|
ok | — | A transcript | yes |
listed | — | Details and languages only (listLanguagesOnly) | no |
no_transcript | NO_CAPTIONS | The video has no captions at all | no |
no_transcript | LANGUAGE_NOT_FOUND | None of your languages; availableLanguages lists what exists | no |
no_transcript | NO_MANUAL_CAPTIONS, NO_AUTO_CAPTIONS | Not the kind of captions asked for | no |
no_transcript | EMPTY_TRANSCRIPT | The track holds only sound labels | no |
failed | PRIVATE, REMOVED, UNAVAILABLE, AGE_RESTRICTED, MEMBERS_ONLY, LOGIN_REQUIRED | YouTube does not show the video to visitors | no |
failed | UPCOMING, LIVE_NOW, LIVE_RECORDING_UNAVAILABLE | Live and scheduled videos | no |
failed | BLOCKED, REGION_BLOCKED, FETCH_FAILED | YouTube refused every address tried; retryable: true | no |
failed | CHANNEL_NOT_FOUND, PLAYLIST_NOT_FOUND, NO_VIDEOS, INVALID_INPUT | The input line points at nothing | no |
Integrations and API
- n8n and Make: use the Apify node or module, Actor
anuarbakty/youtube-transcript-scraper, input{ "urls": ["{{ video link }}"] }, then readtextortranscriptfrom the dataset items. One video per call costs no more than one video in a batch. - Python:
from apify_client import ApifyClientclient = ApifyClient("<YOUR_API_TOKEN>")run = client.actor("anuarbakty/youtube-transcript-scraper").call(run_input={"urls": ["https://www.youtube.com/watch?v=arj7oStGLkU"]})for row in client.dataset(run["defaultDatasetId"]).iterate_items():print(row["status"], row["language"], row["text"][:200] if row["text"] else row["message"])
- JavaScript:
import { ApifyClient } from 'apify-client';const client = new ApifyClient({ token: '<YOUR_API_TOKEN>' });const run = await client.actor('anuarbakty/youtube-transcript-scraper').call({ urls: ['https://www.youtube.com/watch?v=arj7oStGLkU'] });const { items } = await client.dataset(run.defaultDatasetId).listItems();console.log(items[0].text);
- AI agents (MCP): connect Apify's MCP server (
https://mcp.apify.com) to Claude, Cursor, VS Code or ChatGPT and ask "get the transcript of this YouTube video"; the agent calls this Actor and reads the rows.
Is it legal to scrape YouTube transcripts?
The Actor reads only what YouTube shows any visitor who is not signed in: public captions and public video details. It does not sign in, does not download video or audio, and does not touch private or members-only content. How you use the transcripts is up to you; check YouTube's terms and the copyright of the channels you work with, and ask a lawyer when in doubt.
More from this developer
- Facebook Ads Library Scraper: ads from the Meta Ad Library by keyword, brand, page or Instagram account, with creatives, days running and EU reach.
- Threads Scraper: posts, all replies and profiles from Threads without login, keyword search and only-new monitoring.
- 2GIS Places Scraper: businesses from 2GIS (Russia, Kazakhstan, Central Asia, UAE) with phones, WhatsApp, Telegram, emails and websites.
- 2GIS Reviews Scraper: 2GIS reviews with star, topic and date filters and only-new monitoring.
FAQ
What if a video has no captions? You get a free row with status: "no_transcript" and errorCode: "NO_CAPTIONS", plus the video's details.
What if my language is missing? With fallbackToAnyLanguage on (the default), the original language comes and languageMatch says fallback. With it off, a free row lists availableLanguages so you can choose.
Author or auto-generated captions? Author captions come first by default; set captionType to autoFirst, manualOnly or autoOnly to change that. captionType in each row says which one came.
Does it work for Shorts and live streams? Yes: Shorts links, a channel's Shorts tab, and recordings of past streams. A stream that is still live gives a free LIVE_NOW row; run it again once it ends.
How do I get only new videos of a channel? Schedule the Actor with the channel link and publishedAfter set to the schedule's interval, for example 1 day.
Can I use inputs from another YouTube transcript Actor? Yes. Field names of the most used transcript Actors are read as they are. An unknown field stops the run before any charge and says which field it was, so a limit never goes unnoticed.
Is there a limit on videos per run? No fixed one. Use maxVideosPerSource per channel, playlist or search, and maxItems for the whole run.
Something does not work? Open an issue on the Actor's Issues tab and paste the link to the run. A run linked in an issue opens to the developer automatically: its log, input and results, and nothing else in your account. To share every run of this Actor instead, turn on Share run data with developers in Apify Console under Settings → Login & Privacy.