[server] Mint WebPO tokens from the homepage challenge + ytcfg (fixes #242) - #243
[server] Mint WebPO tokens from the homepage challenge + ytcfg (fixes #242)#243brianstanley wants to merge 1 commit into
Conversation
…rainicism#242) YouTube now binds the initial attestation challenge to the webpage session (yt.config_.EVENT_ID) and rejects WebPO tokens minted from /att/get challenges when the session is enrolled in the experiment (see LuanRT/BgUtils#44). Symptom: player requests pass, googlevideo 403s the download. Fetch https://www.youtube.com through the caller's proxy and extract a self-consistent pair from that single page: ytcfg (injected as globalThis.yt.config_ so the BotGuard snapshot sees EVENT_ID) and the initial window.ytAtN challenge. Plugin-passed webpage challenges can't be paired with their originating page's ytcfg, so the homepage pair is preferred; /att/get remains as a last-resort fallback when the homepage fetch fails, so behavior is never worse than before. parseLooseJSON is vendored from LuanRT/BgUtils v4.0.3 (MIT) because bumping bgutils-js to 4.x is a breaking import restructure out of scope here.
|
Ok, I tested this commit, but I still get: yt-dlp -v --extractor-args "youtube:player-client=mweb" https://www.youtube.com/watch?v=iQZ81MbjKpU
[debug] Command-line config: ['-v', '--extractor-args', 'youtube:player-client=mweb', 'https://www.youtube.com/watch?v=iQZ81MbjKpU']
[debug] User config "/home/nico/.config/yt-dlp/config": ['--rm-cache-dir', '--no-playlist', '-o', '/dev/shm/test-dlp/%(title)s.%(ext)s', '-S', 'res:1080,vcodec:h264,acodec:m4a', '--no-windows-filenames', '--embed-metadata', '--embed-thumbnail', '--convert-thumbnails', 'jpg', '--ppa', 'ffmpeg:-metadata synopsis=""', '--force-ipv4', '--sponsorblock-remove', 'all', '--console-title', '-N', '8']
[debug] Encodings: locale UTF-8, fs utf-8, pref UTF-8, out utf-8, error utf-8, screen utf-8
[debug] yt-dlp version local@2026.08.06 [5d6b8c8cd] (zip)
[debug] Python 3.14.7 (CPython x86_64 64bit) - Linux-5.15.0-187-generic-x86_64-with-glibc2.35 (OpenSSL 3.6.3 9 Jun 2026, glibc 2.35)
[debug] exe versions: ffmpeg N-125972-ge13b2e00e8-Nico-20260806 (fdk,setts), ffprobe N-125972-ge13b2e00e8-Nico-20260806, rtmpdump 2.4
[debug] Optional libraries: Cryptodome-3.23.0, brotli-1.2.0, certifi-2026.07.22, curl_cffi-0.15.0, mutagen-1.48.1, requests-2.34.2, secretstorage-3.5.0, sqlite3-3.37.2, urllib3-2.7.0, websockets-17.0.1, yt_dlp_ejs-0.8.0
[debug] JS runtimes: deno-2.9.5
[debug] Proxy map: {}
[debug] Request Handlers: urllib, requests, websockets, curl_cffi
[debug] Plugin directories: /home/nico/.config/yt-dlp/plugins/bgutil-ytdlp-pot-provider/yt_dlp_plugins
[debug] Loaded 1744 extractors
Removing cache dir /home/nico/.cache/yt-dlp ..
[debug] [youtube] [pot:bgutil:script-node] No server_home or script_path passed, defaulting to /home/nico/bgutil-ytdlp-pot-provider/server
[debug] [youtube] [pot:bgutil:script-deno] No server_home or script_path passed, defaulting to /home/nico/bgutil-ytdlp-pot-provider/server
[debug] [youtube] [pot] PO Token Providers: bgutil:http-1.3.1 (external), bgutil:script-node-1.3.1 (external), bgutil:script-deno-1.3.1 (external)
[debug] [youtube] [pot] PO Token Cache Providers: memory
[debug] [youtube] [pot] PO Token Cache Spec Providers: webpo
[debug] [youtube] [jsc] JS Challenge Providers: bun (unavailable), deno, node (unavailable), quickjs (unavailable)
[youtube] Extracting URL: https://www.youtube.com/watch?v=iQZ81MbjKpU
[youtube] iQZ81MbjKpU: Downloading webpage
[youtube] iQZ81MbjKpU: Downloading mweb client config
[debug] [youtube] Forcing "main" player JS variant for player b0d2d49a
original url = /s/player/b0d2d49a/player_es6.vflset/en_US/base.js
[debug] [youtube] iQZ81MbjKpU: Detected experiment to bind GVS PO Token to video ID for mweb client
[youtube] iQZ81MbjKpU: Downloading mweb player API JSON
[debug] [youtube] iQZ81MbjKpU: Detected a 6s ad for mweb
[debug] [youtube] [pot:bgutil:http] No base_url provided, defaulting to http://127.0.0.1:4416
[youtube] [pot:bgutil:http] Generating a gvs PO Token for mweb client via bgutil HTTP server
[debug] [youtube] iQZ81MbjKpU: Retrieved a gvs PO Token for mweb client
[youtube] iQZ81MbjKpU: Downloading player b0d2d49a-main
[youtube] [jsc:deno] Solving JS challenges using deno
[debug] [youtube] [jsc:deno] Using challenge solver lib script v0.8.0 (source: python package, variant: minified)
[debug] [youtube] [jsc:deno] Using challenge solver core script v0.8.0 (source: python package, variant: minified)
[debug] [youtube] [jsc:deno] Running deno: deno run --ext=js --no-code-cache --no-prompt --no-remote --no-lock --node-modules-dir=none --no-config --no-npm --cached-only -
[debug] [youtube] iQZ81MbjKpU: Retrieved a subs PO Token for mweb client
[debug] Sort order given by user: res:1080, vcodec:h264, acodec:m4a
[debug] Sort order given by extractor: quality, res, fps, hdr:12, source, vcodec, channels, acodec, lang, proto
[debug] Formats sorted by: hasvid, ie_pref, res:1080(1080.0), vcodec:h264(7), acodec:m4a(9), quality, fps, hdr:12(7), source, channels, lang, proto, size, br, asr, vext, aext, hasaud, id
[SponsorBlock] Fetching SponsorBlock segments
[debug] SponsorBlock query: https://sponsor.ajay.app/api/skipSegments/da04?service=YouTube&categories=%5B%22interaction%22%2C+%22preview%22%2C+%22intro%22%2C+%22hook%22%2C+%22music_offtopic%22%2C+%22sponsor%22%2C+%22filler%22%2C+%22outro%22%2C+%22selfpromo%22%5D&actionTypes=%5B%22skip%22%2C+%22poi%22%2C+%22chapter%22%5D
[SponsorBlock] Found 2 segments in the SponsorBlock database
[debug] Default format spec: bestvideo*+bestaudio/best
[info] iQZ81MbjKpU: Downloading 1 format(s): 137+140
[info] Downloading video thumbnail 42 ...
[info] Writing video thumbnail 42 to: /dev/shm/test-dlp/grep isn't what you think it means....webp
[ThumbnailsConvertor] Converting thumbnail "/dev/shm/test-dlp/grep isn't what you think it means....webp" to jpg
[debug] ffmpeg command line: ffmpeg -y -loglevel repeat+info -f image2 -pattern_type none -i 'file:/dev/shm/test-dlp/grep isn'"'"'t what you think it means....webp' -update 1 -qmin 1 -q:v 1 -pix_fmt yuv444p -bsf:v mjpeg2jpeg -movflags +faststart -metadata synopsis= 'file:/dev/shm/test-dlp/grep isn'"'"'t what you think it means....jpg'
Deleting original file /dev/shm/test-dlp/grep isn't what you think it means....webp (pass -k to keep)
[debug] Invoking http downloader on "https://rr3---sn-oj5hn5-55.googlevideo.com/videoplayback?expire=1786739171&ei=gyV_atXgBvDN6dsPr8mhoQY&ip=<REDACTED> &id=o-AK-urY-lbK2XrDMTa3Azj5MufLgVa0C7CZ1aasLs-E-2&itag=137&aitags=133%2C134%2C135%2C136%2C137%2C160%2C242%2C243%2C244%2C247%2C248%2C271%2C278%2C313%2C394%2C395%2C396%2C397%2C398%2C399%2C400%2C401%2C598&source=youtube&requiressl=yes&xpc=EgVo2aDSNQ%3D%3D&cps=365&met=1786717571%2C&mh=Y3&mm=31%2C26&mn=sn-oj5hn5-55%2Csn-4g5lznld&ms=au%2Conr&mv=m&mvi=3&pl=19&rms=au%2Cau&initcwndbps=3776250&bui=AZFlqhNvkjP_99BBSwpBf1n7ona4OR-Q1ciiGpxTj_ZYZzFFeRu7ELclprTxKWCNn3to0WhM2wuGfsvp&spc=KBGBckS0fSmO4PyabzB0U8QUA_IG-3m8HeKG3a7sbwmUKPfCkG51c9s6TH6C3C92Wu3SQSZo6FHdhWstzyfp7qgSC8g&vprv=1&svpuc=1&mime=video%2Fmp4&ns=k0V7LcDQH_E08gPKDB74Hj0X&rqh=1&gir=yes&clen=135727760&dur=692.358&lmt=1751618554721594&mt=1786717030&fvip=1&keepalive=yes&fexp=51565115%2C51946838%2C51973818%2C52089683&c=MWEB&sefc=1&txp=5532534&n=s36E4BPrwEfm9Q&sparams=expire%2Cei%2Cip%2Cid%2Caitags%2Csource%2Crequiressl%2Cxpc%2Cbui%2Cspc%2Cvprv%2Csvpuc%2Cmime%2Cns%2Crqh%2Cgir%2Cclen%2Cdur%2Clmt&sig=AE0s2JYwRgIhALxB7T9CQ3h4gPvTfUlLXkYDEOWKP0I-p1JNgec-D6ZKAiEAryBpUd5oQmuW-6tEYr-wKBbpnq5uQmqPBNr7wV9Opz4%3D&lsparams=cps%2Cmet%2Cmh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Crms%2Cinitcwndbps&lsig=APaTxxMwRgIhAJJaDQV07z22okOjbUVv0mXAL7Zec1o9W1JEVLeWbDKmAiEA88Kvj1_vFYWZmQOzz4TVT5woN2bObhgO0dBBgw5yWzc%3D&pot=MltljgQLKY-0l2XKZ6iXxCfVkMutAHH87ZM3s9aAPBc6eASYhyAHFUnP4RHnhBHG8YpfyHv3DUQzHAmeS6C2nl60eYGohedEZv5_g4RanDJgURN_CQ0ORa9ab6BE"
[download] Sleeping 6.00 seconds as required by the site...
[download] Destination: /dev/shm/test-dlp/grep isn't what you think it means....f137.mp4
[download] 7.5% of 129.44MiB at 7.39MiB/s ETA 00:16ERROR: unable to download video data: HTTP Error 403: Forbidden
Traceback (most recent call last):
File "/usr/local/bin/yt-dlp/yt_dlp/YoutubeDL.py", line 3571, in process_info
partial_success, real_download = self.dl(fname, new_info)
~~~~~~~^^^^^^^^^^^^^^^^^
File "/usr/local/bin/yt-dlp/yt_dlp/YoutubeDL.py", line 3324, in dl
return fd.download(name, new_info, subtitle)
~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/bin/yt-dlp/yt_dlp/downloader/common.py", line 480, in download
ret = self.real_download(filename, info_dict)
File "/usr/local/bin/yt-dlp/yt_dlp/downloader/http.py", line 362, in real_download
establish_connection()
~~~~~~~~~~~~~~~~~~~~^^
File "/usr/local/bin/yt-dlp/yt_dlp/downloader/http.py", line 119, in establish_connection
ctx.data = self.ydl.urlopen(request)
~~~~~~~~~~~~~~~~^^^^^^^^^
File "/usr/local/bin/yt-dlp/yt_dlp/YoutubeDL.py", line 4305, in urlopen
return self._request_director.send(req)
~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^
File "/usr/local/bin/yt-dlp/yt_dlp/networking/common.py", line 117, in send
response = handler.send(request)
File "/usr/local/bin/yt-dlp/yt_dlp/networking/_helper.py", line 194, in wrapper
return func(self, *args, **kwargs)
File "/usr/local/bin/yt-dlp/yt_dlp/networking/common.py", line 359, in send
return self._send(request)
~~~~~~~~~~^^^^^^^^^
File "/usr/local/bin/yt-dlp/yt_dlp/networking/_requests.py", line 361, in _send
raise HTTPError(res, redirect_loop=max_redirects_exceeded)
yt_dlp.networking.exceptions.HTTPError: HTTP Error 403: ForbiddenAm I missing something? [Edit] |
Thanks for testing! Quick question though: your log shows the token came from the HTTP provider at 127.0.0.1:4416. Is that process actually running the patched build? If it's an old process or the official Docker image the patch never ran, and the version string says 1.3.1 in both cases so you can't tell from the yt-dlp side. The easiest way to check is the server console. When this PR mints a token it prints "Using challenge from the homepage (patched)". If you see "Using challenge from the webpage" or "/att/get" instead, it's not the patched build. Also restart the server (or POST to /invalidate_caches) before retrying, since minters are cached server side and --rm-cache-dir only clears yt-dlp's cache. FWIW I re-ran the comparison today with your exact video and format (mweb, f137). Stock 1.3.1 got a 403 on the first googlevideo request, this branch downloaded the full 129 MiB. Your log also looks a bit different from #242: the first 10 MiB chunk downloaded fine and it died opening the second one, while the #242 failure rejects the very first request. If your server does print the homepage line and still 403s I'm happy to dig further, but let's rule out the build first. |
Well, I just replaced [Edit] |
Hmm I think that might be it. After that the server console should print "Using challenge from the homepage (patched)" when it mints the token. Curious to hear how it goes. |
|
How stupid of me. yt-dlp -vyt-dlp -v -f 136+140 --extractor-args "youtube:player-client=mweb" https://www.youtube.com/watch?v=iQZ81MbjKpU
[debug] Command-line config: ['-v', '-f', '136+140', '--extractor-args', 'youtube:player-client=mweb', 'https://www.youtube.com/watch?v=iQZ81MbjKpU']
[debug] User config "/home/nico/.config/yt-dlp/config": ['--rm-cache-dir', '--no-playlist', '-o', '/dev/shm/test-dlp/%(title)s.%(ext)s', '-S', 'res:1080,vcodec:h264,acodec:m4a', '--no-windows-filenames', '--embed-metadata', '--embed-thumbnail', '--convert-thumbnails', 'jpg', '--ppa', 'ffmpeg:-metadata synopsis=""', '--force-ipv4', '--sponsorblock-remove', 'all', '--console-title', '-N', '8']
[debug] Encodings: locale UTF-8, fs utf-8, pref UTF-8, out utf-8, error utf-8, screen utf-8
[debug] yt-dlp version local@2026.08.06 [5d6b8c8cd] (zip)
[debug] Python 3.14.7 (CPython x86_64 64bit) - Linux-5.15.0-187-generic-x86_64-with-glibc2.35 (OpenSSL 3.6.3 9 Jun 2026, glibc 2.35)
[debug] exe versions: ffmpeg N-125972-ge13b2e00e8-Nico-20260806 (fdk,setts), ffprobe N-125972-ge13b2e00e8-Nico-20260806, rtmpdump 2.4
[debug] Optional libraries: Cryptodome-3.23.0, brotli-1.2.0, certifi-2026.07.22, curl_cffi-0.15.0, mutagen-1.48.1, requests-2.34.2, secretstorage-3.5.0, sqlite3-3.37.2, urllib3-2.7.0, websockets-17.0.1, yt_dlp_ejs-0.8.0
[debug] JS runtimes: deno-2.9.5
[debug] Proxy map: {}
[debug] Request Handlers: urllib, requests, websockets, curl_cffi
[debug] Plugin directories: /home/nico/.config/yt-dlp/plugins/bgutil-ytdlp-pot-provider/yt_dlp_plugins
[debug] Loaded 1744 extractors
Removing cache dir /home/nico/.cache/yt-dlp ..
[debug] [youtube] [pot:bgutil:script-node] No server_home or script_path passed, defaulting to /home/nico/bgutil-ytdlp-pot-provider/server
[debug] [youtube] [pot:bgutil:script-deno] No server_home or script_path passed, defaulting to /home/nico/bgutil-ytdlp-pot-provider/server
[debug] [youtube] [pot] PO Token Providers: bgutil:http-1.3.1 (external), bgutil:script-node-1.3.1 (external), bgutil:script-deno-1.3.1 (external)
[debug] [youtube] [pot] PO Token Cache Providers: memory
[debug] [youtube] [pot] PO Token Cache Spec Providers: webpo
[debug] [youtube] [jsc] JS Challenge Providers: bun (unavailable), deno, node (unavailable), quickjs (unavailable)
[youtube] Extracting URL: https://www.youtube.com/watch?v=iQZ81MbjKpU
[youtube] iQZ81MbjKpU: Downloading webpage
[youtube] iQZ81MbjKpU: Downloading mweb client config
[debug] [youtube] Forcing "main" player JS variant for player b0d2d49a
original url = /s/player/b0d2d49a/player_es6.vflset/en_US/base.js
[debug] [youtube] iQZ81MbjKpU: Detected experiment to bind GVS PO Token to video ID for mweb client
[youtube] iQZ81MbjKpU: Downloading mweb player API JSON
[debug] [youtube] iQZ81MbjKpU: Detected a 6s ad for mweb
[debug] [youtube] [pot:bgutil:http] No base_url provided, defaulting to http://127.0.0.1:4416
[youtube] [pot:bgutil:http] Generating a gvs PO Token for mweb client via bgutil HTTP server
[debug] [youtube] iQZ81MbjKpU: Retrieved a gvs PO Token for mweb client
[youtube] iQZ81MbjKpU: Downloading player b0d2d49a-main
[youtube] [jsc:deno] Solving JS challenges using deno
[debug] [youtube] [jsc:deno] Using challenge solver lib script v0.8.0 (source: python package, variant: minified)
[debug] [youtube] [jsc:deno] Using challenge solver core script v0.8.0 (source: python package, variant: minified)
[debug] [youtube] [jsc:deno] Running deno: deno run --ext=js --no-code-cache --no-prompt --no-remote --no-lock --node-modules-dir=none --no-config --no-npm --cached-only -
[debug] [youtube] iQZ81MbjKpU: Retrieved a subs PO Token for mweb client
[debug] Sort order given by user: res:1080, vcodec:h264, acodec:m4a
[debug] Sort order given by extractor: quality, res, fps, hdr:12, source, vcodec, channels, acodec, lang, proto
[debug] Formats sorted by: hasvid, ie_pref, res:1080(1080.0), vcodec:h264(7), acodec:m4a(9), quality, fps, hdr:12(7), source, channels, lang, proto, size, br, asr, vext, aext, hasaud, id
[SponsorBlock] Fetching SponsorBlock segments
[debug] SponsorBlock query: https://sponsor.ajay.app/api/skipSegments/da04?service=YouTube&categories=%5B%22outro%22%2C+%22selfpromo%22%2C+%22hook%22%2C+%22sponsor%22%2C+%22preview%22%2C+%22filler%22%2C+%22interaction%22%2C+%22music_offtopic%22%2C+%22intro%22%5D&actionTypes=%5B%22skip%22%2C+%22poi%22%2C+%22chapter%22%5D
[SponsorBlock] Found 2 segments in the SponsorBlock database
[info] iQZ81MbjKpU: Downloading 1 format(s): 136+140
[info] Downloading video thumbnail 42 ...
[info] Writing video thumbnail 42 to: /dev/shm/test-dlp/grep isn't what you think it means....webp
[ThumbnailsConvertor] Converting thumbnail "/dev/shm/test-dlp/grep isn't what you think it means....webp" to jpg
[debug] ffmpeg command line: ffmpeg -y -loglevel repeat+info -f image2 -pattern_type none -i 'file:/dev/shm/test-dlp/grep isn'"'"'t what you think it means....webp' -update 1 -qmin 1 -q:v 1 -pix_fmt yuv444p -bsf:v mjpeg2jpeg -movflags +faststart -metadata synopsis= 'file:/dev/shm/test-dlp/grep isn'"'"'t what you think it means....jpg'
Deleting original file /dev/shm/test-dlp/grep isn't what you think it means....webp (pass -k to keep)
[debug] Invoking http downloader on "https://rr2---sn-u15hn5-51.googlevideo.com/videoplayback?expire=1786743786&ei=ijd_aqCxE7bHi9oPjeKn8Q4&ip=<REDACTED> &id=o-AOLJIl2hQCuKZswlPYibTEqmOpGrB55nl_kY4koxHqDQ&itag=136&aitags=133%2C134%2C135%2C136%2C137%2C160%2C242%2C243%2C244%2C247%2C248%2C271%2C278%2C313%2C394%2C395%2C396%2C397%2C398%2C399%2C400%2C401%2C598&source=youtube&requiressl=yes&xpc=EgVo2aDSNQ%3D%3D&cps=289&met=1786722186%2C&mh=Y3&mm=31%2C26&mn=sn-u15hn5-51%2Csn-4g5lznld&ms=au%2Conr&mv=m&mvi=2&pl=19&rms=au%2Cau&initcwndbps=3966250&bui=AZFlqhOJ4B3GCiH_8XAzcICv8s8-odUSVsTXZUP_YqlYWJgelIv9uFx-PiEEqy1zpYA9UcWIZ3Mz7-is&spc=KBGBcuzLatakgBYTQqBphhfQMkk06QtaK17532C-4t3YCyoTR3mlP7-KV1fg2w2JN1aExW2lZC0BPMk0GXrCCwbUAmY&vprv=1&svpuc=1&mime=video%2Fmp4&ns=hye069UmajocsZCAf1vi-eYX&rqh=1&gir=yes&clen=50230019&dur=692.358&lmt=1751618786640314&mt=1786721845&fvip=1&keepalive=yes&fexp=51565116%2C51946837%2C51973818%2C52089683&c=MWEB&sefc=1&txp=5532534&n=7S7lca2tpf0L_Q&sparams=expire%2Cei%2Cip%2Cid%2Caitags%2Csource%2Crequiressl%2Cxpc%2Cbui%2Cspc%2Cvprv%2Csvpuc%2Cmime%2Cns%2Crqh%2Cgir%2Cclen%2Cdur%2Clmt&sig=AE0s2JYwRQIhAKEUabOk4R7i4_g6WAN-zIwlZd7S3TMYBTyZ40VhGE2ZAiA9Ep9or9vj7iQNV-AymlZUwyRab-urepffQCI3o-HUGw%3D%3D&lsparams=cps%2Cmet%2Cmh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Crms%2Cinitcwndbps&lsig=APaTxxMwRAIgAf_0fHJkzhghnA-GbUgDmP0cTj2IDx-hv1AyAA362uwCICrcl0AGWX6vEepflEOaS0BzRX2MMQqMaPweVK8HOtYd&pot=MleQF65UW78ebpBXlYSBu9gxJqK9uJP9E1IynVFATdDyl7ct4-cruCATYMclLqGQ_5tIF89LBP5U5oZWUgdkWhMJlv1YlVsHpqIN6ZJbq8h4p2yhYtY1w_U%3D"
[download] Sleeping 5.00 seconds as required by the site...
[download] Destination: /dev/shm/test-dlp/grep isn't what you think it means....f136.mp4
[download] 100% of 47.90MiB in 00:00:06 at 7.33MiB/s
[debug] Invoking http downloader on "https://rr2---sn-u15hn5-51.googlevideo.com/videoplayback?expire=1786743786&ei=ijd_aqCxE7bHi9oPjeKn8Q4&ip=<REDACTED> &id=o-AOLJIl2hQCuKZswlPYibTEqmOpGrB55nl_kY4koxHqDQ&itag=140&source=youtube&requiressl=yes&xpc=EgVo2aDSNQ%3D%3D&cps=289&met=1786722186%2C&mh=Y3&mm=31%2C26&mn=sn-u15hn5-51%2Csn-4g5lznld&ms=au%2Conr&mv=m&mvi=2&pl=19&rms=au%2Cau&initcwndbps=3966250&bui=AZFlqhOJ4B3GCiH_8XAzcICv8s8-odUSVsTXZUP_YqlYWJgelIv9uFx-PiEEqy1zpYA9UcWIZ3Mz7-is&spc=KBGBcuzLatakgBYTQqBphhfQMkk06QtaK17532C-4t3YCyoTR3mlP7-KV1fg2w2JN1aExW2lZC0BPMk0GXrCCwbUAmY&vprv=1&svpuc=1&mime=audio%2Fmp4&ns=hye069UmajocsZCAf1vi-eYX&rqh=1&gir=yes&clen=11206859&dur=692.419&lmt=1751616540112306&mt=1786721845&fvip=1&keepalive=yes&fexp=51565116%2C51946837%2C51973818%2C52089683&c=MWEB&sefc=1&txp=5532534&n=7S7lca2tpf0L_Q&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cxpc%2Cbui%2Cspc%2Cvprv%2Csvpuc%2Cmime%2Cns%2Crqh%2Cgir%2Cclen%2Cdur%2Clmt&sig=AE0s2JYwRQIhAPtYxgWmxZrswvxD7ejsXM9So-NQ_OHg4kmVZYkJIcqzAiAHxwzKdIMr6qz3Q2Up22tNwnYFgMtQUhFtFZdRwCeUTQ%3D%3D&lsparams=cps%2Cmet%2Cmh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Crms%2Cinitcwndbps&lsig=APaTxxMwRAIgAf_0fHJkzhghnA-GbUgDmP0cTj2IDx-hv1AyAA362uwCICrcl0AGWX6vEepflEOaS0BzRX2MMQqMaPweVK8HOtYd&pot=MleQF65UW78ebpBXlYSBu9gxJqK9uJP9E1IynVFATdDyl7ct4-cruCATYMclLqGQ_5tIF89LBP5U5oZWUgdkWhMJlv1YlVsHpqIN6ZJbq8h4p2yhYtY1w_U%3D"
[download] Destination: /dev/shm/test-dlp/grep isn't what you think it means....f140.m4a
[download] 100% of 10.69MiB in 00:00:02 at 4.70MiB/s
[Merger] Merging formats into "/dev/shm/test-dlp/grep isn't what you think it means....mp4"
[debug] ffmpeg command line: ffmpeg -y -loglevel repeat+info -i 'file:/dev/shm/test-dlp/grep isn'"'"'t what you think it means....f136.mp4' -i 'file:/dev/shm/test-dlp/grep isn'"'"'t what you think it means....f140.m4a' -c copy -map 0:v:0 -map 1:a:0 -movflags +faststart -metadata synopsis= 'file:/dev/shm/test-dlp/grep isn'"'"'t what you think it means....temp.mp4'
Deleting original file /dev/shm/test-dlp/grep isn't what you think it means....f136.mp4 (pass -k to keep)
Deleting original file /dev/shm/test-dlp/grep isn't what you think it means....f140.m4a (pass -k to keep)
[debug] ffprobe command line: ffprobe -hide_banner -show_format -show_streams -print_format json 'file:/dev/shm/test-dlp/grep isn'"'"'t what you think it means....mp4'
[debug] Concat spec = 26.490000-673.680000, 685.848000-inf
[ModifyChapters] Removing chapters from /dev/shm/test-dlp/grep isn't what you think it means....mp4
[debug] Writing concat spec to /dev/shm/test-dlp/grep isn't what you think it means....temp.mp4.concat
[debug] ffmpeg command line: ffmpeg -y -loglevel repeat+info -hide_banner -nostdin -f concat -safe 0 -i 'file:/dev/shm/test-dlp/grep isn'"'"'t what you think it means....temp.mp4.concat' -map 0 -dn -ignore_unknown -c copy -c:s mov_text -movflags +faststart -metadata synopsis= 'file:/dev/shm/test-dlp/grep isn'"'"'t what you think it means....temp.mp4'
Deleting original file /dev/shm/test-dlp/grep isn't what you think it means....uncut.mp4 (pass -k to keep)
[Metadata] Adding metadata to "/dev/shm/test-dlp/grep isn't what you think it means....mp4"
[debug] ffmpeg command line: ffmpeg -y -loglevel repeat+info -i 'file:/dev/shm/test-dlp/grep isn'"'"'t what you think it means....mp4' -i 'file:/dev/shm/test-dlp/grep isn'"'"'t what you think it means....meta' -map 0 -dn -ignore_unknown -c copy -map_metadata 1 -write_id3v1 1 -metadata 'title=grep isn'"'"'t what you think it means...' -metadata date=20250701 -metadata 'description=Ever wonder why your favorite UNIX command is called "grep"? And what the heck does it have to do with the Founding Fathers?
Join me as we discuss linguistics research, Bell Labs, the American Revolution, and how it all resulted in the linux tool we all depend upon!
---
Timestamps
00:00 The Phone Call that Created grep
01:05 Linguistic fingerprinting
02:55 A Historical Mystery...
05:00 PDP-7 Limitations
07:40 Ken Thompson'"'"'s Overnight Hack
10:27 Essential Tool or Unix Junk?
---
Follow LaurieWired on Social Media:
►https://linktr.ee/lauriewired
---
Works Cited:
Unix: An Oral History (Princeton):
https://web.archive.org/web/20200803035038/https://www.princeton.edu/~hos/frs122/unixhist/finalhis.htm
The Federalist Papers (Library of Congress):
https://guides.loc.gov/federalist-papers/full-text
The History of grep (Rualthanzauva):
https://medium.com/@rualthanzauva/grep-was-a-private-command-of-mine-for-quite-a-while-before-i-made-it-public-ken-thompson-a40e24a5ef48' -metadata 'synopsis=Ever wonder why your favorite UNIX command is called "grep"? And what the heck does it have to do with the Founding Fathers?
Join me as we discuss linguistics research, Bell Labs, the American Revolution, and how it all resulted in the linux tool we all depend upon!
---
Timestamps
00:00 The Phone Call that Created grep
01:05 Linguistic fingerprinting
02:55 A Historical Mystery...
05:00 PDP-7 Limitations
07:40 Ken Thompson'"'"'s Overnight Hack
10:27 Essential Tool or Unix Junk?
---
Follow LaurieWired on Social Media:
►https://linktr.ee/lauriewired
---
Works Cited:
Unix: An Oral History (Princeton):
https://web.archive.org/web/20200803035038/https://www.princeton.edu/~hos/frs122/unixhist/finalhis.htm
The Federalist Papers (Library of Congress):
https://guides.loc.gov/federalist-papers/full-text
The History of grep (Rualthanzauva):
https://medium.com/@rualthanzauva/grep-was-a-private-command-of-mine-for-quite-a-while-before-i-made-it-public-ken-thompson-a40e24a5ef48' -metadata 'purl=https://www.youtube.com/watch?v=iQZ81MbjKpU' -metadata 'comment=https://www.youtube.com/watch?v=iQZ81MbjKpU' -metadata artist=LaurieWired -metadata 'genre=Science & Technology' -metadata:s:1 language=eng -movflags +faststart -metadata synopsis= 'file:/dev/shm/test-dlp/grep isn'"'"'t what you think it means....temp.mp4'
[EmbedThumbnail] mutagen: Adding thumbnail to "/dev/shm/test-dlp/grep isn't what you think it means....mp4"
Btw, is it safe to update [Edit] |
|
Nice, glad it works! Thanks for taking the time to test it. About npm, I think it's fine to update, that notice pops up on every npm command and has nothing to do with this project. Just check your Node version first, I believe npm 12 wants Node 22.22+. On older Node I'd stay on npm 11, works fine either way. |
|
Just to say that I've been using this PR for 2 weeks w/ mweb and it seems to be working perfectly, all the random failures I kept having haven't happened once since. Not to say I may not just have been lucky if I did something wrong / misunderstood this. (personally using it without a server running the script directly, built and used it with deno) |
Problem
Since late July 2026, YouTube binds the initial BotGuard attestation challenge to the webpage session (
yt.config_.EVENT_ID) and rejects WebPO tokens minted from/att/getchallenges when the session is enrolled in the experiment — see LuanRT/BgUtils#44 (fixed there in v4.0.3). Symptom, as reported in #242: player requests succeed, then googlevideo rejects the download with HTTP 403. Enforcement looks probabilistic (A/B rollout), so failures are intermittent and provider/IP-independent — I reproduced identical 403s through two different residential proxy pools.Fix
Port the approach from LuanRT/BgUtils#44 into
SessionManager: before falling back to/att/get, fetchhttps://www.youtube.comthrough the caller's proxy and extract a self-consistent pair from that single page:ytcfg→ injected asglobalThis.yt.config_(andwindow.yt) so the BotGuard snapshot seesEVENT_IDwindow.ytAtN(...)challenge → parsed withparseLooseJSON(vendored from BgUtils v4.0.3, MIT — bumpingbgutils-jsto 4.x is a breaking import restructure I kept out of scope)The homepage pair is preferred over plugin-passed webpage challenges because those can't be paired with their originating page's
ytcfg./att/getremains as a last-resort fallback whenever the homepage fetch or extraction fails, so behavior is never worse than before. The extra homepage request happens once per minter creation (minters stay cached), not per token.Validation
Measured on a production workload (yt-dlp 2026.07.04 + this provider, residential proxies, sticky session rotated and
/invalidate_cachescalled between trials to avoid token-cache contamination; 24 trials, 4 videos, audio downloads):/att/getpath)Server logs during the patched run: 29× challenge minted from the homepage; the legacy fallback engaged only when the homepage fetch itself failed through a flaky proxy exit. The remaining failures were ordinary per-IP bot challenges, unrelated to the token path.
npx tsc,eslint --max-warnings=0andprettierall pass.Fixes #242