ytdl-org/youtube-dl · error · ExtractorError

Cannot extract signature timestamp without player url

Error message

Cannot extract signature timestamp without player url

What it means

Raised by YoutubeIE's signature-timestamp helper (used around embed/age-gate flows) when no STS could be obtained from the cached player JS version or ytcfg, and player_url is None so the player JS cannot be loaded to search for signatureTimestamp. With fatal=True it raises; otherwise it only warns and returns None.

Source

Thrown at youtube_dl/extractor/youtube.py:2164

    def _extract_signature_timestamp(self, video_id, player_url, ytcfg=None, fatal=False):
        """
        Extract signatureTimestamp (sts)

        Required to tell API what sig/player version is in use.
        """
        sts = traverse_obj(
            (self._get_player_js_version(), ytcfg),
            (0, 0),
            (1, 'STS'),
            expected_type=int_or_none)

        if sts:
            return sts

        if not player_url:
            error_msg = 'Cannot extract signature timestamp without player url'
            if fatal:
                raise ExtractorError(error_msg)
            self.report_warning(error_msg)
            return None

        sts = self._load_player_data_from_cache('sts', player_url)
        if sts:
            return sts

        # Attempt to extract from player
        code = self._load_player(video_id, player_url, fatal=fatal)
        sts = int_or_none(self._search_regex(
            r'(?:signatureTimestamp|sts)\s*:\s*(?P<sts>[0-9]{5})', code or '',
            'JS player signature timestamp', group='sts', fatal=fatal))
        if sts:
            self._store_player_data_to_cache('sts', player_url, sts)

        return sts

    def _mark_watched(self, video_id, player_response):

View on GitHub (pinned to 956b8c5855)

Solutions

  1. Ensure the page/player response that contains the player URL is fetched (cookies for age-gated content) before STS extraction.
  2. Update youtube-dl — the STS fallback chain (ytcfg key, player JS regex '(?:signatureTimestamp|sts)\s*:\s*[0-9]{5}') is patched when YouTube moves it.
  3. If calling internally, pass fatal=False when a missing STS should degrade gracefully.
  4. Provide cookies via --cookies so the full player config, including player_url and STS, is present.

Example fix

// before
sts = self._extract_signature_timestamp(video_id, player_url=None, fatal=True)

// after
player_url = self._extract_player_url(ytcfg, webpage) or fatal_player_url
sts = self._extract_signature_timestamp(video_id, player_url, fatal=False)
Defensive patterns

Strategy: fallback

Validate before calling

sts = traverse_obj((self._get_player_js_version(), ytcfg), (0, 0), (1, 'STS'), expected_type=int_or_none)
if not sts and player_url is None:
    player_url = self._extract_player_url(ytcfg, webpage)  # resolve before STS call

Try / catch

try:
    sts = self._extract_signature_timestamp(video_id, player_url)
except ExtractorError as e:
    if 'without player url' in str(e):
        return None  # degrade: proceed without STS where the flow allows
    raise

Prevention

When it happens

Trigger: Requesting player data for an embedded/age-restricted video where neither _get_player_js_version()/ytcfg['STS'] nor cache yields a timestamp, and the caller passed no player_url — typical when the player config scrape failed upstream.

Common situations: Age-gated videos fetched without cookies; YouTube page changes removing the STS from ytcfg; third-party embeds where the player URL is absent from the response.

Related errors


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