{"record":{"id":"918622380a294c0a","repo":"ytdl-org/youtube-dl","slug":"cannot-decrypt-nsig-without-player-url","errorCode":null,"errorMessage":"Cannot decrypt nsig without player_url","messagePattern":"Cannot decrypt nsig without player_url","errorType":"exception","errorClass":"ExtractorError","httpStatus":null,"severity":"error","filePath":"youtube_dl/extractor/youtube.py","lineNumber":1986,"sourceCode":"        return inner\n\n    def _decrypt_signature(self, s, video_id, player_url):\n        \"\"\"Turn the encrypted s field into a working signature\"\"\"\n        extract_sig = self._cached(\n            self._extract_signature_function, 'sig', player_url, self._signature_cache_id(s))\n        func = extract_sig(video_id, player_url, s)\n        self._print_sig_code(func, s)\n        return func(s)\n\n    # from yt-dlp\n    # See also:\n    # 1. https://github.com/ytdl-org/youtube-dl/issues/29326#issuecomment-894619419\n    # 2. https://code.videolan.org/videolan/vlc/-/blob/4fb284e5af69aa9ac2100ccbdd3b88debec9987f/share/lua/playlist/youtube.lua#L116\n    # 3. https://github.com/ytdl-org/youtube-dl/issues/30097#issuecomment-950157377\n    def _decrypt_nsig(self, n, video_id, player_url):\n        \"\"\"Turn the encrypted n field into a working signature\"\"\"\n        if player_url is None:\n            raise ExtractorError('Cannot decrypt nsig without player_url')\n\n        try:\n            jsi, player_id, func_code = self._extract_n_function_code(video_id, player_url)\n        except ExtractorError as e:\n            raise ExtractorError('Unable to extract nsig function code', cause=e)\n        if self.get_param('youtube_print_sig_code'):\n            self.to_screen('Extracted nsig function from {0}:\\n{1}\\n'.format(\n                player_id, func_code[1]))\n\n        try:\n            extract_nsig = self._cached(self._extract_n_function_from_code, 'nsig func', player_url)\n            ret = extract_nsig(jsi, func_code)(n)\n        except JSInterpreter.Exception as e:\n            self.report_warning(\n                '%s (%s %s)' % (\n                    'Unable to decode n-parameter: expect download to be blocked or throttled',\n                    error_to_compat_str(e),\n                    traceback.format_exc()),","sourceCodeStart":1968,"sourceCodeEnd":2004,"githubUrl":"https://github.com/ytdl-org/youtube-dl/blob/956b8c585591b401a543e409accb163eeaaa1193/youtube_dl/extractor/youtube.py#L1968-L2004","documentation":"Raised at the top of YoutubeIE._decrypt_nsig when the n-parameter decryption is attempted with player_url=None. The nsig function must be extracted from the player's JavaScript, so without a player URL there is nothing to load the code from. This indicates the caller failed to obtain the player URL from ytplayer config or streaming data.","triggerScenarios":"Calling _decrypt_nsig (directly or via _unthrottle_format_urls) for a format whose URL has an 'n' query parameter while player_url was never extracted — e.g. missing player response field, age-gated/cookie-only pages where the player config is absent, or API responses built without a player URL.","commonSituations":"YouTube serves formats needing n-decryption but the extractor path did not capture player_url (page layout change, embedded API responses, consent/age walls); downstream forks calling the internal API without threading player_url through.","solutions":["Ensure the full watch page or player response is downloaded so player_url can be extracted before format URL processing.","Update youtube-dl/yt-dlp — extraction of player_url is regularly patched as YouTube changes.","If calling internals yourself, always resolve player_url via _extract_player_url first and pass it to _unthrottle_format_urls/_decrypt_nsig.","As a stopgap, accept throttled URLs (skip nsig) — downloads still work but may be rate-limited by YouTube."],"exampleFix":"// before\nself._decrypt_nsig(n, video_id, None)\n\n// after\nplayer_url = self._extract_player_url(...) or self._search_regex(\n    r'jsUrl\":\\s*\"([^\"]+)', player_response, 'player url')\nself._decrypt_nsig(n, video_id, player_url)","handlingStrategy":"validation","validationCode":"def can_decrypt_nsig(player_url) -> bool:\n    return player_url is not None","typeGuard":null,"tryCatchPattern":"try:\n    url = self._decrypt_nsig(n, video_id, player_url)\nexcept ExtractorError as e:\n    if 'without player_url' in str(e):\n        player_url = self._extract_player_url(...) or resolve_player_url(video_id)\n        url = self._decrypt_nsig(n, video_id, player_url)\n    else:\n        raise","preventionTips":["Always resolve player_url from the watch page / player response before nsig work.","Thread player_url explicitly through any custom extraction pipeline; never assume internals will find it."],"tags":["youtube","nsig","player-url","internal-api"],"backgroundTag":null,"analyzedSha":"956b8c585591b401a543e409accb163eeaaa1193","analyzedAt":"2026-08-14T18:59:47.863Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}