yt-dlp/yt-dlp · error · ExtractorError
Received invalid JSON data
Error message
Received invalid JSON data
What it means
Raised by the Bigo extractor when the POST to ta.bigo.tv getInternalStudioInfo returns valid JSON that is not an object. _download_json already raises on unparseable bodies, so reaching this branch means the endpoint answered 200 with a JSON list, string, or number instead of the expected {code, msg, data} envelope — an API contract break rather than a transport error.
Source
Thrown at yt_dlp/extractor/bigo.py:36
'skip': 'livestream',
}, {
'url': 'https://www.bigo.tv/th/Tarlerm1304',
'only_matching': True,
}, {
'url': 'https://bigo.tv/115976881',
'only_matching': True,
}]
def _real_extract(self, url):
user_id = self._match_id(url)
info_raw = self._download_json(
'https://ta.bigo.tv/official_website/studio/getInternalStudioInfo',
user_id, data=urlencode_postdata({'siteId': user_id}),
headers={'Accept': 'application/json'})
if not isinstance(info_raw, dict):
raise ExtractorError('Received invalid JSON data')
if info_raw.get('code'):
raise ExtractorError(
'Bigo says: {} (code {})'.format(info_raw.get('msg'), info_raw.get('code')), expected=True)
info = info_raw.get('data') or {}
if not info.get('alive'):
raise UserNotLive(video_id=user_id)
formats, subs = self._extract_m3u8_formats_and_subtitles(
info.get('hls_src'), user_id, 'mp4', 'm3u8')
return {
'id': info.get('roomId') or user_id,
'title': info.get('roomTopic') or info.get('nick_name') or user_id,
'formats': formats,
'subtitles': subs,
'thumbnail': info.get('snapshot'),
'uploader': info.get('nick_name'),View on GitHub (pinned to 81ecd58b13)
Solutions
- Update yt-dlp to the latest version; response-shape changes get patched in the extractor.
- Re-check the Bigo room URL — malformed ids can produce degenerate API replies.
- If it persists, curl the endpoint with the same POST body and inspect the JSON type, then report upstream.
Example fix
// before
info_raw = self._download_json(url, user_id, ...)
if not isinstance(info_raw, dict):
raise ExtractorError('Received invalid JSON data')
// after (accept envelope wrapped in a list)
if isinstance(info_raw, list) and len(info_raw) == 1 and isinstance(info_raw[0], dict):
info_raw = info_raw[0] Defensive patterns
Strategy: type-guard
Validate before calling
import json, urllib.request
def bigo_info_is_dict(site_id: str) -> bool:
req = urllib.request.Request(
'https://ta.bigo.tv/official_website/studio/getInternalStudioInfo',
data=urllib.parse.urlencode({'siteId': site_id}).encode(),
headers={'Accept': 'application/json'})
with urllib.request.urlopen(req, timeout=10) as r:
return isinstance(json.load(r), dict) Type guard
def is_bigo_envelope(value) -> bool:
return isinstance(value, dict) and ('code' in value or 'data' in value) Prevention
- Check isinstance(response, dict) before reading code/msg/data
- Pin a current yt-dlp; Bigo endpoint shape changes get patched upstream
When it happens
Trigger: The Bigo endpoint changing its response shape (e.g. returning an array or a bare string), or an edge/CDN node replying with a minimal JSON payload for unknown siteIds; anything where isinstance(info_raw, dict) is False.
Common situations: API version changes after a Bigo web update; hitting the internal endpoint with an unusual siteId that yields a degenerate response; old yt-dlp builds against the updated endpoint.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- Bigo says: {} (code {})
- The channel is not currently live
- Unsafe placeholder for exec command: {na!r} The --output-na-
- Unsafe default(s) in exec command: {outtmpl!r} Conversions a
- Invalid syntax in Cookie Header
AI-assisted analysis of yt-dlp/yt-dlp@81ecd58b13 (2026-08-22).
Data as JSON: /api/errors/46cb9798e5cc9c89.
Report an issue: GitHub.