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
Users are reporting download and preview failures on age-restricted YouTube videos. The root cause was confirmed from a verbose yt-dlp -v run:
android_vr player response playability status: LOGIN_REQUIRED
web_embedded player response playability status: UNPLAYABLE
web_safari player response playability status: LOGIN_REQUIRED
ERROR: [youtube] <id>: Sign in to confirm your age.
yt-dlp already cycles through all its client impersonations (android_vr, web_embedded, web_safari) — every one is bounced by YouTube because the video requires a logged-in, age-verified session. This affects both the preview flow (downloader:get-stream-url) and the full download flow (downloader:download), and it's the dominant "works for some, fails for others" failure class in 2026.
As a quick fix we now classify the failure and surface a clear translated error ("This video is age-restricted…") in the UI. See the commit attached to this issue. The quick fix does not unlock the videos — it only tells the user why they failed. This issue tracks the real fix.
Proposed solution — browser cookie import
yt-dlp supports reading cookies directly from installed browsers via --cookies-from-browser BROWSER. If the user is already signed into YouTube in that browser and has confirmed their age once, yt-dlp pulls the session cookie automatically. No manual export, no cookies.txt wrangling. This is the standard pattern for desktop yt-dlp wrappers.
Cookies file… → file picker for a cookies.txt (power-user fallback)
Persist to electron-store under downloads.youtubeAuth: { kind: 'none' | 'browser' | 'file'; browser?: string; cookiesPath?: string }.
New IPC handlers downloader:get-youtube-auth / downloader:set-youtube-auth.
Build a shared helper getYouTubeAuthArgs(): string[] in apps/desktop/src/main/ipc/downloader.ts that reads the setting and returns the appropriate yt-dlp flags ([], ['--cookies-from-browser', 'firefox'], or ['--cookies', '<path>']).
Update classifyYtDlpFailure age-restriction message to point the user at Settings when auth is not configured, and to a different "cookies may be stale / browser locked" message when it is configured.
Add i18n strings (EN + PL) for all new Settings labels, dropdown options, error hints, and help text. Use namespace settings for labels and toast for error messages, consistent with the rest of the app.
Tests:
Unit tests for getYouTubeAuthArgs() covering all three kind values
IPC handler tests asserting the args are spliced in based on store state
A test for the "cookies configured but still failing" error branch
Caveats to surface in the UI
Chromium-family browsers (Chrome, Edge, Brave, Opera, Vivaldi) on Windows encrypt cookies with DPAPI and hold an exclusive lock on the cookies SQLite DB. yt-dlp can read them, but the browser must be closed at the time of the call. UI should warn the user: "Close Chrome before downloading, or use Firefox to avoid this."
Firefox has no such lock — if it's installed, recommend it as the default.
On macOS, Safari works out of the box but requires Full Disk Access permission.
On Linux, only Firefox and Chromium are commonly supported — detection should gate the options list by platform.
UX details
Default to None — do not touch user cookies without consent.
On first save with a non-None option, run a silent validation call (yt-dlp --cookies-from-browser X --simulate --skip-download https://www.youtube.com/) to confirm yt-dlp can actually read the cookies, and show an inline success/error indicator.
On failure during download, if auth is configured and yt-dlp still returns a LOGIN_REQUIRED or age-restricted error, prompt: "YouTube cookies appear to be stale or the browser is running. Close {browser} and retry, or refresh your YouTube sign-in."
Consider adding a small inline "Fix this" deep-link from the age-restriction toast straight to the new Settings row.
Out of scope (for this issue)
PO Token provider plugin support — yt-dlp debug output shows PO Token Providers: none. Some SABR-only videos need a PO token even with cookies. Adding a PO-token provider requires bundling a plugin or integrating yt-dlp-ejs. File as a separate issue once we see it bite users in the wild.
Cross-platform cookie sync / shared profile — some users run multiple browsers; picking one is fine for v1.
Auto-detect installed browsers — v1 can just list a static set and let the user pick.
Related quick-fix (already landed)
The diagnostic and error-classification groundwork is already in place, so this issue only needs to add the cookie flags and the Settings UI on top:
classifyYtDlpFailure() + stable error codes (yt_dlp_age_restricted, yt_dlp_video_unavailable, yt_dlp_no_audio_format) in apps/desktop/src/main/ipc/downloader.ts
translateYtDlpError() helper in apps/web/src/lib/ytdlpErrors.ts
EN + PL translations in apps/web/src/locales/{en,pl}/toast.json
Shared-logger fix so logger.error(..., err) actually serializes Error.message/stack instead of {}
Stderr capture on yt-dlp failure in get-stream-url (previously discarded)
Unit tests for classifyYtDlpFailure including the age-restriction detection path
Background
Users are reporting download and preview failures on age-restricted YouTube videos. The root cause was confirmed from a verbose
yt-dlp -vrun:yt-dlp already cycles through all its client impersonations (
android_vr,web_embedded,web_safari) — every one is bounced by YouTube because the video requires a logged-in, age-verified session. This affects both the preview flow (downloader:get-stream-url) and the full download flow (downloader:download), and it's the dominant "works for some, fails for others" failure class in 2026.As a quick fix we now classify the failure and surface a clear translated error ("This video is age-restricted…") in the UI. See the commit attached to this issue. The quick fix does not unlock the videos — it only tells the user why they failed. This issue tracks the real fix.
Proposed solution — browser cookie import
yt-dlp supports reading cookies directly from installed browsers via
--cookies-from-browser BROWSER. If the user is already signed into YouTube in that browser and has confirmed their age once, yt-dlp pulls the session cookie automatically. No manual export, no cookies.txt wrangling. This is the standard pattern for desktop yt-dlp wrappers.Supported browsers:
firefox,chrome,edge,brave,safari(macOS only),chromium,opera,vivaldi.Scope
DownloadsSection.tsx(Settings → Downloads) with options:None(default, current behavior)Firefox/Chrome/Edge/Brave/Safari(macOS only)Cookies file…→ file picker for acookies.txt(power-user fallback)electron-storeunderdownloads.youtubeAuth: { kind: 'none' | 'browser' | 'file'; browser?: string; cookiesPath?: string }.downloader:get-youtube-auth/downloader:set-youtube-auth.getYouTubeAuthArgs(): string[]inapps/desktop/src/main/ipc/downloader.tsthat reads the setting and returns the appropriate yt-dlp flags ([],['--cookies-from-browser', 'firefox'], or['--cookies', '<path>']).downloader:search(so search doesn't hide age-gated results)downloader:get-stream-url(fixes preview)downloader:download(fixes download)classifyYtDlpFailureage-restriction message to point the user at Settings when auth is not configured, and to a different "cookies may be stale / browser locked" message when it is configured.settingsfor labels andtoastfor error messages, consistent with the rest of the app.getYouTubeAuthArgs()covering all threekindvaluesCaveats to surface in the UI
UX details
None— do not touch user cookies without consent.yt-dlp --cookies-from-browser X --simulate --skip-download https://www.youtube.com/) to confirm yt-dlp can actually read the cookies, and show an inline success/error indicator.LOGIN_REQUIREDorage-restrictederror, prompt: "YouTube cookies appear to be stale or the browser is running. Close {browser} and retry, or refresh your YouTube sign-in."Out of scope (for this issue)
PO Token Providers: none. Some SABR-only videos need a PO token even with cookies. Adding a PO-token provider requires bundling a plugin or integratingyt-dlp-ejs. File as a separate issue once we see it bite users in the wild.Related quick-fix (already landed)
The diagnostic and error-classification groundwork is already in place, so this issue only needs to add the cookie flags and the Settings UI on top:
classifyYtDlpFailure()+ stable error codes (yt_dlp_age_restricted,yt_dlp_video_unavailable,yt_dlp_no_audio_format) inapps/desktop/src/main/ipc/downloader.tstranslateYtDlpError()helper inapps/web/src/lib/ytdlpErrors.tsapps/web/src/locales/{en,pl}/toast.jsonlogger.error(..., err)actually serializesError.message/stackinstead of{}get-stream-url(previously discarded)classifyYtDlpFailureincluding the age-restriction detection pathReferences
--cookies-from-browserdocs