unslothai/unsloth · error · TranscriptUnavailable
YouTube redirected the caption request too many times.
Error message
YouTube redirected the caption request too many times.
What it means
TranscriptUnavailable raised in _fetch_track_text when the manual redirect loop exhausts all iterations without getting a non-redirect response. The code follows redirects itself (validating each hop via _validated_caption_url) up to a fixed maximum; exceeding that budget triggers this instead of an infinite redirect loop.
Source
Thrown at studio/backend/core/youtube_transcript.py:276
body = b""
for _ in range(_MAX_CAPTION_REDIRECTS + 1):
# 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:View on GitHub (pinned to 203007d190)
Solutions
- Retry once — transient redirect storms usually resolve.
- Ensure requests carry standard browser-like headers/cookies so YouTube does not loop through consent redirects.
- If persistent, capture the redirect chain (log each url) and report; the loop budget or cookie handling may need a fix in the client.
Defensive patterns
Strategy: retry
Try / catch
try:
transcript = await fetch_transcript(video_id)
except TranscriptUnavailable as e:
if "redirected the caption request too many times" in str(e):
await asyncio.sleep(1.0)
transcript = await fetch_transcript(video_id)
else:
raise Prevention
- Send browser-like headers/cookies so consent redirects resolve in one hop.
- Retry once — redirect loops are almost always transient.
- If loops persist, log the chain of URLs to identify the consent endpoint involved.
When it happens
Trigger: YouTube's caption endpoint replying with a redirect chain longer than the loop budget (e.g. repeated 302 hops between consent and caption URLs); a misbehaving or adversarial server bouncing the request between allowed hosts indefinitely.
Common situations: Consent-cookie redirect loops when no consent cookies are sent; CDN misconfiguration loops; extremely rare in normal operation.
Related errors
- YouTube will not play this video.
- YouTube returned an unreadable response.
- YouTube returned unreadable caption data.
- load timed out (last progress: {prog})
- That is not a YouTube video link.
AI-assisted analysis of unslothai/unsloth@203007d190 (2026-08-15).
Data as JSON: /api/errors/0337e4805cd38b0b.
Report an issue: GitHub.