ytdl-org/youtube-dl · error · ExtractorError

%s said: %s

Error message

%s said: %s

What it means

Raised by TVPlayerIE when the stream request to tvplayer.com returns an HTTP error whose JSON body (['tvplayer']['response']['error']) carries an error string. The extractor catches the compat_HTTPError, parses the error payload, and rethrows it as an expected error. Typical payloads are 'bad stream request', geo or account errors.

Source

Thrown at youtube_dl/extractor/tvplayer.py:73

        platform = try_get(
            context, lambda x: x['platform']['key'], compat_str) or 'firefox'

        try:
            response = self._download_json(
                'http://api.tvplayer.com/api/v2/stream/live',
                display_id, 'Downloading JSON stream', headers={
                    'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
                }, data=urlencode_postdata({
                    'id': resource_id,
                    'service': 1,
                    'platform': platform,
                    'validate': validate,
                }))['tvplayer']['response']
        except ExtractorError as e:
            if isinstance(e.cause, compat_HTTPError):
                response = self._parse_json(
                    e.cause.read().decode(), resource_id)['tvplayer']['response']
                raise ExtractorError(
                    '%s said: %s' % (self.IE_NAME, response['error']), expected=True)
            raise

        formats = self._extract_m3u8_formats(response['stream'], display_id, 'mp4')
        self._sort_formats(formats)

        return {
            'id': resource_id,
            'display_id': display_id,
            'title': self._live_title(title),
            'formats': formats,
            'is_live': True,
        }

View on GitHub (pinned to 956b8c5855)

Solutions

  1. Match the error text: 'geo' variants need a UK IP; account variants need a TVPlayer subscription plus --username/--password.
  2. Verify the channel still exists on tvplayer.com and copy a fresh URL.
  3. Log in with credentials so the stream request carries your entitlements.
  4. Update to yt-dlp; the TVPlayer service has since shut down/changed, so newer code or a different source is needed.
Defensive patterns

Strategy: try-catch

Type guard

def tvplayer_error(response: dict) -> bool:
    return bool((response.get('tvplayer', {}).get('response') or {}).get('error'))

Try / catch

try:
    ydl.extract_info(url)
except ExtractorError as e:
    if 'said:' in str(e):
        handle_tvplayer_message(str(e).split('said:')[-1].strip())
    else:
        raise

Prevention

When it happens

Trigger: POSTing the form (id, service=1, platform, validate) to the stream endpoint and receiving an HTTP 4xx/5xx whose body decodes to a tvplayer response with a non-null 'error' key — e.g. 'Channel not available on your account', geo refusal, or invalid resource id.

Common situations: UK-only channels requested from outside the UK, free-tier accounts requesting premium channels, dead channel ids after the service rebranded, changed validate token.

Related errors


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