{"record":{"id":"da962a2176d6ba02","repo":"yt-dlp/yt-dlp","slug":"unable-to-extract-file-id","errorCode":null,"errorMessage":"Unable to extract file ID","messagePattern":"Unable to extract file ID","errorType":"exception","errorClass":"ExtractorError","httpStatus":null,"severity":"error","filePath":"yt_dlp/extractor/zoom.py","lineNumber":107,"sourceCode":"    def _real_extract(self, url):\n        base_url, url_type, video_id = self._match_valid_url(url).group('base_url', 'type', 'id')\n        query = {}\n        start_params = traverse_obj(url, {'startTime': ({parse_qs}, 'startTime', -1)})\n\n        if url_type == 'share':\n            webpage = self._get_real_webpage(url, base_url, video_id, 'share')\n            meeting_id = self._get_page_data(webpage, video_id)['meetingId']\n            redirect_path = self._download_json(\n                f'{base_url}nws/recording/1.0/play/share-info/{meeting_id}',\n                video_id, note='Downloading share info JSON')['result']['redirectUrl']\n            url = update_url_query(urljoin(base_url, redirect_path), start_params)\n            query['continueMode'] = 'true'\n\n        webpage = self._get_real_webpage(url, base_url, video_id, 'play')\n        file_id = self._get_page_data(webpage, video_id)['fileId']\n        if not file_id:\n            # When things go wrong, file_id can be empty string\n            raise ExtractorError('Unable to extract file ID')\n\n        query.update(start_params)\n        data = self._download_json(\n            f'{base_url}nws/recording/1.0/play/info/{file_id}', video_id, query=query,\n            note='Downloading play info JSON')['result']\n\n        subtitles = {}\n        for _type in ('transcript', 'cc', 'chapter'):\n            if data.get(f'{_type}Url'):\n                subtitles[_type] = [{\n                    'url': urljoin(base_url, data[f'{_type}Url']),\n                    'ext': 'vtt',\n                }]\n\n        formats = []\n\n        if data.get('viewMp4Url'):\n            formats.append({","sourceCodeStart":89,"sourceCodeEnd":125,"githubUrl":"https://github.com/yt-dlp/yt-dlp/blob/81ecd58b1394793e6da9998cc19fdb45657f1685/yt_dlp/extractor/zoom.py#L89-L125","documentation":"After loading the Zoom play page and parsing window.__data__, the extractor reads fileId and calls the play-info API with it. The code comments that 'when things go wrong, file_id can be empty string', and this error (not marked expected) fires exactly then: the page rendered without a usable recording file id, so nothing further can be requested.","triggerScenarios":"Recording still processing on Zoom's side (uploaded but not yet playable); access/permission issue where the page loads but no recording file is attached; playback data not yet populated for very recent recordings; frontend data shape change.","commonSituations":"Downloading a recording minutes after the meeting ended before Zoom finished processing; links whose recording the host later restricted; occasional page-state races where __data__ is incomplete.","solutions":["Open the share link in a browser and confirm the recording actually plays there — if it shows 'processing', wait and retry later","Retry after Zoom finishes processing (can take minutes to hours for long meetings)","Update yt-dlp in case the __data__ parsing changed","If the browser cannot play it either, the link/permission is the problem — request a fresh share link from the host"],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"import time\nfrom yt_dlp.utils import ExtractorError\nfor delay in (300, 1800, 7200):  # recording may still be processing\n    try:\n        ydl.download([url]); break\n    except ExtractorError as e:\n        if 'Unable to extract file ID' not in str(e):\n            raise\n        time.sleep(delay)\nelse:\n    raise","preventionTips":["Wait until the recording plays in a browser before queuing it for download","For automated capture of meetings, schedule the download with a delay after the meeting ends","Update yt-dlp before debugging — __data__ parsing can change with Zoom's frontend"],"tags":["zoom","recording","file-id","processing","state"],"backgroundTag":"missing-field-in-response","analyzedSha":"81ecd58b1394793e6da9998cc19fdb45657f1685","analyzedAt":"2026-08-22T12:21:25.439Z","schemaVersion":2},"datasetVersion":"2026-08-22T14:17:55.899Z"}