{"record":{"id":"71294e0c414d2ab6","repo":"ytdl-org/youtube-dl","slug":"s-71294e","errorCode":null,"errorMessage":"%s","messagePattern":"%s","errorType":"exception","errorClass":"ExtractorError","httpStatus":null,"severity":"error","filePath":"youtube_dl/extractor/mgtv.py","lineNumber":55,"sourceCode":"        'url': 'https://w.mgtv.com/b/301817/3826653.html',\n        'only_matching': True,\n    }]\n\n    def _real_extract(self, url):\n        video_id = self._match_id(url)\n        tk2 = base64.urlsafe_b64encode(b'did=%s|pno=1030|ver=0.3.0301|clit=%d' % (compat_str(uuid.uuid4()).encode(), time.time()))[::-1]\n        try:\n            api_data = self._download_json(\n                'https://pcweb.api.mgtv.com/player/video', video_id, query={\n                    'tk2': tk2,\n                    'video_id': video_id,\n                }, headers=self.geo_verification_headers())['data']\n        except ExtractorError as e:\n            if isinstance(e.cause, compat_HTTPError) and e.cause.code == 401:\n                error = self._parse_json(e.cause.read().decode(), None)\n                if error.get('code') == 40005:\n                    self.raise_geo_restricted(countries=self._GEO_COUNTRIES)\n                raise ExtractorError(error['msg'], expected=True)\n            raise\n        info = api_data['info']\n        title = info['title'].strip()\n        stream_data = self._download_json(\n            'https://pcweb.api.mgtv.com/player/getSource', video_id, query={\n                'pm2': api_data['atc']['pm2'],\n                'tk2': tk2,\n                'video_id': video_id,\n            }, headers=self.geo_verification_headers())['data']\n        stream_domain = stream_data['stream_domain'][0]\n\n        formats = []\n        for idx, stream in enumerate(stream_data['stream']):\n            stream_path = stream.get('url')\n            if not stream_path:\n                continue\n            format_data = self._download_json(\n                stream_domain + stream_path, video_id,","sourceCodeStart":37,"sourceCodeEnd":73,"githubUrl":"https://github.com/ytdl-org/youtube-dl/blob/956b8c585591b401a543e409accb163eeaaa1193/youtube_dl/extractor/mgtv.py#L37-L73","documentation":"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.","triggerScenarios":"_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.","commonSituations":"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.","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."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":"def mgtv_is_geo_error(error_json):\n    return isinstance(error_json, dict) and error_json.get('code') == 40005","tryCatchPattern":"try:\n    info = ydl.extract_info(url, download=False)\nexcept ExtractorError as e:\n    msg = str(e)\n    if 'This video is not available from your location' in msg or 'available in your area' in msg:\n        retry_with_mainland_china_proxy(url)\n    elif 'MGTV' in msg or 'mgtv' in msg:\n        log_takedown(url, msg)  # site's own Chinese message; usually means removed\n    else:\n        raise","preventionTips":["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."],"tags":["api-response","http-401","geo","expected-error"],"backgroundTag":null,"analyzedSha":"956b8c585591b401a543e409accb163eeaaa1193","analyzedAt":"2026-08-14T18:59:47.863Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}