ytdl-org/youtube-dl · error · ExtractorError

%s said: %s

Error message

%s said: %s

What it means

Raised by the FilmOn VOD extractor when the API request to https://www.filmon.com/api/vod/movie?id=<id> fails with an HTTP error and the error body contains a 'reason' field. The extractor re-raises the server's own reason prefixed with the extractor name. It is marked expected=True, so it represents a server-side rejection (bad ID, removed movie, region block) rather than a parsing bug.

Source

Thrown at youtube_dl/extractor/filmon.py:48

        'info_dict': {
            'id': '2825',
            'title': 'Popeye Series 1',
            'description': 'The original series of Popeye.',
        },
        'playlist_mincount': 8,
    }]

    def _real_extract(self, url):
        video_id = self._match_id(url)

        try:
            response = self._download_json(
                'https://www.filmon.com/api/vod/movie?id=%s' % video_id,
                video_id)['response']
        except ExtractorError as e:
            if isinstance(e.cause, compat_HTTPError):
                errmsg = self._parse_json(e.cause.read().decode(), video_id)['reason']
                raise ExtractorError('%s said: %s' % (self.IE_NAME, errmsg), expected=True)
            raise

        title = response['title']
        description = strip_or_none(response.get('description'))

        if response.get('type_id') == 1:
            entries = [self.url_result('filmon:' + episode_id) for episode_id in response.get('episodes', [])]
            return self.playlist_result(entries, video_id, title, description)

        QUALITY = qualities(('low', 'high'))
        formats = []
        for format_id, stream in response.get('streams', {}).items():
            stream_url = stream.get('url')
            if not stream_url:
                continue
            formats.append({
                'format_id': format_id,
                'url': stream_url,

View on GitHub (pinned to 956b8c5855)

Solutions

  1. Open https://www.filmon.com/vod/view/movie-<id> in a browser to confirm the title is still listed and playable in your region
  2. Correct the movie id if it was mistyped or truncated from the URL
  3. Use a region-appropriate exit IP (FilmOn VOD rights vary by country)
  4. Retry later if the reason text indicates a temporary API problem

Example fix

# before
youtube_dl 'https://www.filmon.com/vod/view/movie-999999'
# ERROR: FilmOn said: <reason>

# after
youtube_dl 'https://www.filmon.com/vod/view/movie-12345'  # valid, in-catalog id
Defensive patterns

Strategy: try-catch

Try / catch

try:
    info = ydl.extract_info('filmon:movie-%s' % movie_id)
except ExtractorError as e:
    if str(e).startswith('FilmOn said:'):
        drop_movie_from_catalog(movie_id)  # server rejected; do not retry blindly

Prevention

When it happens

Trigger: _download_json raises ExtractorError whose cause is a compat_HTTPError; the code reads the response body and parses 'reason' from the JSON. Produced by requesting a nonexistent or delisted movie id, a VOD item not licensed for your region, or transient FilmOn API failures.

Common situations: Following outdated filmon: movie links; scraping channel guides whose movie entries expired; hitting the API from a region where FilmOn has no VOD rights.

Related errors


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