ytdl-org/youtube-dl · error · ExtractorError

Letv cloud returned an unknown error

Error message

Letv cloud returned an unknown error

What it means

Raised by the Letv Cloud extractor when the gpc.php playJson response has neither 'data', nor 'message', nor a usable 'code' — a completely unrecognized error shape. It is expected=True but signals the extractor cannot interpret the API response at all, which often means an API contract change rather than a content problem.

Source

Thrown at youtube_dl/extractor/leeco.py:329

                'ran': compat_str(timestamp),
            }
            self.sign_data(data)
            return self._download_json(
                'http://api.letvcloud.com/gpc.php?' + compat_urllib_parse_urlencode(data),
                media_id, 'Downloading playJson data for type %s' % cf)

        play_json = get_play_json(cf, time.time())
        # The server time may be different from local time
        if play_json.get('code') == 10071:
            play_json = get_play_json(cf, play_json['timestamp'])

        if not play_json.get('data'):
            if play_json.get('message'):
                raise ExtractorError('Letv cloud said: %s' % play_json['message'], expected=True)
            elif play_json.get('code'):
                raise ExtractorError('Letv cloud returned error %d' % play_json['code'], expected=True)
            else:
                raise ExtractorError('Letv cloud returned an unknown error')

        def b64decode(s):
            return compat_b64decode(s).decode('utf-8')

        formats = []
        for media in play_json['data']['video_info']['media'].values():
            play_url = media['play_url']
            url = b64decode(play_url['main_url'])
            decoded_url = b64decode(url_basename(url))
            formats.append({
                'url': url,
                'ext': determine_ext(decoded_url),
                'format_id': str_or_none(play_url.get('vtype')),
                'format_note': str_or_none(play_url.get('definition')),
                'width': int_or_none(play_url.get('vwidth')),
                'height': int_or_none(play_url.get('vheight')),
            })

View on GitHub (pinned to 956b8c5855)

Solutions

  1. Update youtube-dl / switch to yt-dlp — unknown-shape responses usually mean an API change already fixed upstream
  2. Fetch the gpc.php URL manually with the same uu/vu to inspect what is actually returned
  3. If the service is dead in your region or entirely, use an alternative source for the content
  4. Report the response body upstream so the extractor can be taught the new shape
Defensive patterns

Strategy: retry

Validate before calling

import json, urllib.request

def letv_api_returns_json(uu, vu):
    # smoke-test the gpc.php endpoint shape before running the extractor
    url = 'http://api.letvcloud.com/gpc.php?uu=%s&vu=%s&cf=flash' % (uu, vu)
    try:
        json.load(urllib.request.urlopen(url, timeout=10))
        return True
    except (ValueError, urllib.error.URLError):
        return False

Try / catch

try:
    ydl.extract_info(url)
except ExtractorError as e:
    if 'unknown error' in str(e):
        update_extractor_or_switch_to_ytdlp()  # response shape changed upstream
    else:
        raise

Prevention

When it happens

Trigger: Letv Cloud extraction where gpc.php returns JSON with none of the expected keys (for example an HTML error page parsed as JSON, an empty object, or a new response schema after an API update).

Common situations: Letv Cloud API endpoints being deprecated or restructured; CDN edge responses (maintenance/captcha pages) returned instead of JSON; very old youtube-dl versions against a changed API; network middleboxes mangling responses.

Related errors


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