ytdl-org/youtube-dl · error · ExtractorError

Unsupported URL

Error message

Unsupported URL

What it means

Raised by the LBRY extractor when a resolved claim's value.stream_type is not in _SUPPORTED_STREAM_TYPES, i.e. the lbry:// URL points to a claim that exists but is not a downloadable media stream (e.g. a channel, repost, or document/other content type). It is expected=True so unsupported-but-valid claims fail with a clear message.

Source

Thrown at youtube_dl/extractor/lbry.py:180

        'url': 'https://lbry.tv/$/download/Episode-1/e7d93d772bd87e2b62d5ab993c1c3ced86ebb396',
        'only_matching': True,
    }, {
        'url': 'https://lbry.tv/@lacajadepandora:a/TRUMP-EST%C3%81-BIEN-PUESTO-con-Pilar-Baselga,-Carlos-Senra,-Luis-Palacios-(720p_30fps_H264-192kbit_AAC):1',
        'only_matching': True,
    }]

    def _real_extract(self, url):
        display_id = self._match_id(url)
        if display_id.startswith('$/'):
            display_id = display_id.split('/', 2)[-1].replace('/', ':')
        else:
            display_id = display_id.replace(':', '#')
        display_id = compat_urllib_parse_unquote(display_id)
        uri = 'lbry://' + display_id
        result = self._resolve_url(uri, display_id, 'stream')
        result_value = result['value']
        if result_value.get('stream_type') not in self._SUPPORTED_STREAM_TYPES:
            raise ExtractorError('Unsupported URL', expected=True)
        claim_id = result['claim_id']
        title = result_value['title']
        streaming_url = self._call_api_proxy(
            'get', claim_id, {'uri': uri}, 'streaming url')['streaming_url']
        info = self._parse_stream(result, url)
        urlh = self._request_webpage(
            streaming_url, display_id, note='Downloading streaming redirect url info')
        if determine_ext(urlh.geturl()) == 'm3u8':
            info['formats'] = self._extract_m3u8_formats(
                urlh.geturl(), display_id, 'mp4', entry_protocol='m3u8_native',
                m3u8_id='hls')
            self._sort_formats(info['formats'])
        else:
            info['url'] = streaming_url
        info.update({
            'id': claim_id,
            'title': title,
        })

View on GitHub (pinned to 956b8c5855)

Solutions

  1. Open the URL in a browser and confirm it is actually a video/audio claim, not a channel or post
  2. If it is a repost/channel, navigate to the underlying stream claim and use that URL
  3. Update youtube-dl/yt-dlp so newly supported stream types are handled
  4. For non-media claims, fetch the content directly from the LBRY API/daemon instead of youtube-dl
Defensive patterns

Strategy: validation

Validate before calling

def is_probable_lbry_stream(url):
    # channel claims resolve via 'claim'/'channel'; streams usually linked from content pages
    from urllib.parse import urlparse, unquote
    path = unquote(urlparse(url).path)
    return ':' not in path.split('@')[-1] and not path.startswith('/@')

Try / catch

try:
    ydl.extract_info(url)
except ExtractorError as e:
    if 'Unsupported URL' in str(e):
        resolve_claim_and_follow_to_stream(url)  # e.g. resolve channel -> find video claim
    else:
        raise

Prevention

When it happens

Trigger: Passing an lbry.tv / open.lbry.com URL that resolves via the 'stream' proxy to a claim whose stream_type is not audio/video (for example a channel claim, a reposted non-media claim, or an image/document post).

Common situations: Following links to LBRY channels or blog-style posts thinking they are videos; claim names that shadow a channel; content types added by newer LBRY releases that the extractor's _SUPPORTED_STREAM_TYPES predates.

Related errors


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