ytdl-org/youtube-dl · error · ExtractorError

message

Error message

message

What it means

Raised in BrightcoveNewIE's policy-key retry loop when the playback API answers 401/403. The body is parsed as JSON and the message is json_data.get('message') or json_data['error_code']. Before re-raising it handles two special cases: error_subcode CLIENT_GEO raises a geo-restricted error, and error_code INVALID_POLICY_KEY with a freshly extracted policy key clears the cached key and retries once.

Source

Thrown at youtube_dl/extractor/brightcove.py:656

        for _ in range(2):
            if not policy_key:
                policy_key = extract_policy_key()
                policy_key_extracted = True
            headers['Accept'] = 'application/json;pk=%s' % policy_key
            try:
                json_data = self._download_json(api_url, video_id, headers=headers)
                break
            except ExtractorError as e:
                if isinstance(e.cause, compat_HTTPError) and e.cause.code in (401, 403):
                    json_data = self._parse_json(e.cause.read().decode(), video_id)[0]
                    message = json_data.get('message') or json_data['error_code']
                    if json_data.get('error_subcode') == 'CLIENT_GEO':
                        self.raise_geo_restricted(msg=message)
                    elif json_data.get('error_code') == 'INVALID_POLICY_KEY' and not policy_key_extracted:
                        policy_key = None
                        store_pk(None)
                        continue
                    raise ExtractorError(message, expected=True)
                raise

        errors = json_data.get('errors')
        if errors and errors[0].get('error_subcode') == 'TVE_AUTH':
            custom_fields = json_data['custom_fields']
            tve_token = self._extract_mvpd_auth(
                smuggled_data['source_url'], video_id,
                custom_fields['bcadobepassrequestorid'],
                custom_fields['bcadobepassresourceid'])
            json_data = self._download_json(
                api_url, video_id, headers={
                    'Accept': 'application/json;pk=%s' % policy_key
                }, query={
                    'tveToken': tve_token,
                })

        if content_type == 'playlist':
            return self.playlist_result(

View on GitHub (pinned to 956b8c5855)

Solutions

  1. Clear the cached policy key: youtube-dl --no-cache-dir (or remove the cache directory) and retry so a fresh key is scraped from the player page.
  2. If the error is geo related (CLIENT_GEO shows as geo-restricted), use --proxy or run from an allowed country.
  3. Update to yt-dlp for current policy-key extraction logic.
  4. Confirm the account/player id in the URL is correct — wrong ids commonly produce 401/403 JSON errors.

Example fix

# before
ydl.extract(url)  # 403 INVALID_POLICY_KEY from stale cache

# after
from youtube_dl import YoutubeDL
with YoutubeDL({'no-cache-dir': True}) as ydl:
    ydl.extract(url)
Defensive patterns

Strategy: retry

Try / catch

from youtube_dl.utils import ExtractorError, GeoRestrictedError
try:
    info = ydl_no_cache.extract_info(url, download=False)
except GeoRestrictedError:
    info = ydl_with_proxy.extract_info(url, download=False)
except ExtractorError as e:
    if 'POLICY_KEY' in str(e):  # retry once with a cold cache
        info = YoutubeDL({'no_cache-dir': True}).extract_info(url, download=False)
    else:
        raise

Prevention

When it happens

Trigger: HTTP 401/403 from the playback API where the JSON error is neither CLIENT_GEO nor a first-time INVALID_POLICY_KEY — e.g. an API key/typo'd policy key, an expired token, or access-control rejection. CLIENT_GEO produces a GeoRestrictedError instead; persistent INVALID_POLICY_KEY after one retry falls through to this raise.

Common situations: Stale cached policy key in youtube-dl's cache after the site rotated keys; extracting from a region the account blocks; running an old youtube-dl against a changed Brightcove API.

Related errors


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