ytdl-org/youtube-dl · error · ExtractorError

Cannot decrypt nsig without player_url

Error message

Cannot decrypt nsig without player_url

What it means

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.

Source

Thrown at youtube_dl/extractor/youtube.py:1986

        return inner

    def _decrypt_signature(self, s, video_id, player_url):
        """Turn the encrypted s field into a working signature"""
        extract_sig = self._cached(
            self._extract_signature_function, 'sig', player_url, self._signature_cache_id(s))
        func = extract_sig(video_id, player_url, s)
        self._print_sig_code(func, s)
        return func(s)

    # from yt-dlp
    # See also:
    # 1. https://github.com/ytdl-org/youtube-dl/issues/29326#issuecomment-894619419
    # 2. https://code.videolan.org/videolan/vlc/-/blob/4fb284e5af69aa9ac2100ccbdd3b88debec9987f/share/lua/playlist/youtube.lua#L116
    # 3. https://github.com/ytdl-org/youtube-dl/issues/30097#issuecomment-950157377
    def _decrypt_nsig(self, n, video_id, player_url):
        """Turn the encrypted n field into a working signature"""
        if player_url is None:
            raise ExtractorError('Cannot decrypt nsig without player_url')

        try:
            jsi, player_id, func_code = self._extract_n_function_code(video_id, player_url)
        except ExtractorError as e:
            raise ExtractorError('Unable to extract nsig function code', cause=e)
        if self.get_param('youtube_print_sig_code'):
            self.to_screen('Extracted nsig function from {0}:\n{1}\n'.format(
                player_id, func_code[1]))

        try:
            extract_nsig = self._cached(self._extract_n_function_from_code, 'nsig func', player_url)
            ret = extract_nsig(jsi, func_code)(n)
        except JSInterpreter.Exception as e:
            self.report_warning(
                '%s (%s %s)' % (
                    'Unable to decode n-parameter: expect download to be blocked or throttled',
                    error_to_compat_str(e),
                    traceback.format_exc()),

View on GitHub (pinned to 956b8c5855)

Solutions

  1. Ensure the full watch page or player response is downloaded so player_url can be extracted before format URL processing.
  2. Update youtube-dl/yt-dlp — extraction of player_url is regularly patched as YouTube changes.
  3. If calling internals yourself, always resolve player_url via _extract_player_url first and pass it to _unthrottle_format_urls/_decrypt_nsig.
  4. As a stopgap, accept throttled URLs (skip nsig) — downloads still work but may be rate-limited by YouTube.

Example fix

// before
self._decrypt_nsig(n, video_id, None)

// after
player_url = self._extract_player_url(...) or self._search_regex(
    r'jsUrl":\s*"([^"]+)', player_response, 'player url')
self._decrypt_nsig(n, video_id, player_url)
Defensive patterns

Strategy: validation

Validate before calling

def can_decrypt_nsig(player_url) -> bool:
    return player_url is not None

Try / catch

try:
    url = self._decrypt_nsig(n, video_id, player_url)
except ExtractorError as e:
    if 'without player_url' in str(e):
        player_url = self._extract_player_url(...) or resolve_player_url(video_id)
        url = self._decrypt_nsig(n, video_id, player_url)
    else:
        raise

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of ytdl-org/youtube-dl@956b8c5855 (2026-08-14). Data as JSON: /api/errors/918622380a294c0a. Report an issue: GitHub.