October DealsAmazon USOctober deal check: compare before you payAmazon US: current deals, useful picks and tech finds.Check DealsSlow PC?RecommendedPC slow today? Run a repair scan before it gets worseResolve common Windows issues and optimize system performance.Scan NowOctober DealsAmazon USDeal season is back - check today's better picksAmazon US: current deals, useful picks and tech finds.See Picks×
Skip to content
Mountain View desk10 min

YouTube Transcripts in Python for LLMs, Without Getting Blocked (2026 Guide)

A practical guide to getting YouTube transcripts in Python for LLM pipelines: the official caption API, the limits of unofficial libraries, how to handle blocked requests, and how to keep timestamps and verify what the model says.
Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

For a video you own or manage, use the official YouTube Data API caption download, which requires OAuth authorization. For other public videos, the unofficial youtube-transcript-api package can read manually created and auto-generated captions when they exist, but it is not a service contract and its requests can fail or be blocked. Neither route gives you permission to get around YouTube’s restrictions. An LLM pipeline therefore has to treat missing or blocked captions as ordinary outcomes, keep timestamps and caption provenance, and check important conclusions against the video itself.

Decide the route by authorization first

The code you write matters less than two questions: who controls the video, and whether you have permission to process its captions. Work through these in order.

As an Amazon Associate I earn from qualifying purchases.

  1. Do you manage the video’s channel? If yes, use the Data API caption download described below. It is the only route in this list that YouTube itself documents as an authorized operation.
  2. Does the owner or rights holder give you a caption file? If yes, use that file and record where it came from.
  3. Are public captions available, and is your use permitted? If yes, a prototype can use youtube-transcript-api, with the error handling described below. Check the terms that apply to your use before running it at volume.
  4. Are there no accessible captions, but you are authorized to process the audio? Use local speech recognition on that audio and label the output as machine transcription.
  5. None of the above? Stop and seek permission. Changing your network identity or retrying until a block lifts is not a fallback.

Whether a particular use is permitted depends on your jurisdiction and the specifics of the use. The points here summarize published platform rules and are not legal advice.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Route Best fit Main constraint What to compare
YouTube Data API captions.download Caption tracks for a video the caller is authorized to manage or access OAuth scopes and permission. Not a universal endpoint for every public video. Authorization, caption track ID, requested format, language, error handling
youtube-transcript-api Prototypes and personal scripts where its supported retrieval path works Unofficial; can break or be blocked. Not a compliance workaround. Caption availability, language priority, timestamps, error handling, maintenance
yt-dlp and related tools Broader media workflows that include subtitle handling Tool capability does not confer rights or exempt use from platform terms Subtitle availability, formats, scope of media handling, update cadence
Managed transcript provider Production teams that prefer a vendor-managed service Provider-specific terms, data handling, reliability and pricing need review Supported cases, provenance of text, retention, rate limits, fallback and ASR behavior, contractual permissions
Local ASR on authorized audio Videos with no accessible captions where you have rights to process the audio Compute cost, transcription error, language and accent quality, audio access Word error risk, timestamp accuracy, language support, cost, consent and rights

Compare the routes on authorization, the source of the words (creator captions, YouTube auto-captions, translation, or new ASR output), languages, timestamp fidelity, blocking and reliability, scale, cost, privacy and retention, and fallback behavior. Treat any vendor claim that a service is “unblocked” as unverified until you have confirmed it for your own videos and volume.

The official route: captions.download

The Data API works on caption tracks attached to a video, not on arbitrary URLs. The flow is to authorize with OAuth, list the caption tracks for a video with captions.list, and then download one track by its ID in a format such as SRT or VTT. The authenticated account must have permission over that video’s captions. If it does not, expect an authorization error rather than a transcript. Console labels below reflect the interface as of October 2026 and may change.

  1. In the Google Cloud console, select or create a project, then open APIs & Services > Library and enable the YouTube Data API v3.
  2. Open APIs & Services > OAuth consent screen and configure it for your application.
  3. Open APIs & Services > Credentials, choose Create credentials > OAuth client ID, and obtain user credentials through the standard installed-application flow.
  4. Request the scope named on the captions.download reference page, and authorize with the account that manages the video’s channel.
  5. List the tracks, then download the one you need.
from googleapiclient.discovery import build

youtube = build("youtube", "v3", credentials=creds)

tracks = youtube.captions().list(part="snippet", videoId=VIDEO_ID).execute()
for item in tracks.get("items", []):
    snippet = item["snippet"]
    print(item["id"], snippet["language"], snippet["trackKind"])

if not tracks.get("items"):
    print("No caption track is available through this account.")
else:
    caption_id = tracks["items"][0]["id"]
    srt_bytes = youtube.captions().download(id=caption_id, tfmt="srt").execute()

The trackKind field tells you whether a track is an uploaded caption track or an ASR (machine-generated) track, so store it with the text. An empty items list means no track is available through that account, which is a different outcome from an authorization error.

The unofficial route: youtube-transcript-api

The project describes fetching manually created and auto-generated subtitles without an API key or a headless browser. That is why it is popular for prototypes. The trade-off is that it depends on caption access that YouTube does not offer as a documented contract for this purpose. A change on YouTube’s side can break it, and a block can stop it, so do not promise uptime to anyone who depends on the output.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
from youtube_transcript_api import YouTubeTranscriptApi

ytt = YouTubeTranscriptApi()
track_list = ytt.list(video_id)
track = track_list.find_transcript(["en", "ja"])  # priority order
print(track.language_code, "auto-generated" if track.is_generated else "human-created")
for snippet in track.fetch():
    print(snippet.start, snippet.text)

Language selection should always be explicit. The list you pass is a priority order, and a fallback to a language you did not intend will silently change what your model reads. Record language_code and is_generated with every transcript.

Handle each outcome as its own state

Captions being absent, a video being unavailable, and a request being blocked are three different situations with three different responses. Collapsing them into one generic failure makes batch jobs retry the wrong things.

from youtube_transcript_api import (
    YouTubeTranscriptApi,
    TranscriptsDisabled,
    NoTranscriptFound,
    VideoUnavailable,
    IpBlocked,
    RequestBlocked,
)

def get_segments(video_id, languages=("en",)):
    ytt = YouTubeTranscriptApi()
    try:
        track = ytt.list(video_id).find_transcript(list(languages))
        segments = [
            {"start": s.start, "duration": s.duration, "text": s.text}
            for s in track.fetch()
        ]
        return {
            "status": "ok",
            "language": track.language_code,
            "auto": track.is_generated,
            "segments": segments,
        }
    except TranscriptsDisabled:
        return {"status": "captions_disabled"}
    except NoTranscriptFound:
        return {"status": "no_track_in_language"}
    except VideoUnavailable:
        return {"status": "video_unavailable"}
    except (IpBlocked, RequestBlocked):
        return {"status": "blocked"}
  • captions_disabled: final for that video. Do not retry. Route it to the owner-file or ASR path if you are authorized.
  • no_track_in_language: record the languages that were tried. Try another language only if your application can use it.
  • video_unavailable: the video may be removed, private or otherwise unavailable. Log and skip.
  • blocked: stop the batch. Do not loop, and do not retry in parallel.

When requests are blocked

A block means YouTube is restricting automated access from the client it sees. Your script cannot establish from the outside exactly why a given request was refused, and the library’s own description of its method means it cannot promise that requests will succeed. A block is therefore a signal to change the route, not a problem to engineer around.

YouTube’s developer policy guidance is explicit on this point: “Your service can’t be specifically designed to allow you or your users to get around restrictions YouTube places on their channel” (Google for Developers, “Complying with YouTube’s Developer Policies”). The API terms also state that YouTube “may suspend or terminate your access to, or use of, any aspect of the YouTube API Services (including any credentials assigned to you or your API Client(s)), impose additional requirements and restrictions, or terminate the Agreement between you and YouTube, for any violation of the Agreement by you, your API Client(s) or those acting on your behalf” (YouTube API Services Terms of Service, section 3.1).

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

In practice, that rules out rotating proxies or network identities to get past a block, spoofing client identity, and running parallel retries across accounts. These are not compliant ways to avoid a block, even when a tool makes them easy to configure. The recovery sequence is:

  1. Stop the batch at the first blocked response.
  2. Record the affected video IDs and the time of the first block.
  3. Move those videos to an owner-supplied caption file, the Data API route if you manage the video, or authorized local ASR.
  4. Resume only the remaining jobs that still use an authorized route, at a pace a human has chosen.

Keep timestamps and source provenance from the start

Flattening transcripts into one string is the most common early mistake. Once timestamps are gone, a model’s answer cannot point back to the moment in the video it came from. Keep each segment as a record with the fields below.

  • video_id: normalized from the input. Accept watch?v= URLs, youtu.be short links, and /shorts/ and /embed/ paths, then store only the ID.
  • start and duration: seconds from the beginning of the video, as returned by the caption source.
  • text: the segment text, unmodified.
  • language: the language code you requested and the language actually returned.
  • source: one of creator_caption, auto_caption, translated, owner_file, or asr. Never merge these silently. If a claim depends on machine-generated text, the source label should travel with it into the answer.

When captions are missing: owner files and local ASR

Owner-supplied caption files

Ask the owner for an SRT or VTT file rather than a plain text export, because the timing data is what makes citations possible. Check that the file matches the video version you are processing, since edited videos can drift from an older caption file.

Local speech recognition on audio you may process

Local ASR is a fallback for videos with no accessible captions, and only for audio you are entitled to use. Its output has its own error profile. Names, numbers, dates, drug or product names, and technical terms are the most likely to be wrong, so compare those against the original recording before you rely on them. Keep the segment timestamps the model emits, and label the whole transcript as asr.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Feed long transcripts to an LLM without losing the evidence

Split transcripts on segment boundaries, not at arbitrary character offsets, and overlap by a small number of segments so a sentence that spans a boundary is not cut in half. The function below is a starting point. Tune the size to your model’s context window and to the density of the speech.

def chunk_segments(segments, max_chars=6000, overlap=2):
    chunks, current, size, pending = [], [], 0, False
    for seg in segments:
        current.append(seg)
        size += len(seg["text"])
        pending = True
        if size >= max_chars:
            chunks.append(current)
            current = current[-overlap:] if overlap else []
            size = sum(len(s["text"]) for s in current)
            pending = False
    if pending:
        chunks.append(current)
    return chunks

def to_prompt_text(chunk, video_id):
    lines = [f"Video: {video_id}"]
    for seg in chunk:
        minutes, seconds = divmod(int(seg["start"]), 60)
        lines.append(f"[{minutes:02d}:{seconds:02d}] {seg['text']}")
    return "n".join(lines)

Put the timestamps inside the text the model sees, and instruct it to cite them. A prompt skeleton that works with this format:

Answer using only the transcript excerpt below.
For each claim, give the timestamp where it is stated and quote no more than 20 words.
If the excerpt does not support a claim, say so.

Retrieval over segments can help locate candidate passages, but a top-k search can skip context that a conclusion depends on. It is not equivalent to reading the whole transcript. For a summary that will inform a decision, send the full transcript where it fits, or use a staged summary that keeps timestamps at every level.

What compression can change

A 2026 arXiv preprint on Japanese medical YouTube videos studied how transcript compression affected LLM-based misinformation classification. It found that summary and retrieval-augmented inputs made some institutional and technical language more prominent, while reducing affective, social, temporal, cognitive and conversational cues. That is a result for one language, one domain and one task. It does not show that every summarization task fails. It does show that a compressor’s choices are not neutral, so a summary cannot be assumed to keep every signal a downstream classifier relies on.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Check the output before anyone acts on it

For summaries and claims that will inform a decision, the model’s answer is a lead to verify rather than a finding. Build the checks into the pipeline:

  • Require a timestamp and a short quote for every factual claim, and reject answers that omit them.
  • Open the cited moment of the video, or the owner’s transcript, and confirm the claim. Do this for names, figures and any statement that changes what someone will do.
  • Where a claim rests on auto_caption or asr text, confirm it against the audio before publishing it as fact.
  • Log the status of every video (ok, disabled, unavailable, blocked, no track) so you can report coverage honestly.
  • Review the terms and the authorization for each source before scaling the job.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

Leave a Reply

Your email address will not be published. Required fields are marked *

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

More from the Wire

  1. World desk4 min
    How to Spot an AI Voice Scam Before Sending MoneyDon’t rely on how a caller sounds. Pause, call back through a known number, and verify the emergency with another trusted person before sending money.
  2. Mountain View desk4 min
    Google’s SynthID Detector: How to Check AI-Generated Images, Video and AudioGoogle’s SynthID Detector looks for an embedded watermark in supported images, video and audio. Here is what its results do—and do not—show.
  3. Redmond desk20 min
    How to create a link to File or Folder in Windows 11Windows 11 gives you several ways to point to a file or folder without moving or duplicating it. You can create a desktop shortcut,…
Recommended PC Tool
Recommended PC Tool
PC Slower Than It Used to Be?Free scan - under a minute
Crashes, No Sound, or Screen Glitches?Free driver scan

Two free Windows tools

One Free Minute Could Fix That PC

Before you go - each of these free tools takes about a minute and tackles what quietly slows a Windows PC down.

Special offer. View Outbyte info, uninstall instructions, EULA, and Privacy Policy.