加了Cookie yt-dlp仍报HTTP 403:3个容易漏的请求头差异

本文摘要:yt-dlp 配了 Cookie 仍报 403,常因请求头未补齐。用 curl 逐头减法可区分 403 在会话层、头层还是鉴权层。站点接口变动后需重新验证头组合,URL 签名型接口补头无效。

一、问题与结论

批量抓取视频素材时最常见的挫败场景:从浏览器导出完整的 cookies.txt,yt-dlp 加上 --cookies 后运行,终端反复输出 HTTP Error 403: Forbidden。

核心结论 :Netscape 格式的 Cookie 文件只记录 name、value、domain、path、expiry 等字段,不包含 User-Agent、Referer、Origin。这三个头在 yt-dlp 中是三个互相独立的选项,需要手动指定--------cookies 解决登录状态,不解决客户端指纹;服务端校验的是完整请求上下文,缺任一关键头都可能被拒。

二、排查与选择依据

403 可能出现在三个层级,先定位层级再改配置:

层级 特征 修复方向
会话层 删掉 Cookie 后状态码变化 重新导出或刷新 Cookie
请求头层 删掉 UA、Referer 或 Origin 后掉到 403 回填对应头到 yt-dlp 选项
服务端鉴权层 头和 Cookie 全对仍 403 查 IP/地区限制、URL 签名、提取器参数

定位方法是用 curl 做"逐头做减法":从浏览器 DevTools 的目标请求 Copy as cURL,逐个删除一个头,观察状态码在哪一步从 200 变 403。相比"逐个加头试",减法能直接告诉你缺了哪个。

替代方案与取舍

方案 选择条件 代价 边界
curl 逐头减法定位 首次遇到 403,不确定失效层级 需 DevTools 抓包 只适用于请求头层和会话层;服务端签名鉴权需另行排查
--cookies-from-browser 直读 profile 本地有可访问的浏览器 profile 依赖平台解密组件,环境升级后可能失效 仍不携带 UA/Referer/Origin,不是万能方案
--proxy 对齐出口 IP curl 显示头全对仍 403 引入代理成本与稳定性问题 仅在判定为 IP/地区层时才值得
--extractor-args 调整提取行为 403 出现在提取器内部请求 站点级参数随版本变动,需与版本一起锁定 不解决会话层与头层问题

不建议使用该方案的场景:站点已启用 URL 请求签名(如带时效 token 的 CDN 接口),此时头不匹配只是表象,真正的鉴权在 URL 参数里,补头无效。

三、关键原理

Cookie 与请求头是两条正交的轴。Cookie 侧有 --cookies FILE 与 --cookies-from-browser BROWSER[+KEYRING][:PROFILE][::CONTAINER] 两个入口,两者搬运的都只有 cookie 记录本身;请求头侧是三个独立入口:

yt-dlp 选项 覆盖的请求头 备注
--user-agent UA User-Agent 指定自定义 UA
--referer URL Referer README 写的是 "in some request"------作用范围是部分请求,不是全量
--add-header Origin:VALUE Origin 及任意其他头 格式 FIELD:VALUE,可多次使用;无 --origin 专用选项

两个容易忽略的细节:

  1. Cookie 按域名作用域下发。从页面域导出的 Cookie 不会随请求发到分片所在的第三方域。如果 403 出现在下载阶段而非解析阶段,加头可能完全无效------你改的那三行头根本没出现在 403 的那条请求上。

  2. Origin 严格比对 scheme + host 。[https://www.example.com](https://www.example.com) 与 [https://example.com](https://example.com) 是两个不同 Origin,http 与 https 也不等价;--add-header 冒号后的前导空格是否被 trim,以当前版本实测为准。

四、可运行示例

环境 :Windows / Linux 均适用(以下以 bash 为例);yt-dlp(版本以 yt-dlp --version 为准);ffmpeg(仅在合并音视频流时涉及)。

步骤 1:前置自检

bash 复制代码
yt-dlp --version
yt-dlp --help | grep -E -- '--cookies|--cookies-from-browser|--user-agent|--referer|--add-header'

预期输出:应能 grep 到上述选项。若任何一项缺失,说明当前版本选项不同,先核对版本再排查 403。

步骤 2:复现 403(只加 Cookie)

bash 复制代码
yt-dlp -v --cookies ./cookies.txt \
  --format "bestaudio+bestvideo" \
  -o '%(title)s.%(ext)s' \
  "TARGET_URL" 2> step_A.log || true
grep -i '403\|forbidden' step_A.log

预期输出 :日志中出现 HTTP Error 403: Forbidden(错误前缀随版本可能不同,以实际输出为准)。

步骤 3:补齐三个头

bash 复制代码
yt-dlp -v --cookies ./cookies.txt \
  --user-agent "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36" \
  --referer "https://example.com/video-page" \
  --add-header "Origin:https://example.com" \
  --format "bestaudio+bestvideo" \
  -o '%(title)s.%(ext)s' \
  "TARGET_URL" 2> step_B.log || true

实际输出 :若 403 属于请求头层,step_B.log 中 403 消失、下载进度走完;若仍 403,进入步骤 4 定层。UA 的完整值请从 DevTools → Network → Request Headers 复制。

步骤 4:curl 逐头做减法定位

bash 复制代码
#!/usr/bin/env bash
URL='PASTE_REAL_REQUEST_URL'
UA='PASTE_REAL_USER_AGENT'
REF='PASTE_REAL_REFERER'
ORG='PASTE_REAL_ORIGIN'
CK='PASTE_REAL_COOKIE_HEADER'

code() { curl -o /dev/null -s -w '%{http_code}' "$@" "$URL"; echo; }
CKH=(-H "Cookie: $CK")

echo "全头基准:  $(code -H "User-Agent: $UA" -H "Referer: $REF" -H "Origin: $ORG" "${CKH[@]}")"
echo "删UA:      $(code -H "Referer: $REF" -H "Origin: $ORG" "${CKH[@]}")"
echo "删Referer: $(code -H "User-Agent: $UA" -H "Origin: $ORG" "${CKH[@]}")"
echo "删Origin:  $(code -H "User-Agent: $UA" -H "Referer: $REF" "${CKH[@]}")"
echo "删Cookie:  $(code -H "User-Agent: $UA" -H "Referer: $REF" -H "Origin: $ORG")"

判读:

  • 只有"删 Cookie"掉到 403 → 会话层问题,cookie 无效、过期或域不对,补头无效。
  • 删 UA、Referer 或 Origin 掉到 403 → 对应头回填到 --user-agent / --referer / --add-header。
  • 全对仍 403 → 不在请求头层,转查 IP/地区(--proxy)或提取器参数(--extractor-args),不要再改头。

常见失败:所有结果均为 403 → 请求 URL 已过期(CDN 签名 URL 有时效),重新从 DevTools 复制最新 URL 再试。

关联场景:只有声音、播放列表重复下载

  • 只有声音没有画面 :--format 选了 bestaudio,或站点只提供单流格式。用 -F 列出可用格式后选择含视频的组合,或加 --merge-output-format mp4 配合 ffmpeg 合并。
  • 播放列表重复下载 :加 --download-archive archive.txt 记录已下载条目的内部 ID,重复运行时自动跳过;手动删除文件后仍会被跳过,需同步清理 archive 条目。

五、验证结果与边界

依据 yt-dlp README 与 yt-dlp --help 核对(发布前以当前版本复查):

  • --cookies 与三个请求头选项为独立参数,不存在"一键复刻浏览器"的开关。
  • README 中 --referer 写明只作用于 "some request",具体哪些请求携带 Referer 需在 -v 日志或抓包中确认。

待验证 :--add-header 对值中前导空格是否 trim;-v 打印的请求头粒度;不同站点对 Origin 的校验严格程度差异。

失效边界:

  1. 站点提取器变动后,请求头组合可能需重新调整;升级 yt-dlp 后应做同命令 A/B 对照。
  2. --cookies-from-browser 的后缀语法(如 :PROFILE、::CONTAINER)在旧版本中不存在,误用表现为参数识别错误而非 403,两类问题不要混在一起诊断。
  3. Cookie 过期后补再多头也无效------先确认 Cookie 是否仍然有效。

思考

  1. 在 CI 环境中 --cookies-from-browser 不可用时,如何稳定维护 Cookie 与请求头的同步?
  2. 站点启用 URL 签名后,请求头排查是否还有意义,还是应直接转向提取器参数层面?

参考资料

相关推荐
菜鸟不秃头2 小时前
手搓 ViT -- 并完成图像分类任务
python
ZhuoAIStage2 小时前
舞台工艺检测表单自动生成:用 Python 与智能体 Skill 打通规范限值到可填表的数据流
python·第三方检测·舞台工艺·表单自动生成·规范性引用
MoRanzhi12033 小时前
第3篇 · 使用 PyQt5 实现 2048 桌面版游戏:MVC 架构与撤销和重做
python·mvc·pyqt5·桌面应用开发·gui开发·2048游戏·撤销与重做
蚰蜒螟3 小时前
从 Java SocketChannel 到 TCP 挥手:一次 close() 的完整调用链与引用计数解析
java·python·tcp/ip
Smoothcloud润云3 小时前
GPU算力平台跑知识库问答,模型回答总跑偏?先排查检索链路
人工智能·python·深度学习·gpu算力·gpu
mklpo1473 小时前
python3:如何按照实际执行需求导入模块,而不是启动时统一导入?(Python3.15)。2026-10-20
开发语言·人工智能·python
酒神dnspup3 小时前
HTTP Keep-Alive 与连接池实战:TIME_WAIT、端口耗尽和复用率怎么排查
http·keep-alive·tcp·连接池
夜晚回家4 小时前
Python 赋值运算符详解 | 从 = 到 +=,一张记账单讲清复合赋值
开发语言·python
Maya动画技术4 小时前
pptx批量转png图片工具
python