ytdl-org/youtube-dl · error · ExtractorError
Cannot identify player %r
Error message
Cannot identify player %r
What it means
Raised by YoutubeIE._extract_player_info when the player URL does not match _PLAYER_INFO_RE, so the player version/id cannot be parsed. The original regex failure is chained as cause. This almost always means YouTube changed its player URL format (the code builds URLs like https://www.youtube.com/s/player/<version>/player_ias.vflset/en_US/base.js).
Source
Thrown at youtube_dl/extractor/youtube.py:1774
def _download_player_url(self, video_id, fatal=False):
res = self._download_webpage(
'https://www.youtube.com/iframe_api',
note='Downloading iframe API JS', video_id=video_id, fatal=fatal)
player_version = self._search_regex(
r'player\\?/([0-9a-fA-F]{8})\\?/', res or '', 'player version', fatal=fatal,
default=NO_DEFAULT if res else None) or None
return player_version and 'https://www.youtube.com/s/player/{0}/player_ias.vflset/en_US/base.js'.format(player_version)
def _signature_cache_id(self, example_sig):
""" Return a string representation of a signature """
return '.'.join(compat_str(len(part)) for part in example_sig.split('.'))
def _extract_player_info(self, player_url):
try:
return self._search_regex(
self._PLAYER_INFO_RE, player_url, 'player info', group='id')
except ExtractorError as e:
raise ExtractorError(
'Cannot identify player %r' % (player_url,), cause=e)
def _player_js_cache_key(self, player_url, extra_id=None, _cache={}):
if player_url not in _cache:
player_id = self._extract_player_info(player_url)
player_path = remove_start(
compat_urllib_parse.urlparse(player_url).path,
'/s/player/{0}/'.format(player_id))
variant = next((k for k, v in self._PLAYER_JS_VARIANT_MAP
if v == player_path), None)
if not variant:
variant = next(
(k for k, v in self._PLAYER_JS_VARIANT_MAP
if re.match(re.escape(v).replace('en_US', r'\w+') + '$', player_path)),
None)
if not variant:
self.write_debug(
'Unable to determine player JS variant\n'View on GitHub (pinned to 956b8c5855)
Solutions
- Update youtube-dl to the latest release (or yt-dlp, which tracks player URL changes much faster) — regex fixes ship as patches.
- Print player_url (the message includes it via %r) and compare with the current base.js URL in a browser; adjust _PLAYER_INFO_RE if you maintain a fork.
- Clear cached player data so stale player URLs are not reused (the signature cache keys off player_url).
- If embedding the library, pin to a known-good version and schedule prompt updates, since YouTube-side changes break old regexes.
Defensive patterns
Strategy: try-catch
Validate before calling
import re
PLAYER_INFO_RE = YoutubeIE._PLAYER_INFO_RE
def player_url_parseable(player_url: str) -> bool:
return player_url is not None and re.search(PLAYER_INFO_RE, player_url) is not None Try / catch
try:
...extraction...
except ExtractorError as e:
if 'Cannot identify player' in str(e):
update_youtube_dl() # player URL format changed; update first
raise Prevention
- Keep youtube-dl (or yt-dlp) current; player URL formats change without notice.
- In long-running services, catch this error to trigger a self-update before retrying.
When it happens
Trigger: Any code path that calls _extract_player_info (signature deciphering, nsig decryption, STS extraction) with a player_url whose shape no longer matches _PLAYER_INFO_RE — e.g. new URL schemes, a different path layout, or a None/relative URL that slipped through.
Common situations: YouTube rolls out a new player URL pattern; youtube-dl version is old relative to YouTube changes; the player URL came from a cached page or an embedded player host with a different path.
Related errors
- Unable to find feed id
- Cannot decrypt nsig without player_url
- Unable to extract nsig function code
- Cannot extract signature timestamp without player url
- Invalid URL: %s
AI-assisted analysis of ytdl-org/youtube-dl@956b8c5855 (2026-08-14).
Data as JSON: /api/errors/8fa617a3a48bf4ec.
Report an issue: GitHub.