All guides

November 10, 2026 · 4 min read

Fix youtube-transcript-api NoTranscriptFound

In short

NoTranscriptFound means the video has captions, just not under the exact language code you asked for, often de vs de-DE or a missing en track. List the tracks, match a regional code, or translate one.

NoTranscriptFound is the most misleading error in youtube-transcript-api: the video usually does have a transcript. fetch() only accepts exact language codes, and it asks for English by default, so a German video with a de-DE track fails when you ask for "de", and any video without an English track fails when you ask for nothing.

What the error says

Read the whole message: it lists the codes you asked for, then every track the video actually has. Here the video has German as de-DE, so "de" fails:

YouTubeTranscriptApi().fetch("dQw4w9WgXcQ", languages=["de"])
# NoTranscriptFound: No transcripts were found for any of the
# requested language codes: ['de']
#
# (MANUALLY CREATED)
#  - en ("English")[TRANSLATABLE]
#  - de-DE ("German (Germany)")[TRANSLATABLE]
#  - pt-BR ("Portuguese (Brazil)")[TRANSLATABLE]
# (GENERATED)
#  - en ("English (auto-generated)")[TRANSLATABLE]

Fix 1: match regional codes

List the tracks and pick by the part before the hyphen, so de matches de-DE and de-AT. Prefer a manually created track over the auto-generated one.

from youtube_transcript_api import YouTubeTranscriptApi

def fetch_language(video_id, lang):
    tracks = list(YouTubeTranscriptApi().list(video_id))
    same = [t for t in tracks if t.language_code.split("-")[0] == lang]
    if not same:
        return None
    best = next((t for t in same if not t.is_generated), same[0])
    return best.fetch().to_raw_data()

Fix 2: take whatever language the video has

For summaries and search you often want the spoken language, whatever it is. The auto-generated track is always in the spoken language.

tracks = list(YouTubeTranscriptApi().list(video_id))
spoken = next((t for t in tracks if t.is_generated), tracks[0])
print(spoken.language_code, spoken.fetch().to_raw_data()[:3])

Fix 3: translate an existing track

Tracks marked [TRANSLATABLE] can be machine-translated by YouTube into any listed language.

tracks = YouTubeTranscriptApi().list(video_id)
english = tracks.find_transcript(["de-DE"]).translate("en").fetch()

The API does the matching for you

With the TranscriptYT API, language=de picks de-DE or any other German track, a missing language is translated from the original, and no language returns English or the spoken language. Call /v1/languages to see every track first. If the video has no captions at all, it is transcribed with AI instead of failing.

curl "https://transcript-yt.com/v1/transcript?url=dQw4w9WgXcQ&language=de" \
  -H "Authorization: Bearer $TRANSCRIPTYT_KEY"

Common questions

Why do I get NoTranscriptFound when the video has captions?

The language codes must match exactly. A track published as de-DE, pt-BR, or es-419 is not found when you ask for de, pt, or es, and fetch() asks for ["en"] by default, so non-English videos fail unless you pass their language.

How do I see which transcripts a video has?

Call YouTubeTranscriptApi().list(video_id) and print each track's language_code and is_generated. The NoTranscriptFound message also lists them.

How do I get a transcript in any language that exists?

List the tracks and fetch the first one, or pass several codes in priority order, for example languages=["en", "en-US", "en-GB"].

Can I get an English transcript of a video that has no English captions?

Yes, if its track is translatable: transcript_list.find_transcript(["de-DE"]).translate("en").fetch(). The TranscriptYT API does this automatically when you pass language=en.

Is NoTranscriptFound the same as TranscriptsDisabled?

No. NoTranscriptFound means captions exist in other languages. TranscriptsDisabled means the video has no captions at all, which needs AI transcription of the audio.

Try the YouTube Transcript API

Get transcripts as JSON, text, SRT, or VTT. 100 free credits, no card required.

More guides