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

  1. Update yt-dlp to the latest version; response-shape changes get patched in the extractor.
  2. Re-check the Bigo room URL — malformed ids can produce degenerate API replies.
  3. 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

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

Related errors


AI-assisted analysis of yt-dlp/yt-dlp@81ecd58b13 (2026-08-22). Data as JSON: /api/errors/46cb9798e5cc9c89. Report an issue: GitHub.