{"record":{"id":"1109c8a5538848f0","repo":"ytdl-org/youtube-dl","slug":"s-is-offline","errorCode":null,"errorMessage":"%s is offline","messagePattern":"(.+?) is offline","errorType":"exception","errorClass":"ExtractorError","httpStatus":null,"severity":"warning","filePath":"youtube_dl/extractor/showroomlive.py","lineNumber":35,"sourceCode":"        'only_matching': True,\n    }\n\n    def _real_extract(self, url):\n        broadcaster_id = self._match_id(url)\n\n        webpage = self._download_webpage(url, broadcaster_id)\n\n        room_id = self._search_regex(\n            (r'SrGlobal\\.roomId\\s*=\\s*(\\d+)',\n             r'(?:profile|room)\\?room_id\\=(\\d+)'), webpage, 'room_id')\n\n        room = self._download_json(\n            urljoin(url, '/api/room/profile?room_id=%s' % room_id),\n            broadcaster_id)\n\n        is_live = room.get('is_onlive')\n        if is_live is not True:\n            raise ExtractorError('%s is offline' % broadcaster_id, expected=True)\n\n        uploader = room.get('performer_name') or broadcaster_id\n        title = room.get('room_name') or room.get('main_name') or uploader\n\n        streaming_url_list = self._download_json(\n            urljoin(url, '/api/live/streaming_url?room_id=%s' % room_id),\n            broadcaster_id)['streaming_url_list']\n\n        formats = []\n        for stream in streaming_url_list:\n            stream_url = stream.get('url')\n            if not stream_url:\n                continue\n            stream_type = stream.get('type')\n            if stream_type == 'hls':\n                m3u8_formats = self._extract_m3u8_formats(\n                    stream_url, broadcaster_id, ext='mp4', m3u8_id='hls',\n                    live=True)","sourceCodeStart":17,"sourceCodeEnd":53,"githubUrl":"https://github.com/ytdl-org/youtube-dl/blob/956b8c585591b401a543e409accb163eeaaa1193/youtube_dl/extractor/showroomlive.py#L17-L53","documentation":"ShowRoomLiveIE._real_extract fetches the room profile from /api/room/profile and checks the 'is_onlive' field. If it is not exactly True (the broadcaster is not currently streaming), the extractor raises '<broadcaster> is offline' as an expected error. SHOWROOM is a live-only platform, so there is nothing to extract from an offline room.","triggerScenarios":"Extracting a showroom-live.jp room URL while the broadcaster is offline: room.get('is_onlive') returns None, 0, or false. The profile API is still reachable and returns valid JSON; the error is purely the live-state check.","commonSituations":"Downloading a room URL after a stream ended; scheduling downloads against a room that has not started; the broadcaster being on a different platform/room id; time-zone confusion about when a stream is live.","solutions":["Wait until the broadcaster is actually live and retry (verify by opening the room in a browser).","If you need the past stream, look for the broadcaster's recorded archives on SHOWROOM's replay feature or their uploads elsewhere.","Confirm the room id in the URL matches the broadcaster's current room (rooms can be recreated with new ids).","For automation, poll the /api/room/profile?room_id= endpoint yourself and only invoke youtube-dl when is_onlive is true."],"exampleFix":"// before\nis_live = room.get('is_onlive')\nif is_live is not True:\n    raise ExtractorError('%s is offline' % broadcaster_id, expected=True)\n\n// after (caller-side gate in a wrapper script)\nimport json, urllib.request\nprofile = json.load(urllib.request.urlopen(\n    'https://www.showroom-live.com/api/room/profile?room_id=%s' % room_id))\nif profile.get('is_onlive') is not True:\n    print('offline; not invoking youtube-dl')\nelse:\n    subprocess.run(['youtube-dl', url])","handlingStrategy":"validation","validationCode":"profile = json.load(urllib.request.urlopen(\n    'https://www.showroom-live.com/api/room/profile?room_id=' + room_id))\nif profile.get('is_onlive') is not True:\n    print('offline - not extracting'); exit(0)","typeGuard":"def room_is_live(profile: dict) -> bool:\n    return profile.get('is_onlive') is True","tryCatchPattern":"try:\n    extract(url)\nexcept ExtractorError as e:\n    if 'is offline' in str(e):\n        schedule_retry(later=True)\n    else:\n        raise","preventionTips":["Poll the room profile API and launch youtube-dl only when is_onlive is true.","For scheduled streams, poll near the announced start time.","Record room ids, not page URLs - rooms get recreated."],"tags":["live-stream","offline","showroom","extractor"],"backgroundTag":null,"analyzedSha":"956b8c585591b401a543e409accb163eeaaa1193","analyzedAt":"2026-08-14T18:59:47.863Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}