TranscriptsDisabled & NoTranscriptFound in youtube-transcript-api — how to handle them
When batch processing YouTube videos in Python, youtube_transcript_api frequently fails on individual videos with caption errors. Here is why each exception is raised, how to catch and handle them properly, and what to do when no caption tracks exist.
The three distinct caption exceptions
TranscriptsDisabled: Subtitles are turned off for the video (either manually disabled by the creator or disabled due to age restrictions/copyright flags).NoTranscriptFound: The video has transcripts, but none match the languages you requested (e.g. you asked for['en'], but the video only has a Spanish or Japanese track).NoTranscriptAvailable: YouTube has no transcript tracks at all for this video (neither manual subtitles nor automatic ASR captions have been generated).
How to catch and fallback in Python
Rather than fetching one hardcoded language and hoping, inspect the available tracks first and fall back down them in order.
Version note, because most tutorials are stale: release 1.0 replaced the old class methods with an instance API. YouTubeTranscriptApi.get_transcript(...) and YouTubeTranscriptApi.list_transcripts(...) raise AttributeError on any current install — fetch() and list() are the two public methods now, and cues come back as objects with .text, .start and .duration rather than dictionaries. The code below is the 1.x form.
from youtube_transcript_api import (
YouTubeTranscriptApi,
TranscriptsDisabled,
NoTranscriptFound,
CouldNotRetrieveTranscript,
)
def fetch_safe_transcript(video_id: str):
api = YouTubeTranscriptApi() # 1.x is an INSTANCE api
try:
# list() enumerates the tracks WITHOUT downloading any of them.
tracks = api.list(video_id)
# Manually written captions first — they are punctuated and accurate.
try:
return tracks.find_manually_created_transcript(["en", "es", "de"]).fetch()
except NoTranscriptFound:
pass
# Then auto-generated in a language we want.
try:
return tracks.find_generated_transcript(["en"]).fetch()
except NoTranscriptFound:
pass
# Then anything at all — translating it if the track allows.
for track in tracks:
if track.is_translatable:
return track.translate("en").fetch()
return track.fetch()
return None # iterator was empty
# TranscriptsDisabled and NoTranscriptFound both subclass
# CouldNotRetrieveTranscript, so the specific cases must come first.
except TranscriptsDisabled:
print(f"Subtitles are switched off for {video_id}")
return None
except CouldNotRetrieveTranscript as e:
print(f"Could not retrieve transcript: {e}")
return None
When there really are no captions anywhere
If a video was uploaded recently, has low audio volume, or contains only music, YouTube will not generate captions. In those cases, the only solution is downloading the audio track and running speech recognition over it. VidWords does this automatically for captionless videos, so you do not have to build that step yourself.