yt-dlp/yt-dlp · error · ExtractorError
Unable to extract file ID
Error message
Unable to extract file ID
What it means
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.
Source
Thrown at yt_dlp/extractor/zoom.py:107
def _real_extract(self, url):
base_url, url_type, video_id = self._match_valid_url(url).group('base_url', 'type', 'id')
query = {}
start_params = traverse_obj(url, {'startTime': ({parse_qs}, 'startTime', -1)})
if url_type == 'share':
webpage = self._get_real_webpage(url, base_url, video_id, 'share')
meeting_id = self._get_page_data(webpage, video_id)['meetingId']
redirect_path = self._download_json(
f'{base_url}nws/recording/1.0/play/share-info/{meeting_id}',
video_id, note='Downloading share info JSON')['result']['redirectUrl']
url = update_url_query(urljoin(base_url, redirect_path), start_params)
query['continueMode'] = 'true'
webpage = self._get_real_webpage(url, base_url, video_id, 'play')
file_id = self._get_page_data(webpage, video_id)['fileId']
if not file_id:
# When things go wrong, file_id can be empty string
raise ExtractorError('Unable to extract file ID')
query.update(start_params)
data = self._download_json(
f'{base_url}nws/recording/1.0/play/info/{file_id}', video_id, query=query,
note='Downloading play info JSON')['result']
subtitles = {}
for _type in ('transcript', 'cc', 'chapter'):
if data.get(f'{_type}Url'):
subtitles[_type] = [{
'url': urljoin(base_url, data[f'{_type}Url']),
'ext': 'vtt',
}]
formats = []
if data.get('viewMp4Url'):
formats.append({View on GitHub (pinned to 81ecd58b13)
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
Defensive patterns
Strategy: retry
Try / catch
import time
from yt_dlp.utils import ExtractorError
for delay in (300, 1800, 7200): # recording may still be processing
try:
ydl.download([url]); break
except ExtractorError as e:
if 'Unable to extract file ID' not in str(e):
raise
time.sleep(delay)
else:
raise Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- This video is protected by a passcode, use the --video-passw
- validation['errorMessage'] (dynamic: error text from Zoom AP
- Could not extract video id from recording
AI-assisted analysis of yt-dlp/yt-dlp@81ecd58b13 (2026-08-22).
Data as JSON: /api/errors/da962a2176d6ba02.
Report an issue: GitHub.