From 2ecc4c3bc300701d85e2cbaeb2b28a921a68f0f0 Mon Sep 17 00:00:00 2001 From: bashonly <88596187+bashonly@users.noreply.github.com> Date: Tue, 3 Mar 2026 10:20:22 -0600 Subject: [PATCH] [ie/youtube] Skip webpage player response by default (#16126) * Needed for d3165e83ffc0088eef5e594927ea9ac99a6e2ce6 to be effective with the `web` player client Authored by: bashonly --- README.md | 2 +- yt_dlp/extractor/youtube/_video.py | 9 +++++++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 6f4e097642..a5b649818f 100644 --- a/README.md +++ b/README.md @@ -1862,7 +1862,7 @@ The following extractors use this feature: * `skip`: One or more of `hls`, `dash` or `translated_subs` to skip extraction of the m3u8 manifests, dash manifests and [auto-translated subtitles](https://github.com/yt-dlp/yt-dlp/issues/4090#issuecomment-1158102032) respectively * `player_client`: Clients to extract video data from. The currently available clients are `web`, `web_safari`, `web_embedded`, `web_music`, `web_creator`, `mweb`, `ios`, `android`, `android_vr`, `tv`, `tv_downgraded`, and `tv_simply`. By default, `android_vr,web,web_safari` is used. If no JavaScript runtime/engine is available, then only `android_vr` is used. If logged-in cookies are passed to yt-dlp, then `tv_downgraded,web,web_safari` is used for free accounts and `tv_downgraded,web_creator,web` is used for premium accounts. The `web_music` client is added for `music.youtube.com` URLs when logged-in cookies are used. The `web_embedded` client is added for age-restricted videos but only successfully works around the age-restriction sometimes (e.g. if the video is embeddable), and may be added as a fallback if `android_vr` is unable to access a video. The `web_creator` client is added for age-restricted videos if account age-verification is required. Some clients, such as `web_creator` and `web_music`, require a `po_token` for their formats to be downloadable. Some clients, such as `web_creator`, will only work with authentication. Not all clients support authentication via cookies. You can use `default` for the default clients, or you can use `all` for all clients (not recommended). You can prefix a client with `-` to exclude it, e.g. `youtube:player_client=default,-web` * `player_skip`: Skip some network requests that are generally needed for robust extraction. One or more of `configs` (skip client configs), `webpage` (skip initial webpage), `js` (skip js player), `initial_data` (skip initial data/next ep request). While these options can help reduce the number of requests needed or avoid some rate-limiting, they could cause issues such as missing formats or metadata. See [#860](https://github.com/yt-dlp/yt-dlp/pull/860) and [#12826](https://github.com/yt-dlp/yt-dlp/issues/12826) for more details -* `webpage_skip`: Skip extraction of embedded webpage data. One or both of `player_response`, `initial_data`. These options are for testing purposes and don't skip any network requests +* `webpage_skip`: Skip extraction of embedded webpage data. One or both of `player_response`, `initial_data`. Using these will not skip any network requests, and in some cases will result in additional network requests. Currently, the default is `player_response`; however, typically these are for testing purposes only * `player_params`: YouTube player parameters to use for player requests. Will overwrite any default ones set by yt-dlp. * `player_js_variant`: The player javascript variant to use for n/sig deciphering. The known variants are: `main`, `tcc`, `tce`, `es5`, `es6`, `es6_tcc`, `es6_tce`, `tv`, `tv_es6`, `phone`, `house`. The default is `tv`, and the others are for debugging purposes. You can use `actual` to go with what is prescribed by the site * `player_js_version`: The player javascript version to use for n/sig deciphering, in the format of `signature_timestamp@hash` (e.g. `20348@0004de42`). Currently, the default is to force `20514@9f4cc5e4`. You can use `actual` to go with what is prescribed by the site diff --git a/yt_dlp/extractor/youtube/_video.py b/yt_dlp/extractor/youtube/_video.py index d8ba007b00..67fb6ca341 100644 --- a/yt_dlp/extractor/youtube/_video.py +++ b/yt_dlp/extractor/youtube/_video.py @@ -1873,6 +1873,11 @@ class YoutubeIE(YoutubeBaseInfoExtractor): 'params': {'skip_download': True}, }] + @property + def _skipped_webpage_data(self): + # XXX: player_response as a default is a TEMPORARY workaround for pinning _DEFAULT_PLAYER_JS_VERSION + return self._configuration_arg('webpage_skip', default=['player_response']) + _DEFAULT_PLAYER_JS_VERSION = '20514@9f4cc5e4' _DEFAULT_PLAYER_JS_VARIANT = 'tv' _PLAYER_JS_VARIANT_MAP = { @@ -3044,7 +3049,7 @@ class YoutubeIE(YoutubeBaseInfoExtractor): tried_iframe_fallback = True pr = None - if client == webpage_client and 'player_response' not in self._configuration_arg('webpage_skip'): + if client == webpage_client and 'player_response' not in self._skipped_webpage_data: pr = initial_pr visitor_data = visitor_data or self._extract_visitor_data(webpage_ytcfg, initial_pr, player_ytcfg) @@ -3827,7 +3832,7 @@ class YoutubeIE(YoutubeBaseInfoExtractor): def _download_initial_data(self, video_id, webpage, webpage_client, webpage_ytcfg): initial_data = None - if webpage and 'initial_data' not in self._configuration_arg('webpage_skip'): + if webpage and 'initial_data' not in self._skipped_webpage_data: initial_data = self.extract_yt_initial_data(video_id, webpage, fatal=False) if not traverse_obj(initial_data, 'contents'): self.report_warning('Incomplete data received in embedded initial data; re-fetching using API.')