unslothai/unsloth · warning · TranscriptUnavailable
YouTube returned no caption text for this video.
Error message
YouTube returned no caption text for this video.
What it means
TranscriptUnavailable raised after the caption fetch completes when the response body is empty (falsy `body`). The request succeeded at HTTP level (raise_for_status passed) and redirects settled, but zero bytes of caption payload came back.
Source
Thrown at studio/backend/core/youtube_transcript.py:278
# Redirects are followed by hand so the host allowlist covers every hop, not
# just the URL the player response handed us.
async with client.stream(
"GET", url, headers = {"User-Agent": _USER_AGENT}, follow_redirects = False
) as response:
location = response.headers.get("location")
if response.is_redirect and location:
url = urljoin(url, location)
_validated_caption_url(url)
continue
response.raise_for_status()
body = await _read_capped(
response, _MAX_CAPTION_BYTES, "This video's captions are too large to attach."
)
break
else:
raise TranscriptUnavailable("YouTube redirected the caption request too many times.")
if not body:
raise TranscriptUnavailable("YouTube returned no caption text for this video.")
try:
payload = json.loads(body.decode("utf-8"))
except (UnicodeDecodeError, ValueError) as error:
raise TranscriptUnavailable("YouTube returned unreadable caption data.") from error
events = payload.get("events") if isinstance(payload, dict) else None
return _flatten_events(events or [])
def _flatten_events(events: list[Any]) -> str:
lines: list[str] = []
for event in events:
if not isinstance(event, dict):
continue
# aAppend cues carry only the rolling-window newline between ASR lines.
if event.get("aAppend") == 1:
continue
segments = event.get("segs")View on GitHub (pinned to 203007d190)
Solutions
- Retry the fetch after a short backoff.
- Request a different track/language (the selected track may be a dead entry).
- Fall back to local transcription if YouTube keeps returning empty bodies.
Defensive patterns
Strategy: retry
Try / catch
try:
transcript = await fetch_transcript(video_id)
except TranscriptUnavailable as e:
if "no caption text" in str(e):
transcript = await fetch_transcript(video_id, languages=("en",)) # other track, then give up
else:
raise Prevention
- Treat an empty 200 as retryable; do not mark the video permanently bad on first occurrence.
- Select a specific language track on retry to bypass dead track entries.
- Throttle requests — rate limiting sometimes manifests as empty 200 bodies.
When it happens
Trigger: Caption endpoint returning 200 with an empty body for a given fmt=json3 request; track exists but serves no data; transient server-side empty responses.
Common situations: Rare server-side glitches; requesting captions for tracks that were just disabled; rate-limited endpoints returning empty 200s.
Related errors
- This video's captions are empty.
- load timed out (last progress: {prog})
- That is not a YouTube video link.
- YouTube will not play this video.
- This video has no captions.
AI-assisted analysis of unslothai/unsloth@203007d190 (2026-08-15).
Data as JSON: /api/errors/e8a375b7ef3b8a29.
Report an issue: GitHub.