ytdl-org/youtube-dl · error · ExtractorError

%s said: %s

Error message

%s said: %s

What it means

Raised by the Vbox7 extractor when the JSON from https://www.vbox7.com/aj/player/item/options?vid=<id> contains a truthy top-level 'error' member (read via traverse_obj). The site's own error text is propagated with the extractor name. It is an expected site-side rejection: removed video, bad vid, or blocked request.

Source

Thrown at youtube_dl/extractor/vbox7.py:123

                    kwargs['transform_source'] = fix_chars
                    kwargs = compat_kwargs(kwargs)

        return super(Vbox7IE, self)._parse_json(
            json_string, video_id, *args, **kwargs)

    def _real_extract(self, url):
        video_id = self._match_id(url)
        url = 'https://vbox7.com/play:%s' % (video_id,)

        now = time.time()
        response = self._download_json(
            'https://www.vbox7.com/aj/player/item/options', video_id,
            query={'vid': video_id}, headers={'Referer': url})
        # estimate time to which possible `ago` member is relative
        now = now + 0.5 * (time.time() - now)

        if traverse_obj(response, 'error'):
            raise ExtractorError(
                '%s said: %s' % (self.IE_NAME, response['error']), expected=True)

        src_url = traverse_obj(response, ('options', 'src', T(url_or_none))) or ''

        fmt_base = url_basename(src_url).rsplit('.', 1)[0].rsplit('_', 1)[0]
        if fmt_base in ('na', 'vn'):
            self.raise_geo_restricted(countries=self._GEO_COUNTRIES)

        ext = determine_ext(src_url)
        if ext == 'mpd':
            # extract MPD
            try:
                formats, subtitles = self._extract_mpd_formats_and_subtitles(
                    src_url, video_id, 'dash', fatal=False)
            except KeyError:  # fatal doesn't catch this
                self.report_warning('Failed to parse MPD manifest')
                formats, subtitles = [], {}
        elif ext != 'm3u8':

View on GitHub (pinned to 956b8c5855)

Solutions

  1. Verify the video plays at https://vbox7.com/play:<vid> in a browser.
  2. Check the raw JSON of the options endpoint (with the Referer header set) to see what error the site returns.
  3. If the API shape changed, update the extractor's traversal of response (e.g. error now nested or named differently).
  4. Pass through the site's error message to the end user; it is expected and not retryable.
Defensive patterns

Strategy: try-catch

Validate before calling

resp = ydl.extract_info('https://www.vbox7.com/aj/player/item/options?vid=' + video_id,
                          download=False, headers={'Referer': 'https://vbox7.com/play:' + video_id})
if resp and resp.get('error'):
    skip(video_id, resp['error'])

Try / catch

try:
    ydl.extract_info(url)
except ExtractorError as e:
    if e.expected and 'said:' in str(e):
        log_skip(url, str(e))
    else:
        raise

Prevention

When it happens

Trigger: Extracting a vbox7.com play URL whose options endpoint answers with {"error": "..."} — deleted/private videos, malformed vid, or missing Referer header causing the API to reject the call.

Common situations: Vbox7 redesigns its player API and changes the error field or adds anti-bot checks; old video ids from playlists are removed; requests without the Referer: https://vbox7.com/play:<vid> header get rejected.

Related errors


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