{"record":{"id":"707712b0d067d561","repo":"ytdl-org/youtube-dl","slug":"error-707712","errorCode":null,"errorMessage":"error","messagePattern":"error","errorType":"exception","errorClass":"ExtractorError","httpStatus":null,"severity":"error","filePath":"youtube_dl/extractor/hketv.py","lineNumber":117,"sourceCode":"            'video_url': file_id,\n        }\n\n        response = self._download_json(\n            self._APPS_BASE_URL + '/media/play/handler.php', video_id,\n            data=urlencode_postdata(data),\n            headers=merge_dicts({\n                'Content-Type': 'application/x-www-form-urlencoded'},\n                self.geo_verification_headers()))\n\n        result = response['result']\n\n        if not response.get('success') or not response.get('access'):\n            error = clean_html(response.get('access_err_msg'))\n            if 'Video streaming is not available in your country' in error:\n                self.raise_geo_restricted(\n                    msg=error, countries=self._GEO_COUNTRIES)\n            else:\n                raise ExtractorError(error, expected=True)\n\n        formats = []\n\n        width = int_or_none(result.get('width'))\n        height = int_or_none(result.get('height'))\n\n        playlist0 = result['playlist'][0]\n        for fmt in playlist0['sources']:\n            file_url = urljoin(self._APPS_BASE_URL, fmt.get('file'))\n            if not file_url:\n                continue\n            # If we ever wanted to provide the final resolved URL that\n            # does not require cookies, albeit with a shorter lifespan:\n            #     urlh = self._downloader.urlopen(file_url)\n            #     resolved_url = urlh.geturl()\n            label = fmt.get('label')\n            h = self._FORMAT_HEIGHTS.get(label)\n            w = h * width // height if h and width and height else None","sourceCodeStart":99,"sourceCodeEnd":135,"githubUrl":"https://github.com/ytdl-org/youtube-dl/blob/956b8c585591b401a543e409accb163eeaaa1193/youtube_dl/extractor/hketv.py#L99-L135","documentation":"Raised by the RTHK (HKTVE/hketv) extractor when the API response lacks success or access; the message is the cleaned access_err_msg text. If that text contains 'Video streaming is not available in your country' it raises geo-restricted instead. Marked expected=True.","triggerScenarios":"POSTing to the hketv API where response.success/access is false: accessing RTHK content outside allowed regions without geo bypass, or the specific programme being unpublished/expired.","commonSituations":"Non-HK IP hitting region-locked RTHK programmes (message variant without the exact country string), removed programmes, or API payload changes in old youtube-dl builds.","solutions":["If geo-related, use an HK IP or pass --geo-verification-proxy","Confirm the programme still plays at hketv.com / rthk.hk in a browser","Update youtube-dl/yt-dlp for API changes","Run with -v to read the exact access_err_msg"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"import requests\nresp = requests.post(HKETV_API, data=payload, headers={'Content-Type': 'application/x-www-form-urlencoded'}).json()\nif not resp.get('success') or not resp.get('access'):\n    print('HKETV refusal:', resp.get('access_err_msg'))","typeGuard":"def hketv_accessible(response):\n    return bool(response.get('success')) and bool(response.get('access')) and response.get('result', {}).get('playlist')","tryCatchPattern":"try:\n    ydl.extract_info(url)\nexcept DownloadError as e:\n    if 'not available in your country' in str(e):\n        use_geo_proxy_and_retry(url)\n    elif 'HKETV' in str(e):\n        skip_as_unavailable(url)\n    else:\n        raise","preventionTips":["Use --geo-verification-proxy or an HK exit for RTHK content","Pre-check the API's success/access flags before queuing","Parse access_err_msg — it distinguishes geo from unpublished"],"tags":["hketv","rthk","geo-restriction","api-error"],"backgroundTag":null,"analyzedSha":"956b8c585591b401a543e409accb163eeaaa1193","analyzedAt":"2026-08-14T18:59:47.863Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}