ytdl-org/youtube-dl · error · ExtractorError
Can't extract Bangumi episode ID
Error message
Can't extract Bangumi episode ID
What it means
Final branch of BiliBiliBangumiIE._report_error: the API result dict contains neither 'message' nor 'code', so the extractor cannot extract a Bangumi episode ID from it and raises this bare extraction failure (not expected=True — it signals a parsing/schema problem rather than a clean server rejection). It means the API responded with an object whose shape the extractor does not understand.
Source
Thrown at youtube_dl/extractor/bilibili.py:121
'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(
[r'EmbedPlayer\([^)]+,\s*"([^"]+)"\)',
r'EmbedPlayer\([^)]+,\s*\\"([^"]+)\\"\)',
r'<iframe[^>]+src="https://secure\.bilibili\.com/secure,([^"]+)"'],
webpage, 'player parameters'))['cid'][0]View on GitHub (pinned to 956b8c5855)
Solutions
- Dump the raw API response (add a temporary log before _report_error) to see the actual shape.
- If the envelope changed, update the field access feeding _report_error and the episode-id extraction (bilibili.py:121).
- Confirm the signed request (APP_KEY/secret) is still valid — auth failures sometimes return bodies without message/code.
- Update youtube-dl / yt-dlp: newer versions track Bilibili API changes and this extractor was heavily reworked there.
Example fix
// before
else:
raise ExtractorError('Can\'t extract Bangumi episode ID')
// after: include a sample of the payload so the schema mismatch is diagnosable
else:
raise ExtractorError('Can\'t extract Bangumi episode ID (unexpected API result: %.200r)' % (result,)) Defensive patterns
Strategy: try-catch
Try / catch
try:
ydl.extract_info(bangumi_url)
except ExtractorError as e:
if "Can't extract Bangumi episode ID" in str(e):
# schema drift, not a server rejection; update extractor, don't retry
raise ExtractorOutdated('bilibili bangumi API envelope changed') from e
raise Prevention
- Update to the latest extractor build when this appears — it almost always means API drift.
- Pin and track extractor versions so envelope changes are caught in CI, not production.
- Capture the raw API response when triaging; the bare message hides the payload.
When it happens
Trigger: A Bangumi API response whose JSON is a dict lacking both keys — e.g. a successful-but-empty object, a redesigned response envelope, or the wrong endpoint being parsed into _report_error. Distinguish from 53/54: those carry server reasons; this one means the extractor found nothing it recognizes at all.
Common situations: Bilibili migrated the bangumi API to a new envelope (data nested under 'result' etc.) after this extractor version; middleware/CDN returning an empty {}; debugging with a patched URL that hits a different endpoint; result accidentally an error page parsed as JSON.
Related errors
AI-assisted analysis of ytdl-org/youtube-dl@956b8c5855 (2026-08-14).
Data as JSON: /api/errors/cd1d481aca770db1.
Report an issue: GitHub.