ytdl-org/youtube-dl · error · UnsupportedError

Unsupported URL: %s

Error message

Unsupported URL: %s

What it means

Raised as UnsupportedError at the end of BrightcoveLegacyIE._real_extract when the URL could not be converted into anything the extractor supports: it only proceeds if it can derive a publisher_id (from an account id or by base64-decoding the second part of a playerKey), otherwise it falls through to 'raise UnsupportedError(url)'. UnsupportedError tells youtube-dl's dispatcher that this IE cannot handle the link.

Source

Thrown at youtube_dl/extractor/brightcove.py:338

                            'http://link.brightcove.com/services/player/bcpid' + player_id[0],
                            video_id, headers=headers, fatal=False)
                        if player_page:
                            player_key = self._search_regex(
                                r'<param\s+name="playerKey"\s+value="([\w~,-]+)"',
                                player_page, 'player key', fatal=False)
                if player_key:
                    enc_pub_id = player_key.split(',')[1].replace('~', '=')
                    publisher_id = struct.unpack('>Q', base64.urlsafe_b64decode(enc_pub_id))[0]
            if publisher_id:
                brightcove_new_url = 'http://players.brightcove.net/%s/default_default/index.html?videoId=%s' % (publisher_id, video_id)
                if referer:
                    brightcove_new_url = smuggle_url(brightcove_new_url, {'referrer': referer})
                return self.url_result(brightcove_new_url, BrightcoveNewIE.ie_key(), video_id)
        # TODO: figure out if it's possible to extract playlistId from playerKey
        # elif 'playerKey' in query:
        #     player_key = query['playerKey']
        #     return self._get_playlist_info(player_key[0])
        raise UnsupportedError(url)


class BrightcoveNewIE(AdobePassIE):
    IE_NAME = 'brightcove:new'
    _VALID_URL = r'https?://players\.brightcove\.net/(?P<account_id>\d+)/(?P<player_id>[^/]+)_(?P<embed>[^/]+)/index\.html\?.*(?P<content_type>video|playlist)Id=(?P<video_id>\d+|ref:[^&]+)'
    _TESTS = [{
        'url': 'http://players.brightcove.net/929656772001/e41d32dc-ec74-459e-a845-6c69f7b724ea_default/index.html?videoId=4463358922001',
        'md5': 'c8100925723840d4b0d243f7025703be',
        'info_dict': {
            'id': '4463358922001',
            'ext': 'mp4',
            'title': 'Meet the man behind Popcorn Time',
            'description': 'md5:eac376a4fe366edc70279bfb681aea16',
            'duration': 165.768,
            'timestamp': 1441391203,
            'upload_date': '20150904',
            'uploader_id': '929656772001',
            'formats': 'mincount:20',

View on GitHub (pinned to 956b8c5855)

Solutions

  1. Use the full new-style player URL: https://players.brightcove.net/<account_id>/<player>_default/index.html?videoId=<video_id> — the account id is the numeric path segment.
  2. If only a playerKey is known, decode the publisher id yourself: player_key.split(',')[1].replace('~','=') then base64 urlsafe-decode and struct.unpack('>Q', ...), and build the players.brightcove.net URL.
  3. Update to yt-dlp, which has extended Brightcove URL support.
  4. Extract from the original article page rather than the bare player URL.

Example fix

# before
ydl.extract('http://link.brightcove.com/services/player/bcpid123')  # no account info derivable

# after
account_id = struct.unpack('>Q', base64.urlsafe_b64decode(player_key.split(',')[1].replace('~', '=')))[0]
ydl.extract('http://players.brightcove.net/%d/default_default/index.html?videoId=%s' % (account_id, video_id))
Defensive patterns

Strategy: validation

Validate before calling

import re, struct, base64
# Validate before extracting: URL must expose an account id or decodable playerKey
m = re.search(r'players\.brightcove\.net/(\d+)/', url)
if not m and 'playerKey' not in url:
    raise ValueError('URL carries no Brightcove account id; cannot extract')
if 'playerKey=' in url:
    key = re.search(r'playerKey=([^&]+)', url).group(1)
    account = struct.unpack('>Q', base64.urlsafe_b64decode(key.split(',')[1].replace('~', '=')))[0]

Try / catch

from youtube_dl.utils import UnsupportedError
try:
    ydl.extract_info(url)
except UnsupportedError:
    # let youtube-dl try other extractors / generic
    ydl.extract_info(url, force_generic_extractor=True)

Prevention

When it happens

Trigger: A URL matched the Brightcove legacy IE pattern but contained neither a usable account/publisher id nor a playerKey whose base64 portion decodes to a publisher id; also reached when 'playerKey' playlist handling is disabled (the elif branch is commented out in the source).

Common situations: Hand-crafted or stale brightcove URLs missing the account id; pages that changed their embed scheme so the URL captured by the user (or a generic extractor pass) no longer carries the ids the extractor needs.

Related errors


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