ytdl-org/youtube-dl · error · ExtractorError

No downloadable streams found

Error message

No downloadable streams found

What it means

Raised by TuneInBaseIE when the content JSON contains no 'StreamUrl' field: the id resolved (title/logo present) but TuneIn exposes no playable stream list for it. Expected=True, meaning 'nothing to download for this station/show'.

Source

Thrown at youtube_dl/extractor/tunein.py:32

    @staticmethod
    def _extract_urls(webpage):
        return re.findall(
            r'<iframe[^>]+src=["\'](?P<url>(?:https?://)?tunein\.com/embed/player/[pst]\d+)',
            webpage)

    def _real_extract(self, url):
        content_id = self._match_id(url)

        content_info = self._download_json(
            self._API_BASE_URL + self._API_URL_QUERY % content_id,
            content_id, note='Downloading JSON metadata')

        title = content_info['Title']
        thumbnail = content_info.get('Logo')
        location = content_info.get('Location')
        streams_url = content_info.get('StreamUrl')
        if not streams_url:
            raise ExtractorError('No downloadable streams found', expected=True)
        if not streams_url.startswith('http://'):
            streams_url = compat_urlparse.urljoin(url, streams_url)

        streams = self._download_json(
            streams_url, content_id, note='Downloading stream data',
            transform_source=lambda s: re.sub(r'^\s*\((.*)\);\s*$', r'\1', s))['Streams']

        is_live = None
        formats = []
        for stream in streams:
            if stream.get('Type') == 'Live':
                is_live = True
            reliability = stream.get('Reliability')
            format_note = (
                'Reliability: %d%%' % reliability
                if reliability is not None else None)
            formats.append({
                'preference': (

View on GitHub (pinned to 956b8c5855)

Solutions

  1. Open the tunein.com page in a browser and confirm a player actually streams
  2. If it is a show/podcast page, list and extract the individual episode URLs instead of the parent id
  3. Retry later if the station is temporarily down; stream availability changes
  4. Update to yt-dlp for current TuneIn API handling
Defensive patterns

Strategy: validation

Validate before calling

info = ydl.extract_info(api_url, download=False)
# equivalent pre-check: fetch content JSON and confirm 'StreamUrl' is present
if not content_info.get('StreamUrl'):
    raise Skip('no streams for %s' % content_id)

Try / catch

try:
    ydl.extract_info(tunein_url)
except ExtractorError as e:
    if e.expected and 'No downloadable streams' in str(e):
        if is_show_page(tunein_url):
            extract_episodes_individually(tunein_url)
        else:
            schedule_retry(url)

Prevention

When it happens

Trigger: Extracting a tunein.com station id whose API entry has StreamUrl empty/absent: station currently off-air in the API, a stub/placeholder page (e.g. an upcoming show id), or content Tunein no longer carries.

Common situations: Podcast-show pages whose episodes must be extracted individually rather than the show id; temporarily offline streams; regional variants of stations lacking stream URLs for your market.

Related errors


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