yt-dlp/yt-dlp · error · ExtractorError

Unable to get available API hosts

Error message

Unable to get available API hosts

What it means

Raised by AudiusBaseIE._select_api_base: host discovery GETs https://api.audius.co/ and expects get_response_data() to yield a LIST of API host URLs to random.choice() from. If data is not a list, no _API_BASE can be set and every subsequent request is impossible.

Source

Thrown at yt_dlp/extractor/audius.py:32

            response_data = response.get('data')
            if response_data is not None:
                return response_data
            if len(response) == 1 and 'message' in response:
                raise ExtractorError('API error: {}'.format(response['message']),
                                     expected=True)
        raise ExtractorError('Unexpected API response')

    def _select_api_base(self):
        """Selecting one of the currently available API hosts"""
        response = super()._download_json(
            'https://api.audius.co/', None,
            note='Requesting available API hosts',
            errnote='Unable to request available API hosts')
        hosts = self._get_response_data(response)
        if isinstance(hosts, list):
            self._API_BASE = random.choice(hosts)
            return
        raise ExtractorError('Unable to get available API hosts')

    @staticmethod
    def _prepare_url(url, title):
        """
        Audius removes forward slashes from the uri, but leaves backslashes.
        The problem is that the current version of Chrome replaces backslashes
        in the address bar with a forward slashes, so if you copy the link from
        there and paste it into youtube-dl, you won't be able to download
        anything from this link, since the Audius API won't be able to resolve
        this url
        """
        url = urllib.parse.unquote(url)
        title = urllib.parse.unquote(title)
        if '/' in title or '%2F' in title:
            fixed_title = title.replace('/', '%5C').replace('%2F', '%5C')
            return url.replace(title, fixed_title)
        return url

View on GitHub (pinned to 81ecd58b13)

Solutions

  1. Retry the command: discovery runs fresh each time and transient states pass
  2. Open https://api.audius.co/ in a browser; it should print {'data': [...]} with host URLs
  3. Update yt-dlp
  4. Check for interfering proxies if the payload looks like an error page
Defensive patterns

Strategy: retry

Validate before calling

import json, urllib.request
resp = json.load(urllib.request.urlopen('https://api.audius.co/'))
if not isinstance(resp.get('data'), list):
    wait_and_retry()  # discovery unusable; extractor would raise this error

Try / catch

for attempt in range(3):
    try:
        info = ydl.extract_info(url, download=False)
        break
    except yt_dlp.utils.ExtractorError as e:
        if 'Unable to get available API hosts' not in str(e) or attempt == 2:
            raise
        time.sleep(5)  # discovery endpoint transient failure

Prevention

When it happens

Trigger: The discovery endpoint responds 200 but its data is not a list - schema change on Audius' side, a message-only error dict (which first surfaces as 'API error'), or a mangled response from a proxy.

Common situations: Audius changing the discovery contract; transient gateway states; SSL-inspecting or captive-portal networks returning their own JSON.

Related errors


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