ytdl-org/youtube-dl · warning · ExtractorError
%s is offline
Error message
%s is offline
What it means
Raised by TwitchStreamIE when the channel's user object exists but user.stream is falsy — the channel is simply not broadcasting right now. Expected error; it is a state condition, not a failure to parse.
Source
Thrown at youtube_dl/extractor/twitch.py:796
'isVodOrCollection': False,
'vodID': '',
},
}, {
'operationName': 'VideoPreviewOverlay',
'variables': {'login': channel_name},
}],
'Downloading stream GraphQL')
user = gql[0]['data']['user']
if not user:
raise ExtractorError(
'%s does not exist' % channel_name, expected=True)
stream = user['stream']
if not stream:
raise ExtractorError('%s is offline' % channel_name, expected=True)
access_token = self._download_access_token(
channel_name, 'stream', 'channelName')
token = access_token['value']
stream_id = stream.get('id') or channel_name
query = {
'allow_source': 'true',
'allow_audio_only': 'true',
'allow_spectre': 'true',
'p': random.randint(1000000, 10000000),
'player': 'twitchweb',
'playlist_include_framerate': 'true',
'segment_preference': '4',
'sig': access_token['signature'].encode('utf-8'),
'token': token.encode('utf-8'),
}
formats = self._extract_m3u8_formats(View on GitHub (pinned to 956b8c5855)
Solutions
- Check the channel page for a LIVE badge; if offline, wait for the broadcast and retry.
- Download the VOD afterwards via its /videos/ URL once published.
- Use a monitoring script/timer to re-attempt when the stream comes online.
- If it is a rerun, try the underlying VOD URL instead.
Defensive patterns
Strategy: retry
Validate before calling
import requests
q = [{'operationName': 'StreamMetadata', 'variables': {'login': channel}}]
r = requests.post('https://gql.twitch.tv/gql', json=q, headers={'Client-ID': CLIENT_ID})
stream = (r.json()[0]['data'].get('user') or {}).get('stream')
if not stream:
schedule_retry(channel, when='next broadcast window') Type guard
def is_streaming(data: dict) -> bool:
return bool((data.get('user') or {}).get('stream')) Try / catch
try:
ydl.extract_info(channel_url)
except ExtractorError as e:
if 'is offline' in str(e):
retry_later(channel_url, backoff_minutes=15) # state, not failure
else:
raise Prevention
- Poll the lightweight stream GraphQL endpoint and start the download when stream becomes non-null.
- Treat 'offline' as retryable state; treat 'does not exist' as permanent.
When it happens
Trigger: Extracting any twitch.tv/<name> URL for a channel that is currently offline (user['stream'] null/empty after the existence check passed).
Common situations: Trying to download a live stream after it ended, scheduled streams, reruns the API does not expose as stream, timezone mistakes about broadcast schedules.
Related errors
AI-assisted analysis of ytdl-org/youtube-dl@956b8c5855 (2026-08-14).
Data as JSON: /api/errors/7de09c1285f8cf90.
Report an issue: GitHub.