Repository: yt-dlp/yt-dlp

Issue:
[youtube] player `4fcd6e4a`: nsig extraction failed: Some formats may be missing
### Checklist

- [x] I'm reporting that yt-dlp is broken on a **supported** site
- [x] I've verified that I have **updated yt-dlp to nightly or master** ([update instructions](https://github.com/yt-dlp/yt-dlp#update-channels))
- [x] I've checked that all provided URLs are playable in a browser with the same IP and same login details
- [x] I've checked that all URLs and arguments with special characters are [properly quoted or escaped](https://github.com/yt-dlp/yt-dlp/wiki/FAQ#video-url-contains-an-ampersand--and-im-getting-some-strange-output-1-2839-or-v-is-not-recognized-as-an-internal-or-external-command)
- [x] I've searched [known issues](https://github.com/yt-dlp/yt-dlp/issues/3766), [the FAQ](https://github.com/yt-dlp/yt-dlp/wiki/FAQ), and the [bugtracker](https://github.com/yt-dlp/yt-dlp/issues?q=is%3Aissue%20-label%3Aspam%20%20) for similar issues **including closed ones**. DO NOT post duplicates
- [ ] I've read about [sharing account credentials](https://github.com/yt-dlp/yt-dlp/blob/master/CONTRIBUTING.md#are-you-willing-to-share-account-details-if-needed) and I'm willing to share it if required

### Region

_No response_

### Provide a description that is worded well enough to be understood

Another one

### Provide verbose output that clearly demonstrates the problem

- [x] Run **your** yt-dlp command with **-vU** flag added (`yt-dlp -vU <your command line>`)
- [ ] If using API, add `'verbose': True` to `YoutubeDL` params instead
- [x] Copy the WHOLE output (starting with `[debug] Command-line config`) and insert it below

### Complete Verbose Output

```shell
yt-dlp "https://www.youtube.com/watch?v=aqz-KE-bpKQ" -vF
[debug] Command-line config: ['https://www.youtube.com/watch?v=aqz-KE-bpKQ', '-vF']
[debug] Encodings: locale cp1252, fs utf-8, pref cp1252, out utf-8, error utf-8, screen utf-8
[debug] yt-dlp version master@2025.03.25.001035 from yt-dlp/yt-dlp-master-builds [9dde546e7] (win_exe)
[debug] Python 3.10.11 (CPython AMD64 64bit) - Windows-10-10.0.26100-SP0 (OpenSSL 1.1.1t  7 Feb 2023)
[debug] exe versions: ffmpeg 7.1.1-full_build-www.gyan.dev (setts), ffprobe 7.1.1-full_build-www.gyan.dev, phantomjs 2.5.0, rtmpdump 2.4
[debug] Optional libraries: Cryptodome-3.22.0, brotli-1.1.0, certifi-2025.01.31, curl_cffi-0.10.0, mutagen-1.47.0, requests-2.32.3, sqlite3-3.40.1, urllib3-2.3.0, websockets-15.0.1
[debug] Proxy map: {}
[debug] Request Handlers: urllib, requests, websockets, curl_cffi
[debug] Plugin directories: none
[debug] Loaded 1849 extractors
[youtube] Extracting URL: https://www.youtube.com/watch?v=aqz-KE-bpKQ
[youtube] aqz-KE-bpKQ: Downloading webpage
[youtube] aqz-KE-bpKQ: Downloading tv client config
[youtube] aqz-KE-bpKQ: Downloading player 4fcd6e4a
[youtube] aqz-KE-bpKQ: Downloading tv player API JSON
[youtube] aqz-KE-bpKQ: Downloading ios player API JSON
[debug] [youtube] No global array variable found in player JS
[debug] Saving youtube-nsig.4fcd6e4a to cache
WARNING: [youtube] aqz-KE-bpKQ: Native nsig extraction failed: Trying with PhantomJS
         n = uqvdm0tOPenl-6aMU ; player = https://www.youtube.com/s/player/4fcd6e4a/player_ias.vflset/en_US/base.js
[debug] [youtube] Traceback (most recent call last):
  File "yt_dlp\extractor\youtube\_video.py", line 2222, in extract_nsig
  File "yt_dlp\jsinterp.py", line 923, in resf
  File "yt_dlp\jsinterp.py", line 240, in interpret_statement
  File "yt_dlp\jsinterp.py", line 393, in interpret_statement
  File "yt_dlp\jsinterp.py", line 240, in interpret_statement
  File "yt_dlp\jsinterp.py", line 587, in interpret_statement
  File "yt_dlp\jsinterp.py", line 240, in interpret_statement
  File "yt_dlp\jsinterp.py", line 625, in interpret_statement
  File "yt_dlp\jsinterp.py", line 357, in _operator
  File "yt_dlp\jsinterp.py", line 845, in interpret_expression
  File "yt_dlp\jsinterp.py", line 240, in interpret_statement
  File "yt_dlp\jsinterp.py", line 465, in interpret_statement
  File "yt_dlp\jsinterp.py", line 466, in <listcomp>
  File "yt_dlp\jsinterp.py", line 845, in interpret_expression
  File "yt_dlp\jsinterp.py", line 240, in interpret_statement
  File "yt_dlp\jsinterp.py", line 658, in interpret_statement
  File "collections\__init__.py", line 986, in __getitem__
  File "collections\__init__.py", line 978, in __missing__
KeyError: 'e4'
 (caused by KeyError('e4')); please report this issue on  https://github.com/yt-dlp/yt-dlp/issues?q= , filling out the appropriate issue template. Confirm you are on the latest version using  yt-dlp -U
[youtube] aqz-KE-bpKQ: Executing signature code
[debug] [youtube] PhantomJS command line: phantomjs "--ssl-protocol=any" C:\Users\User\AppData\Local\Temp\tmpufboee9t
WARNING: [youtube] aqz-KE-bpKQ: nsig extraction failed: Some formats may be missing
         n = uqvdm0tOPenl-6aMU ; player = https://www.youtube.com/s/player/4fcd6e4a/player_ias.vflset/en_US/base.js
[debug] [youtube] Executing signature code failed with returncode 3221225725:
; please report this issue on  https://github.com/yt-dlp/yt-dlp/issues?q= , filling out the appropriate issue template. Confirm you are on the latest version using  yt-dlp -U
[debug] Loading youtube-nsig.4fcd6e4a from cache
WARNING: [youtube] aqz-KE-bpKQ: Native nsig extraction failed: Trying with PhantomJS
         n = gs3PN0NhiHXm-mlUh ; player = https://www.youtube.com/s/player/4fcd6e4a/player_ias.vflset/en_US/base.js
[youtube] aqz-KE-bpKQ: Executing signature code
[debug] [youtube] PhantomJS command line: phantomjs "--ssl-protocol=any" C:\Users\User\AppData\Local\Temp\tmp4jhwf5qk
WARNING: [youtube] aqz-KE-bpKQ: nsig extraction failed: Some formats may be missing
         n = gs3PN0NhiHXm-mlUh ; player = https://www.youtube.com/s/player/4fcd6e4a/player_ias.vflset/en_US/base.js
[debug] [youtube] aqz-KE-bpKQ: ios client https formats require a GVS PO Token which was not provided. They will be skipped as they may yield HTTP Error 403. You can manually pass a GVS PO Token for this client with --extractor-args "youtube:po_token=ios.gvs+XXX". For more information, refer to  https://github.com/yt-dlp/yt-dlp/wiki/PO-Token-Guide . To enable these broken formats anyway, pass --extractor-args "youtube:formats=missing_pot"
[debug] Loading youtube-nsig.4fcd6e4a from cache
WARNING: [youtube] aqz-KE-bpKQ: Native nsig extraction failed: Trying with PhantomJS
         n = lfHRAN-mwbAb8abyd ; player = https://www.youtube.com/s/player/4fcd6e4a/player_ias.vflset/en_US/base.js
[youtube] aqz-KE-bpKQ: Executing signature code
[debug] [youtube] PhantomJS command line: phantomjs "--ssl-protocol=any" C:\Users\User\AppData\Local\Temp\tmpeolz7yuy
WARNING: [youtube] aqz-KE-bpKQ: nsig extraction failed: Some formats may be missing
         n = lfHRAN-mwbAb8abyd ; player = https://www.youtube.com/s/player/4fcd6e4a/player_ias.vflset/en_US/base.js
[debug] Loading youtube-nsig.4fcd6e4a from cache
WARNING: [youtube] aqz-KE-bpKQ: Native nsig extraction failed: Trying with PhantomJS
         n = LRtgV1U1dwNHINrGy ; player = https://www.youtube.com/s/player/4fcd6e4a/player_ias.vflset/en_US/base.js
[youtube] aqz-KE-bpKQ: Executing signature code
[debug] [youtube] PhantomJS command line: phantomjs "--ssl-protocol=any" C:\Users\User\AppData\Local\Temp\tmpgewssq5a
WARNING: [youtube] aqz-KE-bpKQ: nsig extraction failed: Some formats may be missing
         n = LRtgV1U1dwNHINrGy ; player = https://www.youtube.com/s/player/4fcd6e4a/player_ias.vflset/en_US/base.js
[youtube] aqz-KE-bpKQ: Downloading m3u8 information
[debug] Sort order given by extractor: quality, res, fps, hdr:12, source, vcodec, channels, acodec, lang, proto
[debug] Formats sorted by: hasvid, ie_pref, quality, res, fps, hdr:12(7), source, vcodec, channels, acodec, lang, proto, size, br, asr, vext, aext, hasaud, id
[info] Available formats for aqz-KE-bpKQ:
ID  EXT   RESOLUTION FPS │   FILESIZE    TBR PROTO │ VCODEC           VBR ACODEC     MORE INFO
───────────────────────────────────────────────────────────────────────────────────────────────────────
sb3 mhtml 48x27        0 │                   mhtml │ images                          storyboard
sb2 mhtml 80x45        0 │                   mhtml │ images                          storyboard
sb1 mhtml 160x90       0 │                   mhtml │ images                          storyboard
sb0 mhtml 320x180      0 │                   mhtml │ images                          storyboard
233 mp4   audio only     │                   m3u8  │ audio only           unknown    Default, low, IOS
234 mp4   audio only     │                   m3u8  │ audio only           unknown    Default, high, IOS
602 mp4   256x144     15 │ ~  7.06MiB    93k m3u8  │ vp09.00.10.08    93k video only IOS
269 mp4   256x144     30 │ ~ 12.84MiB   170k m3u8  │ avc1.4D400C     170k video only IOS
603 mp4   256x144     30 │ ~ 12.35MiB   163k m3u8  │ vp09.00.11.08   163k video only IOS
229 mp4   426x240     30 │ ~ 23.53MiB   311k m3u8  │ avc1.4D4015     311k video only IOS
604 mp4   426x240     30 │ ~ 22.43MiB   296k m3u8  │ vp09.00.20.08   296k video only IOS
230 mp4   640x360     30 │ ~ 61.58MiB   813k m3u8  │ avc1.4D401E     813k video only IOS
605 mp4   640x360     30 │ ~ 56.00MiB   740k m3u8  │ vp09.00.21.08   740k video only IOS
231 mp4   854x480     30 │ ~ 97.73MiB  1291k m3u8  │ avc1.4D401F    1291k video only IOS
606 mp4   854x480     30 │ ~ 86.14MiB  1138k m3u8  │ vp09.00.30.08  1138k video only IOS
311 mp4   1280x720    60 │ ~344.72MiB  4554k m3u8  │ avc1.4D4020    4554k video only IOS
612 mp4   1280x720    60 │ ~230.32MiB  3043k m3u8  │ vp09.00.40.08  3043k video only IOS
312 mp4   1920x1080   60 │ ~561.51MiB  7418k m3u8  │ avc1.64002A    7418k video only IOS
617 mp4   1920x1080   60 │ ~380.19MiB  5022k m3u8  │ vp09.00.41.08  5022k video only IOS
623 mp4   2560x1440   60 │ ~  1.04GiB 14050k m3u8  │ vp09.00.50.08 14050k video only IOS
628 mp4   3840x2160   60 │ ~  2.07GiB 27987k m3u8  │ vp09.00.51.08 27987k video only IOS
```

Discussion:

Patch:
diff --git a/yt_dlp/extractor/youtube/_video.py b/yt_dlp/extractor/youtube/_video.py
index b7203fd89..16e9a3eed 100644
--- a/yt_dlp/extractor/youtube/_video.py
+++ b/yt_dlp/extractor/youtube/_video.py
@@ -2182,6 +2182,7 @@ def _extract_player_js_global_var(self, jscode):
                     (?P<value>
                         (?P<q2>["\'])(?:(?!(?P=q2)).|\\.)+(?P=q2)
                         \.split\((?P<q3>["\'])(?:(?!(?P=q3)).)+(?P=q3)\)
+                        |\[\s*(?:(?P<q4>["\'])(?:(?!(?P=q4)).|\\.)*(?P=q4)\s*,?\s*)+\]
                     )
                 )[;,]
             ''', jscode, 'global variable', group=('code', 'name', 'value'), default=(None, None, None))
@@ -2199,7 +2200,7 @@ def _fixup_n_function_code(self, argnames, code, full_code):
 
     def _extract_n_function_code(self, video_id, player_url):
         player_id = self._extract_player_info(player_url)
-        func_code = self.cache.load('youtube-nsig', player_id, min_ver='2025.03.25')
+        func_code = self.cache.load('youtube-nsig', player_id, min_ver='2025.03.26')
         jscode = func_code or self._load_player(video_id, player_url)
         jsi = JSInterpreter(jscode)
 


Test patch:
diff --git a/test/test_youtube_signature.py b/test/test_youtube_signature.py
index 453caacd6..c79fdc9df 100644
--- a/test/test_youtube_signature.py
+++ b/test/test_youtube_signature.py
@@ -88,6 +88,11 @@
         '2aq0aqSyOoJXtK73m-uME_jv7-pT15gOFC02RFkGMqWpzEICs69VdbwQ0LDp1v7j8xx92efCJlYFYb1sUkkBSPOlPmXgIARw8JQ0qOAOAA',
         '0aqSyOoJXtK73m-uME_jv7-pT15gOFC02RFkGMqWpz2ICs6EVdbwQ0LDp1v7j8xx92efCJlYFYb1sUkkBSPOlPmXgIARw8JQ0qOAOAA',
     ),
+    (
+        'https://www.youtube.com/s/player/4fcd6e4a/player_ias.vflset/en_US/base.js',
+        '2aq0aqSyOoJXtK73m-uME_jv7-pT15gOFC02RFkGMqWpzEICs69VdbwQ0LDp1v7j8xx92efCJlYFYb1sUkkBSPOlPmXgIARw8JQ0qOAOAA',
+        'wAOAOq0QJ8ARAIgXmPlOPSBkkUs1bYFYlJCfe29xx8q7v1pDL0QwbdV96sCIEzpWqMGkFR20CFOg51Tp-7vj_EMu-m37KtXJoOySqa0',
+    ),
 ]
 
 _NSIG_TESTS = [
@@ -243,6 +248,10 @@
         'https://www.youtube.com/s/player/363db69b/player_ias.vflset/en_US/base.js',
         'eWYu5d5YeY_4LyEDc', 'XJQqf-N7Xra3gg',
     ),
+    (
+        'https://www.youtube.com/s/player/4fcd6e4a/player_ias.vflset/en_US/base.js',
+        'o_L251jm8yhZkWtBW', 'lXoxI3XvToqn6A',
+    ),
 ]