YouTube Transcripts API - Original Spoken Language
Pricing
Pay per event
YouTube Transcripts API - Original Spoken Language
YouTube transcripts in the language actually spoken: right on 44 of 45 videos in our published test, none wrong, vs 31 for the top 3 Store tools. Subtitles and captions with timestamps from videos, Shorts, playlists and channels. $2 per 1,000; you pay only for correct ones.
Pricing
Pay per event
Rating
0.0
(0)
Developer
nnrbzz
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
20 hours ago
Last modified
Categories
Share
YouTube Transcript & Subtitle API - Original Language
Get YouTube transcripts, subtitles and captions in the language actually spoken, from videos, Shorts, playlists and whole channels, with timestamps and LLM-ready chunks. Other tools return the first caption track, often a translation, or need the language named in advance; this one finds the spoken language itself, checks it against the text, and charges only for correct transcripts. Paste one YouTube link and click Start: at $2 per 1,000, Apify's free plan's $5 monthly credit covers 2,500 transcripts.
What does it do?
- Returns the spoken language, no language code needed. In our published test it was right on 44 of 45 captioned videos and wrong on none (the 45th came back free as "language unknown"). The top 3 Store tools each got 31. See the comparison.
- Checks every transcript's language against its text before you're charged. When YouTube's auto-caption label is wrong (English speech labelled Dutch, say), you get the language actually spoken, flagged as corrected.
- Charges only for correct transcripts. A video with no captions, one that fails, or one whose spoken language can't be named still gets a row saying why. That row is free.
- Takes videos, Shorts, playlists and channels in bulk, mixed in one run.
- Gives timestamps and ~300-word chunks ready to embed, quote or feed to an LLM.
- Pro adds an English translation and a 5-point summary with 3 topics.
It works through the Apify API, on a schedule, in Claude, Cursor and ChatGPT through Apify's MCP server, and in n8n, Make and Zapier.
Use cases
- RAG and knowledge bases: load a whole channel as timestamped chunks you can cite.
- Multilingual content research: compare what Spanish, Japanese or Hindi creators say, in their own words, not a machine translation.
- Repurposing videos: turn talks and podcasts into blog posts, newsletters and social posts.
- Competitor and brand monitoring: read every new upload from the channels you follow.
- Language datasets: collect captions labelled with a language that has been checked against the text.
- AI agents that need clean transcripts: a stable
statusanderror_codeon every row, so an agent knows what happened.
What data do you get?
| Data | Fields | |
|---|---|---|
| 📝 | Full transcript text | text, word_count, char_count |
| ⏱️ | Caption lines with start time and duration | segments |
| 🧩 | ~300-word chunks with start and end times | chunks |
| 🗣️ | Spoken language and caption language | spoken_language, caption_language, caption_language_name |
| ✅ | Language check against the text | language_check, language_detected, language_corrected, language_label_youtube |
| 🤖 | Auto-generated or translated captions | is_auto_generated, is_translated, language_signal |
| 🌐 | Every caption track on the video | available_languages |
| 🎬 | Video details | video_id, url, title, channel, channel_id, duration_s |
| 🚦 | Outcome and charge | status, error_code, error, charged_event, attempts_used, source |
| ✨ | Pro: English translation and summary | translation_en, summary, pro_status, model_cost_usd |
How to get YouTube transcripts
- Create a free Apify account.
- Open this actor and click Try for free.
- Paste video, Shorts, playlist or channel links (or video IDs).
- Click Start.
- Download the results as JSON, CSV or Excel, or get them through the API.
An empty input runs one example video, so you can see a real row first.
How much does it cost to get YouTube transcripts?
| Price | Per 1,000 videos | Each | Charged when |
|---|---|---|---|
| Transcript | $2 per 1,000 | $0.002 | the transcript is delivered |
| Transcript + Pro | $12 per 1,000 | $0.012 | Pro is on and the English translation and summary are both delivered |
| Failed, no captions, language unknown | free | $0 | never |
| Run start | free | $0 | never: you pay nothing for runs where no transcript is delivered |
Free plan: Apify's $5 monthly credit covers 2,500 transcripts, or about 415 with Pro.
Examples:
- A 100-video playlist: $0.20.
- 1,000 videos from 10 channels: $2 (with Pro: $12).
- 10,000 videos: $20.
Input
One video (the prefilled example):
{ "videos": ["https://www.youtube.com/watch?v=aircAruvnKk"] }
A playlist:
{ "playlists": ["https://www.youtube.com/playlist?list=PLZHQObOWTQDNU6R1_67000Dx_ZCJB-3pi"], "maxVideosPerSource": 50 }
A channel's newest uploads:
{ "channels": ["https://www.youtube.com/@3blue1brown"], "maxVideosPerSource": 20 }
| Field | Default | What it does |
|---|---|---|
videos | — | Watch, youtu.be, shorts, embed, live and mobile URLs, or 11-character IDs. A video given twice is fetched and charged once. |
playlists | [] | Any URL with list=, or a playlist ID. |
channels | [] | @handle, /channel/UC…, /c/…, /user/…, or a UC… ID. Newest uploads first, including Shorts and past live streams. |
maxVideosPerSource | 100 | Videos per playlist or channel, up to 1,000. |
originalLanguageOnly | true | Strict mode: when YouTube gives no signal for the spoken language, or has no captions in it, you get a free error row, not a guess. Turn it off to get the best other track. |
preferredLanguage | empty | Empty: the spoken language. A code such as es, ja or pt-BR: that language instead. Human captions come first, then auto-generated ones, then YouTube's own translation (flagged is_translated: true). If none exists, you get a free language_unavailable row. |
pro | false | English translation and summary (see Pro). |
includeSegments | true | Each caption line with its start and duration. Turning it off roughly halves the row size, and text and chunks stay. |
maxAttempts | 10 | Attempts per video, each on a fresh proxy IP. |
concurrency | 10 | Videos fetched in parallel. |
An empty input ({}) runs the example video above, charged as one transcript when delivered.
If YouTube's playlist listing can't be read, the actor falls back to the public feed, which lists only the newest 15 videos. The run log and the OUTPUT record say how many videos each source gave.
Output
One dataset row per video. A Korean video with human Chinese, English, Japanese and Spanish translations (the Store leader returns Chinese here):
{"video_id": "1qOJvWakMz0","url": "https://www.youtube.com/watch?v=1qOJvWakMz0","title": "…","channel": "BANGTANTV","channel_id": "UC…","duration_s": 1307,"status": "ok","error_code": null,"spoken_language": "ko","caption_language": "ko","caption_language_name": "Korean","is_auto_generated": false,"is_translated": false,"language_signal": "single_auto_track","language_check": "verified","language_detected": "ko","language_corrected": false,"language_label_youtube": null,"available_languages": ["zh", "en", "ja", "ko", "ko:auto", "es"],"word_count": 1758,"text": "…the whole transcript, once…","segments": [{ "start": 0.4, "dur": 3.1, "text": "…" }],"chunks": [{ "start": 0.4, "end": 131.9, "text": "…about 300 words…" }],"attempts_used": 1,"source": null,"error": null,"charged_event": "transcript"}
char_count (left out above) follows word_count.
A row that isn't delivered is free, and says why:
{ "video_id": "…", "status": "no_captions", "error_code": "no_captions", "text": null, "chunks": [], "error": "this video has no captions", "charged_event": null }
Pro
Set "pro": true. Each delivered row also gets:
{"pro_status": "ok","translation_en": "…English translation…","translation_note": null,"summary": { "bullets": ["…", "…", "…", "…", "…"], "topics": ["…", "…", "…"] },"models": { "translation": "deepseek/deepseek-v4-flash", "summary": "anthropic/claude-haiku-5.5" },"model_cost_usd": 0.0029,"charged_event": "transcript-pro"}
- English transcripts get no translation call. This covers a video spoken in English, and one you asked for in English with
preferredLanguage.translation_enisnull,translation_notesays why, and the summary is still made. - Long videos: transcripts over 10,000 words (Chinese and Japanese: characters ÷ 2), roughly over an hour of speech, get no translation or summary. You get the transcript at the core price ($0.002), with
pro_status: "skipped_too_long"andpro_error_code: "too_long_for_pro". - If a model fails: you get the transcript at the core price, with
pro_status: "failed",pro_error_code: "model_error", and any part that worked. - The models were chosen in blind quality tests. DeepSeek V4 Flash matched the best translator we tested, at about half the cost. Claude Haiku 5.5 was the only summariser with no factual errors.
Field notes
status:ok,no_captionsorerror.error_codeisnullexactly whenstatusisok.spoken_language: the language spoken in the video, as YouTube signals it.nullwhen there is no signal (only possible with strict mode off).caption_language: the language of the text you got. It equalsspoken_languageunless you setpreferredLanguage.is_auto_generated: YouTube's speech recognition rather than human captions.is_translated: YouTube machine-translated the text (only withpreferredLanguage).language_signal: what named the language.original_audio: the audio track marked original.single_auto_track: the one speech-recognition track.only_caption_language: every track is in one language.preferred_language: you asked for it. With strict mode off,default_track(YouTube's default track for English-language viewers) andfirst_trackmean there was no signal: they are guesses.language_check: the text's language checked against its label before charging.verified: they agree.corrected: an auto-generated track whose text is another language;spoken_languageandcaption_languagegive the language of the text,language_label_youtubeYouTube's label.mismatch: a human track whose text is another language, delivered only becausepreferredLanguageasked for that label (otherwise it is a freelanguage_mismatchrow).unchecked: too short to judge (under about 200 letters, or 60 Chinese, Japanese or Korean characters), or a language the check doesn't cover.
language_detected: the language the check read in the text (nullwhen unchecked).language_corrected:truewhen the label was corrected.available_languages: every caption track, sorted by code. Auto-generated ones end in:auto.chunks: whole caption lines grouped into about 300 words, with start and end times. Chinese and Japanese characters count as half a word; for those,char_countis the better size measure.source: the playlist or channel the video came from.
Which tools return the right language (measured)
On 23 Oct 2026 we ran the top 3 transcript tools in the Store, two transcript APIs outside Apify, and our engine on the same 50 videos. 45 have captions and 5 have none. Each tool ran with its default input, without naming a language.
Apify Store:
| Right spoken language, of 45 captioned | Billed for empty or wrong results | |
|---|---|---|
Store leader (starvibe/youtube-video-transcript) | 31 | 19 of 50 |
No. 2 (johnvc/YoutubeTranscripts, languages: ["en"]) | 31 | 2 |
No. 3 (pintostudio/youtube-transcript-scraper, targetLanguage: "en") | 31 | 13 (10 of them machine translations) |
| This actor's engine | 43 at 5 attempts per video; 45 in each of two runs at 10 attempts (the default) | 0: the 5 no-caption videos were reported free |
Outside Apify (called with no language, as a typical buyer would):
| Right spoken language, of 45 captioned | Wrong language delivered | No answer | |
|---|---|---|---|
Supadata (mode=native) | 41 | 4 | 0 |
| TranscriptAPI | 39 | 2 | 4 timeouts |
| This actor on Apify | 44 | 0 | 1, free as "language unknown" |
- This actor on Apify, 23 Oct 2026: 44 of 45 in the right language and 5 of 5 no-caption videos reported free. The 45th came back free as
original_language_unknown, because YouTube gave no reliable signal for it (see How we measured). - Delivery at volume: 98.6% of 498 videos were delivered in one run at 10 videos in parallel.
How the others miss, in our published test:
- The leader takes the first human track in YouTube's list. That list is sorted for the viewer's locale, not by the video's language. So an English TED talk with an Arabic translation comes back in Arabic, and an auto-dubbed video comes back as its first dub.
- No. 2 needs the language named in advance. On its default (English), non-English videos come back empty.
- No. 3 machine-translates everything to English and does not say so.
- Supadata returned Arabic for 2 English videos and for 1 auto-dubbed Spanish one, and English for the Korean video above. It also returned 34 words for one of the 5 no-caption videos.
- TranscriptAPI returned Galician for a Spanish video and English for the Korean one, and timed out on 4 small English channels.
Error codes
Every row with an error code is free.
error_code | Meaning | Retried? |
|---|---|---|
no_captions | The video has no captions. We don't transcribe audio. | no |
original_language_unknown | Strict mode: YouTube gives no signal for the spoken language. | no |
original_language_unavailable | Strict mode: the spoken language is known (in spoken_language) but has no captions. | no |
language_unavailable | No captions in preferredLanguage, and no YouTube translation into it; or YouTube's auto-generated track in that language turned out to be in another language (language_label_youtube gives YouTube's label, language_detected the language of the text). | no |
language_mismatch | A human caption track whose text is in another language than its label (likely a translation uploaded under the wrong label). Ask for that label with preferredLanguage to get it anyway. | no |
private | The video is private. | no |
age_restricted | The video needs a signed-in adult account. | no |
members_only | Channel members only. | no |
unavailable | Removed, blocked in the proxy's country, or otherwise not playable. | when YouTube says unplayable |
bot_check | YouTube asked every attempt's IP to prove it isn't a bot. | yes, up to maxAttempts |
network_error | The connection failed on every attempt. | yes |
caption_fetch_failed | The captions were listed but didn't download on any attempt. | yes |
invalid_input | Not a YouTube video, playlist or channel. | no |
source_unavailable | A playlist or channel that couldn't be read. | yes, inside the source read |
internal_error | An unexpected error on our side. Please open an issue. | no |
FAQ
How much does it cost?
$2 per 1,000 transcripts ($0.002 each), $12 per 1,000 with Pro. Apify's free plan gives $5 of credit every month: 2,500 transcripts, or about 415 with Pro. Failed videos, videos with no captions and run starts are free. See the pricing table.
Can I use it with integrations?
Yes. Apify connects to n8n, Make, Zapier, Google Sheets, Slack, Airbyte and more, and can send the dataset to them when a run finishes. You can also run it on a schedule, for example to read a channel's new uploads every day.
Can I use it with the API?
Yes. To run it and get the rows in one call, POST your input to https://api.apify.com/v2/acts/neonroobz~youtube-transcripts/run-sync-get-dataset-items?token=<YOUR_TOKEN>. The Apify clients for Python (apify-client) and JavaScript (apify-client) do the same: client.actor("neonroobz/youtube-transcripts").call(...) with your input. Set includeSegments: false to save tokens: text and the timed chunks stay.
Can I use it through an MCP server?
Yes. Add https://mcp.apify.com?tools=neonroobz/youtube-transcripts to Claude, Cursor, ChatGPT or any MCP client, then ask, for example, "get the transcripts of the last 10 videos on @3blue1brown". Pricing is pay-per-event only, every input has a working default, and every row carries a stable status and error_code an agent can act on.
Is it legal to scrape YouTube transcripts?
This actor reads only captions that YouTube shows publicly to any logged-out viewer. It doesn't sign in, and it doesn't read private, members-only or age-restricted videos. It stores no personal data. Scraping publicly available data is legal as long as you respect copyright and personal-data rules such as the GDPR: transcripts are the creators' work, so check how you may reuse them. If you're unsure, ask a lawyer. Apify's blog has more on the legality of web scraping.
Which language do I get?
By default, the language spoken in the video. YouTube's own signals name it:
- the audio track marked original (on auto-dubbed videos);
- otherwise the language of the speech-recognition track;
- otherwise the only language the captions are in.
If there is a human caption track in that language, you get it, because it is usually cleaner than the auto-generated one. With strict mode on (the default), a video with none of these signals gives a free error row.
YouTube's default caption track is not one of the signals. We measured it: on the same TED talk it is English for an English-language viewer, Spanish for a Spanish one and Arabic for an Arabic one, and the order of the track list changes the same way. A video with only human captions in several languages and no speech-recognition track (typical of TED talks) therefore gets original_language_unknown in strict mode. With strict mode off, you get the default track for English-language viewers, labelled default_track with spoken_language: null. Set preferredLanguage if you want a specific language instead.
Why does a row say language_corrected: true?
YouTube sometimes labels English speech by a guest's accent or by the topic: a Computerphile interview with a Dutch guest speaking English came labelled Dutch, and a DW News report in English on German politics came labelled German. The words in the auto-captions are what was said, so you get them, labelled as the language they are in (en), with YouTube's label kept in language_label_youtube. The charge is the normal one: the text is right.
If you asked for a language with preferredLanguage and the auto track labelled with it is really another language, you get a free language_unavailable row instead. A human track whose text doesn't match its label is not delivered (a free language_mismatch row), because that is usually a translation, not the spoken language.
What if a video has no captions?
You get a free no_captions row. We return the captions YouTube has, human or auto-generated. We don't transcribe audio.
What about long videos and Pro?
Pro covers transcripts up to 10,000 words. Longer ones are delivered and charged at the core price, without the translation and summary.
What does the run summary hold?
The OUTPUT record in the key-value store holds:
- counts by status and by error code;
delivery_rate: delivered ÷ (delivered + videos that failed after fetching);- attempts per video;
- which language signal was used;
language_check: how many transcripts were verified, corrected, refused as a mismatch, or unchecked;- events charged and Pro model cost;
- each playlist and channel and how many videos it gave;
not_processed: videos not reached because of your spending limit.
How often is it updated?
YouTube changes its pages without notice. Each release is run against the 50-video test set, and we aim to fix a break within a day of finding it.
Is anything stored?
No. Nothing is kept between runs.
How we measured
- Test set: 50 public videos, fixed in advance: English talks with many human translations; small English channels with auto-captions only; Spanish, German, Japanese, Portuguese, Hindi and Korean originals; long videos, Shorts and auto-dubbed videos; 5 videos with no captions.
- Reference: each video's spoken language, set from YouTube's caption and audio tracks by the same rule our engine uses, then checked by eye against the channel and title language for all 50.
- Scoring: a result is right when the transcript's language is the spoken one, and billed when the tool charged for that video.
- Runs:
- The Store tools ran on Apify with a typical buyer's default input: No. 2 with its default
languages: ["en"], No. 3 with its requiredtargetLanguageat its default"en". - Supadata ran with
mode=native(captions only) and TranscriptAPI with no language, both on 23 Oct 2026. - Our engine ran from Apify datacenter proxies, at 5 attempts per video and then twice at 10.
- Delivery was measured on a separate 498-video run: the 50 test videos plus recent uploads from 35 large channels.
- The Store tools ran on Apify with a typical buyer's default input: No. 2 with its default
- Strict mode was added after the engine runs. It changes a result only when YouTube gives none of the 3 language signals in the FAQ. On the test set that is one video, an English TED talk with 7 human caption tracks and no speech-recognition track. It counted as right in the engine runs only because YouTube's default caption track was English, and that track follows the viewer's locale (all our requests are sent as an English-language viewer). Strict mode now returns it as a free
original_language_unknownrow. - Language check: an offline language detector (franc 6.2.0, trigrams) read the first 3,000 characters of the 524 transcripts delivered in the 498-video and 50-video runs. 514 agreed with their label. 5 were close dialects of the label (Scots for English, Magahi or Bhojpuri for Hindi), 3 were too short to judge, and 2 were real mislabels: English speech on YouTube auto-caption tracks labelled Dutch and German. With dialects counted as their language and a minimum length, the check raises 0 false alarms on those 524 and catches both mislabels. It now runs on every transcript before charging.
Limits
- Captions only, public videos only. No audio transcription.
- "Original language" is YouTube's own signal. Auto-captions keep their own mistakes, such as misheard names and missing punctuation. The translation and summary work from that text.
- Datacenter IPs are sometimes asked to prove they aren't bots. The run summary reports attempts per video, so you can see when this happens more often.
Feedback
A video came back wrong, or something broke? Open an issue in the Issues tab with the video URL. We aim to fix a break within a day of finding it.