YouTube Transcript Scraper — Subtitles & Captions API avatar

YouTube Transcript Scraper — Subtitles & Captions API

Pricing

from $3.25 / 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 $3.25 / 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

21 hours ago

Last modified

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 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.

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

Integrations and API

  • 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.

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.