ytdl-org/youtube-dl · error · ExtractorError
%s said: %s
Error message
%s said: %s
What it means
Raised by BiliBiliBangumiIE._report_error when a Bangumi API call returns a result dict containing a 'message' key: the error interpolates the extractor name ('Bilibili Bangumi') and the API's own message text (e.g. 'Bilibili Bangumi said: Sorry, the video is only available in mainland China'). Expected=True — a server-side rejection carried through verbatim.
Source
Thrown at youtube_dl/extractor/bilibili.py:117
'timestamp': 1488382634,
'upload_date': '20170301',
},
'params': {
'skip_download': True, # Test metadata only
},
}]
}, {
# new BV video id format
'url': 'https://www.bilibili.com/video/BV1JE411F741',
'only_matching': True,
}]
_APP_KEY = 'iVGUTjsxvpLeuDCf'
_BILIBILI_KEY = 'aHRmhWMLkdeMuILqORnYZocwMBpMEOdt'
def _report_error(self, result):
if 'message' in result:
raise ExtractorError('%s said: %s' % (self.IE_NAME, result['message']), expected=True)
elif 'code' in result:
raise ExtractorError('%s returns error %d' % (self.IE_NAME, result['code']), expected=True)
else:
raise ExtractorError('Can\'t extract Bangumi episode ID')
def _real_extract(self, url):
url, smuggled_data = unsmuggle_url(url, {})
mobj = re.match(self._VALID_URL, url)
video_id = mobj.group('id') or mobj.group('id_bv')
anime_id = mobj.group('anime_id')
webpage = self._download_webpage(url, video_id)
if 'anime/' not in url:
cid = self._search_regex(
r'\bcid(?:["\']:|=)(\d+)', webpage, 'cid',
default=None
) or compat_parse_qs(self._search_regex(View on GitHub (pinned to 956b8c5855)
Solutions
- Read the interpolated message — it is Bilibili's own reason; 'mainland China' messages require a CN IP (VPN) or a different source.
- For removed episodes, check the bangumi page in a browser for replacement ids.
- If all requests fail with auth-style messages, the bundled _APP_KEY/_BILIBILI_KEY may be stale — update them from the current web app and report upstream.
- Handle as expected in batch tools: log and skip rather than abort the run.
Defensive patterns
Strategy: try-catch
Try / catch
try:
ydl.extract_info(bangumi_url)
except ExtractorError as e:
msg = str(e)
if 'said:' in msg:
if 'mainland China' in msg:
raise RegionBlocked(msg) from e
log_api_rejection(bangumi_url, msg) # server-side reason; not retryable as-is
else:
raise Prevention
- Route bangumi requests through a mainland-China IP for region-locked content.
- Batch tools should log 'said:' rejections and continue, not abort.
- Keep extractor versions current — Bilibili rotates keys and envelopes over time.
When it happens
Trigger: Calling the Bangumi playurl/season API (signed with _APP_KEY/_BILIBILI_KEY) for content the API refuses: region-locked videos for non-mainland-China IPs, removed episodes, or parameter errors — any response whose JSON includes a non-empty 'message' field hits this branch before the code branch.
Common situations: Non-CN IPs extracting region-locked bangumi (the dominant case); episodes pulled for licensing reasons; stale APP_KEY/signing secret after Bilibili rotated it, causing auth-reject messages; wrong anime/episode ids producing API error messages.
Related errors
AI-assisted analysis of ytdl-org/youtube-dl@956b8c5855 (2026-08-14).
Data as JSON: /api/errors/ebd47824a695e45e.
Report an issue: GitHub.