YouTube Transcript Scraper — Subtitles & Captions API avatar

YouTube Transcript Scraper — Subtitles & Captions API

Pricing

from $1.20 / 1,000 transcripts

Go to Apify Store
YouTube Transcript Scraper — Subtitles & Captions API

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 $1.20 / 1,000 transcripts

Rating

0.0

(0)

Developer

Anuar Bakty

Anuar Bakty

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

2 days ago

Last modified

Security

Limited permissions

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, .vtt and .txt files 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?

GroupFields
Transcripttranscript (lines with start, duration, end, text, optional words), text, paragraphs, chunks, timestampedText, srt, vtt, xml, fileUrls, segmentCount
Languagelanguage, languageName, captionType (manual / auto), isAutoGenerated, languageMatch (requested / fallback / original / all), availableLanguages, requestedLanguages
VideovideoId, url, title, description, keywords, category, thumbnailUrl, durationSeconds, duration, publishedAt, publishDate, isShort, isLive, wasLive, isUnlisted, isFamilySafe
EngagementviewCount, likeCount, commentCount
ChannelchannelName, channelId, channelUrl, channelHandle, channelThumbnailUrl, subscriberCount
Runstatus, 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 video transcripts

  1. Paste one or more links or video ids into YouTube links or video ids, or type Search words.
  2. Set Languages (default en; the original language is taken when none of yours exists).
  3. Choose Transcript formats and, for channels and searches, Videos per channel tab, playlist or search.
  4. 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.

SRT, VTT and TXT 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. listLanguagesOnly returns the details and languages of any number of videos without charge.
  • Spending limits that hold. maxItems stops the run after that many transcripts, and the run's cost limit in Apify is respected to the cent.

Input

FieldWhat it doesDefault
urlsVideos, Shorts, channels, channel tabs, playlists, search pages, video ids, @handles—
searchTermsSearch words, one search per line—
languagesLanguage codes or names in order of preference; en matches en-US and en-GB["en"]
fallbackToAnyLanguageTake the video's original language when none of yours existstrue
captionTypemanualFirst, autoFirst, manualOnly, autoOnlymanualFirst
allLanguagesOne row per caption language of the videofalse
listLanguagesOnlyOnly details and languages, no transcript, freefalse
outputFormatsAny of segments, text, paragraphs, chunks, timestampedText, srt, vtt, xml["segments", "text"]
chunkWordsWords per chunk in the chunks format150
saveFilesAlso save .srt, .vtt, .txt files and put their links in fileUrlsfalse
removeNonSpeechRemove [Music], [Applause], music notes and [ __ ]true
wordTimestampsStart and end of every word (auto-generated captions)false
includeDetailsExact publish time, likes, category, Shorts flag, @handletrue
includeEngagementComment count and channel subscriberstrue
maxVideosPerSourceVideos per channel tab, playlist or search; 0 = all50
channelTabsvideos, shorts, streams["videos"]
publishedAfter, publishedBefore2026-09-01, or 30 days, 2 weeks, 6 months—
maxItemsMost transcripts in the whole run; 0 = no limit0
includeErrorRowsFree rows for videos without a transcripttrue
deduplicateEach video once per runtrue
failIfAllInputsFailEnd the run as failed when no transcript came, for alertsfalse
strictInputStop before the first request on an unknown field nametrue
runTagText copied into every row—
proxyConfigurationLeave as it is; the Actor picks addresses itselfApify 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

statuserrorCodeMeaningCharged
ok—A transcriptyes
listed—Details and languages only (listLanguagesOnly)no
no_transcriptNO_CAPTIONSThe video has no captions at allno
no_transcriptLANGUAGE_NOT_FOUNDNone of your languages; availableLanguages lists what existsno
no_transcriptNO_MANUAL_CAPTIONS, NO_AUTO_CAPTIONSNot the kind of captions asked forno
no_transcriptEMPTY_TRANSCRIPTThe track holds only sound labelsno
failedPRIVATE, REMOVED, UNAVAILABLE, AGE_RESTRICTED, MEMBERS_ONLY, LOGIN_REQUIREDYouTube does not show the video to visitorsno
failedUPCOMING, LIVE_NOW, LIVE_RECORDING_UNAVAILABLELive and scheduled videosno
failedBLOCKED, REGION_BLOCKED, FETCH_FAILEDYouTube refused every address tried; retryable: trueno
failedCHANNEL_NOT_FOUND, PLAYLIST_NOT_FOUND, NO_VIDEOS, INVALID_INPUTThe input line points at nothingno

YouTube transcript API and integrations

  • n8n and Make: use the Apify node or module, Actor anuarbakty/youtube-transcript-scraper, input { "urls": ["{{ video link }}"] }, then read text or transcript from the dataset items. One video per call costs no more than one video in a batch.
  • Python:
from apify_client import ApifyClient
client = 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.

Apify's two-minute step-by-step video shows how to configure the MCP server:

Run it on a schedule

In Apify Console, open Schedules, click Create new, choose how often, and add this Actor with one of the inputs below, or a task you saved. Set Published on or after to the schedule's interval, as in each row.

How oftenInputWhat you get
Every dayChannel links, "channelTabs": ["videos", "shorts"], "publishedAfter": "1 day", "maxVideosPerSource": 0Transcripts of the new videos and Shorts of the channels you follow, such as clinics and health channels, in your n8n or Make flow
Every week"searchTerms": ["physical therapy after knee replacement"], "publishedAfter": "7 days", "maxVideosPerSource": 20What this week's videos say about a topic; n8n can send the text to ChatGPT or Claude for a digest
Every weekA podcast or lecture channel, "outputFormats": ["chunks"], "publishedAfter": "7 days", "maxVideosPerSource": 0New chunks with links to the exact second, for your Python or JavaScript code to add to a vector database
Every monthChannel links, "listLanguagesOnly": true, "publishedAfter": "30 days", "maxVideosPerSource": 0Free rows with the caption languages of the month's videos, as Excel or CSV, for accessibility and translation work

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

  • Instagram Reels Transcript Generator: Instagram reels to text by link, account or hashtag: transcript, SRT and VTT subtitles, hooks, no login.
  • 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.
  • Google Ads Library Scraper: Google ads of any brand or website from the Google Ads Transparency Center: ad text read even from pictures, variations, countries, EU reach and targeting, no login.
  • Pinterest Search Scraper: Pinterest pins, boards and profiles without login, with real pin links, saves, repins and comments, plus Pinterest Trends and search suggestions.

FAQ

How do I get a transcript of a YouTube video? Paste the video's link, or just its 11-character id, into YouTube links or video ids and click Start. The row holds the full transcript (the video's script) in text and the timed lines in transcript; copy it or download it as JSON, CSV or Excel. For more videos, paste one link per line, or give a channel, a playlist or search words.

Is there an official YouTube transcript API? Why use this scraper instead? YouTube Data API v3 has a captions resource: captions.list lists a video's caption tracks without their text, and captions.download returns one track as SRT, VTT, SBV, SCC or TTML. Both need OAuth authorization, the download works only for a user with permission to edit the video, and each download costs 200 units of the default 10,000-unit daily quota. So the official API is made for videos you manage. This Actor works on other people's public videos, channels, playlists and searches, needs no Google Cloud project, OAuth or quota, and puts the transcript and the video's details in one row.

Can I use it as a YouTube transcript generator? Yes. Give it one video link or many, a channel, a playlist or search words, and it makes each video's transcript from its captions, the author's or YouTube's auto-generated ones, in the language you choose: plain text, readable paragraphs, [1:23]-style timestamped text, SRT or VTT. The same input runs from n8n, Make, the API or an AI agent.

How do I download YouTube subtitles or captions as SRT or VTT? Add srt or vtt to Transcript formats to get them inside each row, or turn on Save .srt, .vtt and .txt files with download links to get a link to each file in fileUrls. Pick the language in Languages, or turn on Every language the video has to get all of them in one run.

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.

Can I get the transcripts of a whole YouTube channel? Yes. Paste the channel link or @handle and set Videos per channel tab, playlist or search to 0 to take every video, newest first. Add shorts and streams to Channel tabs for Shorts and past live streams, and set Published on or after or Published on or before for a date range. For a playlist, paste its link the same way.

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.