ytdl-org/youtube-dl · warning · ExtractorError

error

Error message

error

What it means

Raised by ChaturbateIE when no m3u8 playlist URLs were found on the room page. The extractor first scrapes an error text from known markup (a .desc_span span or the #defchat <strong> line); if that matches, the room's own status message (often ROOM IS CURRENTLY OFFLINE) is raised as an expected ExtractorError.

Source

Thrown at youtube_dl/extractor/chaturbate.py:84

        m3u8_urls = []
        for found_m3u8_url in found_m3u8_urls:
            m3u8_fast_url, m3u8_no_fast_url = found_m3u8_url, found_m3u8_url.replace('_fast', '')
            for m3u8_url in (m3u8_fast_url, m3u8_no_fast_url):
                if m3u8_url not in m3u8_urls:
                    m3u8_urls.append(m3u8_url)

        if not m3u8_urls:
            error = self._search_regex(
                [r'<span[^>]+class=(["\'])desc_span\1[^>]*>(?P<error>[^<]+)</span>',
                 r'<div[^>]+id=(["\'])defchat\1[^>]*>\s*<p><strong>(?P<error>[^<]+)<'],
                webpage, 'error', group='error', default=None)
            if not error:
                if any(p in webpage for p in (
                        self._ROOM_OFFLINE, 'offline_tipping', 'tip_offline')):
                    error = self._ROOM_OFFLINE
            if error:
                raise ExtractorError(error, expected=True)
            raise ExtractorError('Unable to find stream URL')

        formats = []
        for m3u8_url in m3u8_urls:
            for known_id in ('fast', 'slow'):
                if '_%s' % known_id in m3u8_url:
                    m3u8_id = known_id
                    break
            else:
                m3u8_id = None
            formats.extend(self._extract_m3u8_formats(
                m3u8_url, video_id, ext='mp4',
                # ffmpeg skips segments for fast m3u8
                preference=-10 if m3u8_id == 'fast' else None,
                m3u8_id=m3u8_id, fatal=False, live=True))
        self._sort_formats(formats)

        return {

View on GitHub (pinned to 956b8c5855)

Solutions

  1. Only extract while the room is actually streaming; poll the room URL and retry when it becomes live.
  2. For password rooms, pass the room password mechanism if supported (or an authenticated session cookie).
  3. If the page clearly shows a stream but you still get an error text, update to yt-dlp — the markup regexes are brittle.
  4. Treat the error string literally: it is copied from the room's own status line.

Example fix

import time
from youtube_dl.utils import ExtractorError

while True:
    try:
        ydl.extract(room_url, download=True)
        break
    except ExtractorError as e:
        if 'offline' in str(e).lower():
            time.sleep(60)  # wait for the room to go live
        else:
            raise
Defensive patterns

Strategy: retry

Validate before calling

# pre-flight: is the room live?
html = http_get(room_url)
if 'ROOM IS CURRENTLY OFFLINE' in html or 'offline_tipping' in html:
    schedule_retry_later(room_url)

Try / catch

from youtube_dl.utils import ExtractorError
try:
    ydl.extract_info(room_url)
except ExtractorError as e:
    msg = str(e).lower()
    if 'offline' in msg or 'away' in msg:
        sleep_and_requeue(room_url, 60)   # transient: room not broadcasting
    else:
        raise                              # e.g. private/banned: permanent

Prevention

When it happens

Trigger: The room page contains no playlist (m3u8_urls empty) plus one of the error markers — room offline, hidden/private, or banned — OR the page contains 'offline_tipping'/'tip_offline' strings which are mapped to the offline message. (If NO error marker is found, a different 'Unable to find stream URL' error is raised instead.)

Common situations: Trying to record a room that is not currently broadcasting; private/password-protected shows; the model's page markup changed so the regexes no longer capture the status text.

Related errors


AI-assisted analysis of ytdl-org/youtube-dl@956b8c5855 (2026-08-14). Data as JSON: /api/errors/58370f7c412d7cd1. Report an issue: GitHub.