ytdl-org/youtube-dl · error · ExtractorError
%s
Error message
%s
What it means
Raised by the MGTV extractor when the pcweb.api.mgtv.com/player/video call fails with HTTP 401: the JSON error body is parsed, geo-restriction code 40005 is converted to a proper geo error, and any OTHER code becomes this raise with the API's own 'msg' text. Expected=True, so it is a service-refusal signal, not a bug.
Source
Thrown at youtube_dl/extractor/mgtv.py:55
'url': 'https://w.mgtv.com/b/301817/3826653.html',
'only_matching': True,
}]
def _real_extract(self, url):
video_id = self._match_id(url)
tk2 = base64.urlsafe_b64encode(b'did=%s|pno=1030|ver=0.3.0301|clit=%d' % (compat_str(uuid.uuid4()).encode(), time.time()))[::-1]
try:
api_data = self._download_json(
'https://pcweb.api.mgtv.com/player/video', video_id, query={
'tk2': tk2,
'video_id': video_id,
}, headers=self.geo_verification_headers())['data']
except ExtractorError as e:
if isinstance(e.cause, compat_HTTPError) and e.cause.code == 401:
error = self._parse_json(e.cause.read().decode(), None)
if error.get('code') == 40005:
self.raise_geo_restricted(countries=self._GEO_COUNTRIES)
raise ExtractorError(error['msg'], expected=True)
raise
info = api_data['info']
title = info['title'].strip()
stream_data = self._download_json(
'https://pcweb.api.mgtv.com/player/getSource', video_id, query={
'pm2': api_data['atc']['pm2'],
'tk2': tk2,
'video_id': video_id,
}, headers=self.geo_verification_headers())['data']
stream_domain = stream_data['stream_domain'][0]
formats = []
for idx, stream in enumerate(stream_data['stream']):
stream_path = stream.get('url')
if not stream_path:
continue
format_data = self._download_json(
stream_domain + stream_path, video_id,View on GitHub (pinned to 956b8c5855)
Solutions
- Read the embedded msg — it is MGTV's stated reason in Chinese (e.g. 该视频已下线).
- If it is region related despite the code, route through a mainland-China proxy with --proxy.
- Verify the video plays at mgtv.com in a browser.
- Update youtube-dl / yt-dlp, as the tk2 signing and error-code mapping have evolved.
Defensive patterns
Strategy: try-catch
Type guard
def mgtv_is_geo_error(error_json):
return isinstance(error_json, dict) and error_json.get('code') == 40005 Try / catch
try:
info = ydl.extract_info(url, download=False)
except ExtractorError as e:
msg = str(e)
if 'This video is not available from your location' in msg or 'available in your area' in msg:
retry_with_mainland_china_proxy(url)
elif 'MGTV' in msg or 'mgtv' in msg:
log_takedown(url, msg) # site's own Chinese message; usually means removed
else:
raise Prevention
- Use a mainland-China proxy for MGTV batches to eliminate the dominant failure mode.
- Keep the extractor updated: the tk2 signing parameter and error-code mapping change over time.
When it happens
Trigger: _download_json raises ExtractorError whose cause is compat_HTTPError with code 401; the parsed body's 'code' != 40005, so error['msg'] is re-raised (e.g. video removed, copyright takedown). Non-401 network errors are re-raised untouched.
Common situations: Video taken down for licensing reasons on Hunan TV/MGTV; region-adjacent refusals that use a different code than 40005; stale video ids from old links; API changes returning 401 for requests missing required cookies.
Related errors
- %s said: %s
- lynda returned error: %s
- %s encountered an error: %s
- This video is only available after 20:00
- Invalid url for track %d of album url %s
AI-assisted analysis of ytdl-org/youtube-dl@956b8c5855 (2026-08-14).
Data as JSON: /api/errors/71294e0c414d2ab6.
Report an issue: GitHub.