Per-channel "skip auth check" toggle for the youtubetab warning

yt-dlp prints a scary-looking ERROR when it can't confirm a channel
tab loaded authenticated:

  ERROR: [youtube:tab] @Channel: Playlists that require authentication
  may not extract correctly without a successful webpage download…
  pass "--extractor-args youtubetab:skip=authcheck" to skip this check

For PUBLIC channels that's just noise — there's no auth-gated content
to miss, and the flag silences it without changing which videos are
found. But for members-only/private channels archived with cookies,
the warning is a real "your cookies may not be working, you might be
getting an incomplete list" signal worth keeping.

So make it a per-channel toggle rather than a blanket setting:

- DownloadOptions gains `skip_auth_check: bool`; apply() emits
  `--extractor-args youtubetab:skip=authcheck` when set. (Its own flag;
  the youtubetab: namespace is distinct from the POT provider's
  youtubepot-bgutilhttp: one, so they coexist.)
- Desktop + web channel-options dialogs gain a checkbox with a tooltip
  spelling out the public-vs-private trade-off.

1 new test; 81 pass.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
Luna 2026-06-01 05:25:06 -07:00
parent 5cb011a13d
commit 6cefc0c0e5
3 changed files with 39 additions and 0 deletions

View file

@ -219,6 +219,7 @@ struct ChannelOptionsForm {
quality_idx: usize, // 0=default, 1=Best, 2=1080p, 3=720p, 4=480p, 5=360p quality_idx: usize, // 0=default, 1=Best, 2=1080p, 3=720p, 4=480p, 5=360p
audio_only: bool, audio_only: bool,
fetch_comments: bool, fetch_comments: bool,
skip_auth_check: bool,
limit_rate_kb: String, limit_rate_kb: String,
min_filesize_mb: String, min_filesize_mb: String,
max_filesize_mb: String, max_filesize_mb: String,
@ -440,6 +441,7 @@ impl App {
quality_idx, quality_idx,
audio_only: opts.audio_only, audio_only: opts.audio_only,
fetch_comments: opts.fetch_comments, fetch_comments: opts.fetch_comments,
skip_auth_check: opts.skip_auth_check,
limit_rate_kb: num(opts.limit_rate_kb), limit_rate_kb: num(opts.limit_rate_kb),
min_filesize_mb: num(opts.min_filesize_mb), min_filesize_mb: num(opts.min_filesize_mb),
max_filesize_mb: num(opts.max_filesize_mb), max_filesize_mb: num(opts.max_filesize_mb),
@ -470,6 +472,7 @@ impl App {
quality, quality,
audio_only: f.audio_only, audio_only: f.audio_only,
fetch_comments: f.fetch_comments, fetch_comments: f.fetch_comments,
skip_auth_check: f.skip_auth_check,
limit_rate_kb: parse_num(&f.limit_rate_kb), limit_rate_kb: parse_num(&f.limit_rate_kb),
min_filesize_mb: parse_num(&f.min_filesize_mb), min_filesize_mb: parse_num(&f.min_filesize_mb),
max_filesize_mb: parse_num(&f.max_filesize_mb), max_filesize_mb: parse_num(&f.max_filesize_mb),
@ -1904,6 +1907,11 @@ impl App {
.on_hover_text("Slow on popular videos. Once captured, comments are browsable from the player modal in the web UI."); .on_hover_text("Slow on popular videos. Once captured, comments are browsable from the player modal in the web UI.");
ui.end_row(); ui.end_row();
ui.label("Skip auth check");
ui.checkbox(&mut form.skip_auth_check, "Suppress the channel-tab authentication warning")
.on_hover_text("Passes --extractor-args youtubetab:skip=authcheck. Safe for PUBLIC channels — it silences yt-dlp's \"playlists that require authentication may not extract correctly\" warning without changing which videos are found. Leave OFF for members-only/private channels, where that warning signals your cookies may not be working.");
ui.end_row();
ui.label("Bandwidth cap (KB/s)"); ui.label("Bandwidth cap (KB/s)");
ui.add(egui::TextEdit::singleline(&mut form.limit_rate_kb).desired_width(100.0).hint_text("off")); ui.add(egui::TextEdit::singleline(&mut form.limit_rate_kb).desired_width(100.0).hint_text("off"));
ui.end_row(); ui.end_row();

View file

@ -79,6 +79,19 @@ pub struct DownloadOptions {
/// When on, the web UI's player modal exposes a Comments tab. /// When on, the web UI's player modal exposes a Comments tab.
#[serde(default)] #[serde(default)]
pub fetch_comments: bool, pub fetch_comments: bool,
/// Skip yt-dlp's channel-tab authentication sanity check by passing
/// `--extractor-args youtubetab:skip=authcheck`.
///
/// yt-dlp warns ("Playlists that require authentication may not
/// extract correctly…") when it can't confirm a channel page loaded
/// authenticated. For PUBLIC channels that warning is noise — there's
/// no auth-gated content to miss — so this silences it. Leave OFF for
/// channels where you archive members-only / private content with
/// cookies: there the warning is a real "your cookies aren't working,
/// you may be getting an incomplete list" signal worth keeping.
#[serde(default)]
pub skip_auth_check: bool,
} }
impl DownloadOptions { impl DownloadOptions {
@ -129,6 +142,12 @@ impl DownloadOptions {
if self.fetch_comments { if self.fetch_comments {
cmd.arg("--write-comments"); cmd.arg("--write-comments");
} }
if self.skip_auth_check {
// Its own --extractor-args flag; the youtubetab: namespace is
// distinct from the POT provider's youtubepot-bgutilhttp: one,
// so they coexist as separate flags without clobbering.
cmd.arg("--extractor-args").arg("youtubetab:skip=authcheck");
}
} }
/// Deserialize from the JSON blob stored in `channel_options.options_json`. /// Deserialize from the JSON blob stored in `channel_options.options_json`.
@ -182,6 +201,14 @@ mod tests {
assert_eq!(args, vec!["--sub-langs", "en,ja,es"]); assert_eq!(args, vec!["--sub-langs", "en,ja,es"]);
} }
#[test]
fn skip_auth_check_emits_extractor_arg() {
let mut cmd = Command::new("yt-dlp");
DownloadOptions { skip_auth_check: true, ..Default::default() }.apply(&mut cmd);
let args: Vec<String> = cmd.get_args().map(|a| a.to_string_lossy().into_owned()).collect();
assert_eq!(args, vec!["--extractor-args", "youtubetab:skip=authcheck"]);
}
#[test] #[test]
fn audio_only_adds_extract_audio_chain() { fn audio_only_adds_extract_audio_chain() {
let mut cmd = Command::new("yt-dlp"); let mut cmd = Command::new("yt-dlp");

View file

@ -913,6 +913,9 @@ async function openChannelOptions(idx){
<div class="settings-row"><label>Fetch comments</label> <div class="settings-row"><label>Fetch comments</label>
<input type="checkbox" id="opt-comments" ${opts.fetch_comments?'checked':''}></div> <input type="checkbox" id="opt-comments" ${opts.fetch_comments?'checked':''}></div>
<div class="settings-hint" style="margin-bottom:4px">Adds <code>--write-comments</code>. Embeds the comment tree into info.json — slow for popular videos but enables the Comments tab in the player.</div> <div class="settings-hint" style="margin-bottom:4px">Adds <code>--write-comments</code>. Embeds the comment tree into info.json — slow for popular videos but enables the Comments tab in the player.</div>
<div class="settings-row"><label>Skip auth check</label>
<input type="checkbox" id="opt-skipauth" ${opts.skip_auth_check?'checked':''}></div>
<div class="settings-hint" style="margin-bottom:4px">Adds <code>--extractor-args youtubetab:skip=authcheck</code>. Safe for <strong>public</strong> channels — silences the "playlists that require authentication may not extract correctly" warning without changing which videos are found. Leave off for members-only/private channels, where that warning means your cookies may not be working.</div>
<div class="settings-row"><label>Bandwidth cap (KB/s)</label> <div class="settings-row"><label>Bandwidth cap (KB/s)</label>
<input type="number" id="opt-rate" value="${opts.limit_rate_kb||''}" placeholder="off" min="0" style="width:90px;background:var(--bg);color:var(--text);border:1px solid var(--border);border-radius:4px;padding:4px 6px"></div> <input type="number" id="opt-rate" value="${opts.limit_rate_kb||''}" placeholder="off" min="0" style="width:90px;background:var(--bg);color:var(--text);border:1px solid var(--border);border-radius:4px;padding:4px 6px"></div>
<div class="settings-row"><label>Min size (MB)</label> <div class="settings-row"><label>Min size (MB)</label>
@ -949,6 +952,7 @@ function readChannelOptionsForm(){
quality:q?q:null, quality:q?q:null,
audio_only:document.getElementById('opt-audio')?.checked||false, audio_only:document.getElementById('opt-audio')?.checked||false,
fetch_comments:document.getElementById('opt-comments')?.checked||false, fetch_comments:document.getElementById('opt-comments')?.checked||false,
skip_auth_check:document.getElementById('opt-skipauth')?.checked||false,
limit_rate_kb:intOrNull('opt-rate'), limit_rate_kb:intOrNull('opt-rate'),
min_filesize_mb:intOrNull('opt-minsz'), min_filesize_mb:intOrNull('opt-minsz'),
max_filesize_mb:intOrNull('opt-maxsz'), max_filesize_mb:intOrNull('opt-maxsz'),