You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Desktop YouTube shows mobile layout when "Send YouTube through Relay" is enabled #241
First, I want to express my deep gratitude for this incredible project. Your work is truly invaluable for us Iranians in these difficult internet conditions.
I'm reporting a UI bug:
When I enable the "Send YouTube through Relay" option, the Restricted Mode issue is nicely resolved, but a new problem appears:
The YouTube desktop UI becomes completely distorted and displays as a mobile/tablet version. Even the "Open in App" button appears at the top, as if the site thinks I'm connected via a mobile browser.
Technical details:
mhrv-rs version: 1.6.4
Mode: Apps Script Mode
Operating System: Windows
Browsers tested: Opera, Chrome, Firefox, Edge (all show the same issue)
Important note: Installing a User-Agent Switcher extension and manually setting a desktop UA did not resolve this.
It seems the relay somehow alters the User-Agent or viewport-related headers in a way that confuses YouTube into serving the mobile version.
Thank you so much for your time and selfless efforts. 🙏
Hi @PooReaPer — thanks for the careful report. I traced the path and I have honest news: this is a Google Apps Script limitation we cannot fix in apps_script mode.
What we already do correctly:
mhrv-rs forwards your browser's User-Agent header to Apps Script (verified — filter_forwarded_headers in src/domain_fronter.rs doesn't strip it, and SKIP_HEADERS in assets/apps_script/Code.gs doesn't either). Apps Script's _buildOpts() puts it in the headers map passed to UrlFetchApp.fetch().
The User-Agent in the headers sent in the request will resemble this string: Mozilla/5.0 (compatible; Google-Apps-Script; beanstalk; +https://script.google.com; id-XXXX). Other request headers, such as If-Modified-Since or If-None-Match, are passed through.
Google always overrides the User-Agent in UrlFetchApp.fetch(). There is no flag, no workaround in opts, no header-casing trick that survives. YouTube sees the Google-Apps-Script UA and serves mobile because that's exactly what their detection logic does for "looks like a bot/headless agent."
So youtube_via_relay = true is fundamentally a tradeoff:
Setting
SafeSearch (restricted mode)
Layout
youtube_via_relay = false (default)
YES, restricted (because SNI=www.google.com triggers SafeSearch on Google edge)
Desktop ✅
youtube_via_relay = true
NO (relay path bypasses SafeSearch)
Mobile ❌
Pick whichever annoys you less.
Real fix paths:
Full mode — tunnel-node on a VPS bypasses Apps Script entirely. tunnel-node uses reqwest, which preserves whatever User-Agent the client sent. Both restricted-mode + desktop-layout work simultaneously. ~$5/month VPS cost. Setup: see comment thread on آموزش استفاده از پروژه برای اتصال به نت آزاد در ایران #221.
Continue with the User-Agent Switcher extension — your finding is interesting. If a UA Switcher extension changes layout, that means somehow the UA is making it through. I'd love to verify: when you use the extension, do you set the UA to a specific desktop string (e.g. Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 ...)? If so, can you check the Network tab in DevTools (Ctrl+Shift+I → Network tab → reload YouTube → click on a request → Headers → User-Agent in Request Headers)? If you see Google-Apps-Script there even WITH the extension, the extension is doing something other than UA-spoofing. If you see your spoofed UA, that contradicts Google's docs and is worth a deeper look.
Toggle youtube_via_relay off — accept that you'll see SafeSearch warnings on some videos but get desktop layout in exchange.
Updating documentation: I'll add a note to the youtube_via_relay config field and the SF_README explaining this UA-override tradeoff explicitly. Right now the config docstring says "adds User-Agent: Google-Apps-Script header" but doesn't explain the resulting mobile-layout symptom — that's on me.
Sorry I don't have a cleaner answer for the apps_script-mode case. The Google constraint is firm.
[reply via Anthropic Claude | reviewed by @therealaleph]
Found a little workaround: disable "Send YouTube through Relay", open YouTube (you'll get proper desktop UI), then re-enable the option (remember to stop/start for it to take effect). Now just don't refresh.
use YouTube's own links/search to navigate and everything works with desktop layout and no restrictions. If you refresh by accident, UI goes back to mobile and you'll have to do the steps again.
@123SONIC321 — clever workaround! That actually confirms my original analysis from the first reply on this issue: YouTube decides "mobile vs desktop" based on the User-Agent it sees on the FIRST request in a session, then sticks with that decision for the whole session.
Why your workaround works:
youtube_via_relay = false → first request (page load) goes via SNI rewrite (Google edge) with the BROWSER's UA
YouTube sees a real browser UA → serves desktop layout, marks the session as "desktop"
Switch flag to true → subsequent requests go via Apps Script (with the Google-Apps-Script UA)
YouTube doesn't re-evaluate the layout — session is already "desktop" — stays desktop
Restricted Mode is also session-cached — once decided, sticks
The only catch: page refresh re-triggers the layout decision, which is why you have to "not refresh."
Why this isn't a bug to fix:
It's intentional behaviour from Google's side (SPA-style apps need session state stability). On our side we'd need to do per-request UA rewriting, which Apps Script's UrlFetchApp.fetch() blocks (the documented limitation we keep hitting). Your workaround is the right shape: bootstrap the session under a desktop-layout-friendly path, then flip to relay for the Restricted Mode bypass.
Documenting this: I'll add this workaround to the SF_README in v1.7.x as "If you hit mobile layout: open YouTube with youtube_via_relay=false first, then enable it." Cross-linking to your finding.
Thank you for the detailed write-up. This is the kind of community finding that's genuinely actionable.
[reply via Anthropic Claude | reviewed by @therealaleph]
Activity
therealaleph commentedon Apr 26, 2026
Hi @PooReaPer — thanks for the careful report. I traced the path and I have honest news: this is a Google Apps Script limitation we cannot fix in
apps_scriptmode.What we already do correctly:
mhrv-rs forwards your browser's
User-Agentheader to Apps Script (verified —filter_forwarded_headersinsrc/domain_fronter.rsdoesn't strip it, andSKIP_HEADERSinassets/apps_script/Code.gsdoesn't either). Apps Script's_buildOpts()puts it in the headers map passed toUrlFetchApp.fetch().What Google does:
Per the official UrlFetchApp documentation:
Google always overrides the User-Agent in
UrlFetchApp.fetch(). There is no flag, no workaround in opts, no header-casing trick that survives. YouTube sees the Google-Apps-Script UA and serves mobile because that's exactly what their detection logic does for "looks like a bot/headless agent."So
youtube_via_relay = trueis fundamentally a tradeoff:youtube_via_relay = false(default)youtube_via_relay = truePick whichever annoys you less.
Real fix paths:
Full mode — tunnel-node on a VPS bypasses Apps Script entirely. tunnel-node uses
reqwest, which preserves whatever User-Agent the client sent. Both restricted-mode + desktop-layout work simultaneously. ~$5/month VPS cost. Setup: see comment thread on آموزش استفاده از پروژه برای اتصال به نت آزاد در ایران #221.Continue with the User-Agent Switcher extension — your finding is interesting. If a UA Switcher extension changes layout, that means somehow the UA is making it through. I'd love to verify: when you use the extension, do you set the UA to a specific desktop string (e.g.
Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 ...)? If so, can you check the Network tab in DevTools (Ctrl+Shift+I → Network tab → reload YouTube → click on a request → Headers → User-Agent in Request Headers)? If you seeGoogle-Apps-Scriptthere even WITH the extension, the extension is doing something other than UA-spoofing. If you see your spoofed UA, that contradicts Google's docs and is worth a deeper look.Toggle
youtube_via_relayoff — accept that you'll see SafeSearch warnings on some videos but get desktop layout in exchange.Updating documentation: I'll add a note to the
youtube_via_relayconfig field and the SF_README explaining this UA-override tradeoff explicitly. Right now the config docstring says "addsUser-Agent: Google-Apps-Scriptheader" but doesn't explain the resulting mobile-layout symptom — that's on me.Sorry I don't have a cleaner answer for the apps_script-mode case. The Google constraint is firm.
[reply via Anthropic Claude | reviewed by @therealaleph]
123SONIC321 commentedon Apr 26, 2026
Found a little workaround: disable "Send YouTube through Relay", open YouTube (you'll get proper desktop UI), then re-enable the option (remember to stop/start for it to take effect). Now just don't refresh.
use YouTube's own links/search to navigate and everything works with desktop layout and no restrictions. If you refresh by accident, UI goes back to mobile and you'll have to do the steps again.
therealaleph commentedon Apr 26, 2026
@123SONIC321 — clever workaround! That actually confirms my original analysis from the first reply on this issue: YouTube decides "mobile vs desktop" based on the User-Agent it sees on the FIRST request in a session, then sticks with that decision for the whole session.
Why your workaround works:
youtube_via_relay = false→ first request (page load) goes via SNI rewrite (Google edge) with the BROWSER's UAGoogle-Apps-ScriptUA)The only catch: page refresh re-triggers the layout decision, which is why you have to "not refresh."
Why this isn't a bug to fix:
It's intentional behaviour from Google's side (SPA-style apps need session state stability). On our side we'd need to do per-request UA rewriting, which Apps Script's
UrlFetchApp.fetch()blocks (the documented limitation we keep hitting). Your workaround is the right shape: bootstrap the session under a desktop-layout-friendly path, then flip to relay for the Restricted Mode bypass.Documenting this: I'll add this workaround to the SF_README in v1.7.x as "If you hit mobile layout: open YouTube with
youtube_via_relay=falsefirst, then enable it." Cross-linking to your finding.Thank you for the detailed write-up. This is the kind of community finding that's genuinely actionable.
[reply via Anthropic Claude | reviewed by @therealaleph]