ytdl-org/youtube-dl · error · ExtractorError

%s said: %s

Error message

%s said: %s

What it means

Raised inside AfreecaTV's view-info loop when the video info XML returns a non-empty flag other than PARTIAL_ADULT. For flag == 'ADULT' the message is the extractor's own 'Only users older than 19 are able to watch this video...'; for any other unknown flag the raw flag string is embedded into '%s said: %s'. Marked expected=True.

Source

Thrown at youtube_dl/extractor/afreecatv.py:270

                video_id, headers={
                    'Referer': url,
                }, query=query)

            flag = xpath_text(video_xml, './track/flag', 'flag', default=None)
            if flag and flag == 'SUCCEED':
                break
            if flag == 'PARTIAL_ADULT':
                self._downloader.report_warning(
                    'In accordance with local laws and regulations, underage users are restricted from watching adult content. '
                    'Only content suitable for all ages will be downloaded. '
                    'Provide account credentials if you wish to download restricted content.')
                partial_view = True
                continue
            elif flag == 'ADULT':
                error = 'Only users older than 19 are able to watch this video. Provide account credentials to download this content.'
            else:
                error = flag
            raise ExtractorError(
                '%s said: %s' % (self.IE_NAME, error), expected=True)
        else:
            raise ExtractorError('Unable to download video info')

        video_element = video_xml.findall(compat_xpath('./track/video'))[-1]
        if video_element is None or video_element.text is None:
            raise ExtractorError(
                'Video %s does not exist' % video_id, expected=True)

        video_url = video_element.text.strip()

        title = xpath_text(video_xml, './track/title', 'title', fatal=True)

        uploader = xpath_text(video_xml, './track/nickname', 'uploader')
        uploader_id = xpath_text(video_xml, './track/bj_id', 'uploader id')
        duration = int_or_none(xpath_text(
            video_xml, './track/duration', 'duration'))
        thumbnail = xpath_text(video_xml, './track/titleImage', 'thumbnail')

View on GitHub (pinned to 956b8c5855)

Solutions

  1. For ADULT: supply --username/--password of an age-verified (19+) AfreecaTV account
  2. Complete age verification on the AfreecaTV website first if the account lacks it
  3. For unknown flag strings, decode the site's flag meaning from the channel page before retrying

Example fix

# before
youtube-dl 'http://play.afreecatv.com/abc123'

# after
youtube-dl --username user --password pass 'http://play.afreecatv.com/abc123'  # 19+ verified account
Defensive patterns

Strategy: try-catch

Try / catch

try:
    ydl.extract_info(url)
except ExtractorError as e:
    if 'older than 19' in str(e):
        requeue_with_credentials(url)  # needs 19+ verified account
    elif 'afreecatv said:' in str(e).lower():
        log_unknown_flag(url, str(e))  # unknown flag string, diagnostic value
    else:
        raise

Prevention

When it happens

Trigger: Video info XML contains <flag>ADULT</flag> while extracting without a logged-in adult-verified account; any other unknown flag string returned by the station info API.

Common situations: Downloading 19+ content anonymously; account without age verification; region-locked flags on Korean-only material.

Related errors


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