ytdl-org/youtube-dl · error · ExtractorError

This user is offline.

Error message

This user is offline.

What it means

Raised by BigoIE._real_extract after a successful API response (no error code): the response's data.alive flag is falsy, meaning the channel exists but is not currently live-streaming. Since Bigo extraction targets live HLS streams (hls_src with m3u8 protocol), an offline user has nothing to extract, so it fails expected=True.

Source

Thrown at youtube_dl/extractor/bigo.py:45

        'only_matching': True,
    }]

    def _real_extract(self, url):
        user_id = self._match_id(url)

        info_raw = self._download_json(
            'https://bigo.tv/studio/getInternalStudioInfo',
            user_id, data=urlencode_postdata({'siteId': user_id}))

        if not isinstance(info_raw, dict):
            raise ExtractorError('Received invalid JSON data')
        if info_raw.get('code'):
            raise ExtractorError(
                'Bigo says: %s (code %s)' % (info_raw.get('msg'), info_raw.get('code')), expected=True)
        info = info_raw.get('data') or {}

        if not info.get('alive'):
            raise ExtractorError('This user is offline.', expected=True)

        return {
            'id': info.get('roomId') or user_id,
            'title': info.get('roomTopic') or info.get('nick_name') or user_id,
            'formats': [{
                'url': info.get('hls_src'),
                'ext': 'mp4',
                'protocol': 'm3u8',
            }],
            'thumbnail': info.get('snapshot'),
            'uploader': info.get('nick_name'),
            'uploader_id': user_id,
            'is_live': True,
        }

View on GitHub (pinned to 956b8c5855)

Solutions

  1. Retry while the channel is actually live — verify at https://bigo.tv/<user_id> that a LIVE badge/player shows.
  2. For monitoring, poll the getInternalStudioInfo endpoint and only invoke full extraction when alive is truthy.
  3. Handle this as an expected error and back off rather than re-triggering immediately.
  4. Confirm the id belongs to the intended streamer; a wrong-but-existing id also reports offline.

Example fix

// before - caller extracts directly
from youtube_dl import YoutubeDL
YoutubeDL().extract_info('https://bigo.tv/115976881', download=True)

// after - probe liveness first via the same API the extractor uses, then extract only when live
import requests
r = requests.post('https://bigo.tv/studio/getInternalStudioInfo', data={'siteId': '115976881'}).json()
if r.get('code') or not (r.get('data') or {}).get('alive'):
    print('channel offline or errored; retry later')
else:
    YoutubeDL().extract_info('https://bigo.tv/115976881', download=True)
Defensive patterns

Strategy: validation

Validate before calling

import requests

def bigo_user_is_live(user_id):
    r = requests.post('https://bigo.tv/studio/getInternalStudioInfo', data={'siteId': user_id})
    if r.status_code != 200:
        return False
    body = r.json()
    return isinstance(body, dict) and not body.get('code') and bool((body.get('data') or {}).get('alive'))

Type guard

def is_live_bigo_data(info):
    return isinstance(info, dict) and bool(info.get('alive')) and bool(info.get('hls_src'))

Try / catch

try:
    ydl.extract_info(bigo_url)
except ExtractorError as e:
    if str(e) == 'This user is offline.':
        schedule_next_poll(bigo_url)  # expected while streamer is off-air
    else:
        raise

Prevention

When it happens

Trigger: Extracting any Bigo channel URL while the streamer is offline: API returns code 0 with data.alive = false/0/absent. Purely time-dependent — the same URL succeeds while the user is live.

Common situations: Monitoring scripts polling channel URLs between streams; users replaying links to streams that ended; time-zone mismatch about when a streamer goes live; channels that stream rarely.

Related errors


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