Skip to content

[Bug]: Trailers stop resolving: extraction requires the rate-limited watch page and selects PO-token-gated stream URLs #584

Description

@aneeshtigga

Pre-flight checks

  • I searched existing issues and this is not a duplicate.
  • I can reproduce this on the latest desktop release or latest main build.
  • This issue is limited to a single bug (not multiple unrelated problems).
  • This is not a source/stream-specific error (the issue happens regardless of which source is used).

App version / commit

0.1.21-alpha and Dev (built from source)

Install method

Built from source

Platform

macOS (desktop)

Desktop hardware

Apple Silicon (arm64)

OS version

macOS 26.6 (Darwin 25.6.0)

Area (tag)

Playback (start/stop/buffering)

Bug description

Trailers fail to resolve, and once YouTube flags the network's IP nothing resolves at all. Two independent causes, both measured by replaying the extractor's own requests.

1. ANDROID / IOS adaptive URLs are PO token gated. They serve the first range then 403 every later range, independent of User-Agent (tested Chrome, Safari, Lavf, each client's own UA) and of itag:

Client that minted the URL bytes=0-65535 tail range full GET
IOS (itag 137) 206 403 403
ANDROID (itag 137/136/134/140/251) 206 403 403
ANDROID (itag 18, progressive) 206 n/a 200, downloads fully
VISIONOS (itag 137) 206 206 200

A single head-range probe cannot see this, because the first chunk always succeeds.

2. Extraction requires the watch page, which YouTube rate limits first. extractPlaybackSourceInternal fetches the watch page (1.1-1.4 MB) before every player call only to scrape INNERTUBE_API_KEY and VISITOR_DATA, and throws when it fails. Once flagged it returns 429, then a 302 to a 407-byte error page. Measured at that same moment, the player endpoint still worked:

Video Player API (ANDROID) Progressive itag 18
MAbjq7ydKDI OK, with and without a key full GET 200, 10,139,298 bytes
8ZYhuvIv1pA OK, with and without a key full GET 200, 4,282,937 bytes

INNERTUBE_API_KEY is a public constant present in every YouTube page, so the scrape is not needed.

Contributing factors: 3 player calls per extraction plus the 1.4 MB page, multiplied by hero and hover previews; stale client versions (android 20.10.35, ios 20.10.1 vs current 21.26.364 / 21.26.4); LOGIN_REQUIRED hits the rare clients (visionos, android_vr) long before ANDROID/IOS.

Steps to reproduce

  1. Open titles with trailers and play them, or browse Home with trailer previews enabled.
  2. Trailers start failing, then stop resolving entirely.
  3. With NUVIO_TRAILER_DEBUG=1 the log shows blocked stage=extraction ... Failed to fetch watch page (429).
  4. Confirm streams still exist: call youtubei/v1/player for the same video id with the ANDROID context and fetch the itag 18 URL. It returns 200 and downloads completely while the app reports failure.

Expected behavior

Trailers keep resolving while YouTube serves any playable format, reducing quality if needed instead of failing.

Actual behavior

Extraction dies on the watch page before the player API is tried, and gated URLs that pass the head-range probe then 403 during playback.

Frequency

Always

Did this work before?

Not sure

Media details (optional)

No response

Logs (required for crash reports)

[TrailerDebug] extract start videoId=8ZYhuvIv1pA
[TrailerDebug] blocked stage=extraction error=IllegalStateException message=Failed to fetch watch page (429)

Anything else? (optional)

A fix is implemented and tested on macOS and iOS, submitted as #552: use the public constant key and only fall back to the watch page, probe head and tail so gated URLs are rejected, prefer PO-token-free clients (visionos, android_vr) with fallback to ANDROID progressive itag 18, skip remaining clients once one resolves, refresh client versions, treat UNPLAYABLE/ERROR as final per video, and back off after a 429.

Full measurements were in #551, which the unlabeled-issue bot closed before triage; re-filing through the template so it carries the bug label. Same report for mobile: NuvioMedia/NuvioMobile#1829. Related: NuvioMedia/NuvioTV#2451.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions