ytdl-org/youtube-dl · error · ExtractorError

%s said: %s

Error message

%s said: %s

What it means

Raised by the MSN extractor when the playlist-parsing pass produced zero entries, and the webpage instead carries a data-error="..." attribute. The extractor surfaces the site's own error text (e.g. content removed or region unavailable) prefixed with 'MSN said:'. It is expected=True, so it terminates that URL cleanly.

Source

Thrown at youtube_dl/extractor/msn.py:169

            entries.append({
                'id': video_id,
                'display_id': display_id,
                'title': title,
                'description': video.get('description'),
                'thumbnail': video.get('headlineImage', {}).get('url'),
                'duration': int_or_none(video.get('durationSecs')),
                'uploader': video.get('sourceFriendly'),
                'uploader_id': video.get('providerId'),
                'creator': video.get('creator'),
                'subtitles': subtitles,
                'formats': formats,
            })

        if not entries:
            error = unescapeHTML(self._search_regex(
                r'data-error=(["\'])(?P<error>.+?)\1',
                webpage, 'error', group='error'))
            raise ExtractorError('%s said: %s' % (self.IE_NAME, error), expected=True)

        return self.playlist_result(entries, page_id)

View on GitHub (pinned to 956b8c5855)

Solutions

  1. Read the embedded site message — it is the site's own explanation (removal, geo block) and dictates what to do next.
  2. Verify the URL still plays in a browser; if not, the link is dead and no tool can download it.
  3. Update youtube-dl/youtube-dl to get the latest MSN extractor in case the page format changed.
  4. If the content is geo-blocked, retry with --geo-verify-proxy or a proxy for the allowed region.

Example fix

youtube-dl --geo-verify-proxy 'https://www.msn.com/en-us/video/...'
Defensive patterns

Strategy: try-catch

Validate before calling

import requests
html = requests.get(url).text
import re
m = re.search(r'data-error=(["\'])(?P<e>.+?)\1', html)
if m and '<video' not in html.lower():
    print('site error:', m.group('e'))  # skip before invoking the extractor

Try / catch

except ExtractorError as e:
    if e.expected and str(e).startswith('MSN said:'):
        record_site_error(url, str(e))  # message carries the site's own reason
    else:
        raise

Prevention

When it happens

Trigger: Calling the MSNIE on an MSN video/playlist page whose JSON blob yields no entries and whose HTML contains a data-error='...' attribute, which is unescaped and reported verbatim.

Common situations: Dead or removed MSN embeds; region-locked MSN content; MSN page layout/JSON changes after an extractor update lags; URLs scraped from third-party sites that reference expired articles.

Related errors


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