From 765a90e80871f8a7c1c3f5ae7b6f0dcf2d7afda7 Mon Sep 17 00:00:00 2001 From: Kayos Date: Sun, 24 May 2026 11:50:15 -0700 Subject: [PATCH] client: skip player.js deobf for Android + prefer Android-first client order YouTube's Android InnerTube path returns pre-signed stream URLs (no `s=` cipher param, no `n=` throttling param) just like the iOS path. Mark Android as deobf-exempt and put it first in the default player client order so the typical playback path stops fetching player.js entirely. Avoids the `could not extract sig fn name` failure on YouTube's newer player.js shapes (eg. c2f7551f). Desktop stays in the rotation behind botguard for completeness; it will still try to deobf and may fail, but it's only consulted as a fallback for botguard-signed sessions now. --- src/client/mod.rs | 6 +++++- src/client/player.rs | 9 +++++++-- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/client/mod.rs b/src/client/mod.rs index 06386bc..f3304f0 100644 --- a/src/client/mod.rs +++ b/src/client/mod.rs @@ -100,7 +100,11 @@ impl ClientType { } fn needs_deobf(self) -> bool { - !matches!(self, ClientType::Ios) + // Android + iOS InnerTube paths return pre-signed stream URLs (no &s= cipher, + // no &n= throttling param), so they don't need player.js deobfuscation at all. + // Skipping the deobf fetch here keeps the player path alive even when YouTube + // rotates the player.js to a shape our extractor doesn't recognise. + !matches!(self, ClientType::Ios | ClientType::Android) } fn needs_po_token(self) -> bool { diff --git a/src/client/player.rs b/src/client/player.rs index 9bae601..1fd00ab 100644 --- a/src/client/player.rs +++ b/src/client/player.rs @@ -245,10 +245,15 @@ impl RustyPipeQuery { /// The order may change in the future in case YouTube applies changes to their /// platform that disable a client or make it less reliable. pub fn player_client_order(&self) -> &'static [ClientType] { + // Default to the InnerTube clients that don't need player.js deobfuscation + // (Android, iOS). Tv is kept as a final fallback for when the mobile clients + // return degraded responses. Desktop is only used when botguard is wired + // (po_token signing) because it otherwise serves obfuscated URLs we can't + // currently deobf on YT's newer player versions. if self.client.inner.botguard.is_some() { - &[ClientType::Desktop, ClientType::Ios, ClientType::Tv] + &[ClientType::Android, ClientType::Ios, ClientType::Desktop, ClientType::Tv] } else { - &[ClientType::Ios, ClientType::Tv] + &[ClientType::Android, ClientType::Ios, ClientType::Tv] } }