yt-dlp/yt-dlp · error · ExtractorError

{msg['detail']}

Error message

{msg['detail']}

What it means

Viidea (lecture-capture platform) extractor surfaces the API's own error text: when the lecture metadata request ({livepipe}/site/api/lecture/{id}?format=json) returns HTTP 403, the JSON response's 'detail' field is re-raised as the error message with expected=True. Whatever the server says — password required, lecture unpublished, permissions — becomes the user-visible message.

Source

Thrown at yt_dlp/extractor/viidea.py:136

        cfg = self._parse_json(self._search_regex(
            [r'cfg\s*:\s*({.+?})\s*,\s*[\da-zA-Z_]+\s*:\s*\(?\s*function',
             r'cfg\s*:\s*({[^}]+})'],
            webpage, 'cfg'), lecture_slug, js_to_json)

        lecture_id = str(cfg['obj_id'])

        base_url = self._proto_relative_url(cfg['livepipe'], 'http:')

        try:
            lecture_data = self._download_json(
                f'{base_url}/site/api/lecture/{lecture_id}?format=json',
                lecture_id)['lecture'][0]
        except ExtractorError as e:
            if isinstance(e.cause, HTTPError) and e.cause.status == 403:
                msg = self._parse_json(
                    e.cause.response.read().decode('utf-8'), lecture_id)
                raise ExtractorError(msg['detail'], expected=True)
            raise

        lecture_info = {
            'id': lecture_id,
            'display_id': lecture_slug,
            'title': lecture_data['title'],
            'timestamp': parse_iso8601(lecture_data.get('time')),
            'description': lecture_data.get('description_wiki'),
            'thumbnail': lecture_data.get('thumb'),
        }

        playlist_entries = []
        lecture_type = lecture_data.get('type')
        parts = [str(video) for video in cfg.get('videos', [])]
        if parts:
            multipart = len(parts) > 1

            def extract_part(part_id):

View on GitHub (pinned to 81ecd58b13)

Solutions

  1. Read the detail text — it states the server's reason (locked, unpublished, unauthorized).
  2. If the portal requires login, authenticate in a browser, export cookies, and pass --cookies.
  3. Confirm the lecture is playable in a browser while logged in; if not, it cannot be downloaded either.
  4. Update yt-dlp in case the API contract changed.
Defensive patterns

Strategy: try-catch

Try / catch

try:
    info = ydl.extract_info(url, download=True)
except DownloadError as e:
    if '[viidea]' in str(e):
        # e.message is the server's own 'detail' text (locked/unpublished/unauthorized)
        log_warning(f'lecture API refused: {e}')
    else:
        raise

Prevention

When it happens

Trigger: The lecture API returns 403 with a JSON body containing a 'detail' key — e.g. the lecture is not yet published, is instructor-only, or the institution disabled anonymous access to the recording.

Common situations: Students downloading lectures before they are made public, institutional portals that require an authenticated session, or lectures whose availability window has closed.

Related errors


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