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

  1. Open the share link in a browser and confirm the recording actually plays there — if it shows 'processing', wait and retry later
  2. Retry after Zoom finishes processing (can take minutes to hours for long meetings)
  3. Update yt-dlp in case the __data__ parsing changed
  4. 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

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


AI-assisted analysis of yt-dlp/yt-dlp@81ecd58b13 (2026-08-22). Data as JSON: /api/errors/da962a2176d6ba02. Report an issue: GitHub.