ytdl-org/youtube-dl · error · ExtractorError

Invalid url for track %d of album url %s

Error message

Invalid url for track %d of album url %s

What it means

Raised by BandcampAlbumIE-style album crawling in the Audiomack extractor when the per-track album API endpoint (api/music/url/album/<tag>/<track_no>) returns a JSON object with no 'url' key or with an 'error' key. Because Audiomack has no single album-metadata endpoint, the extractor loops itertools.count() querying each track until failure; this particular failure means the album URL tag itself is wrong, not merely the end of the playlist (end-of-playlist is signaled by 'url' being empty/None). It is raised as a hard ExtractorError, so the whole album extraction aborts.

Source

Thrown at youtube_dl/extractor/audiomack.py:131

    def _real_extract(self, url):
        # URLs end with [uploader name]/album/[uploader title]
        # this title is whatever the user types in, and is rarely
        # the proper song title.  Real metadata is in the api response
        album_url_tag = self._match_id(url).replace('/album/', '/')
        result = {'_type': 'playlist', 'entries': []}
        # There is no one endpoint for album metadata - instead it is included/repeated in each song's metadata
        # Therefore we don't know how many songs the album has and must infi-loop until failure
        for track_no in itertools.count():
            # Get song's metadata
            api_response = self._download_json(
                'http://www.audiomack.com/api/music/url/album/%s/%d?extended=1&_=%d'
                % (album_url_tag, track_no, time.time()), album_url_tag,
                note='Querying song information (%d)' % (track_no + 1))

            # Total failure, only occurs when url is totally wrong
            # Won't happen in middle of valid playlist (next case)
            if 'url' not in api_response or 'error' in api_response:
                raise ExtractorError('Invalid url for track %d of album url %s' % (track_no, url))
            # URL is good but song id doesn't exist - usually means end of playlist
            elif not api_response['url']:
                break
            else:
                # Pull out the album metadata and add to result (if it exists)
                for resultkey, apikey in [('id', 'album_id'), ('title', 'album_title')]:
                    if apikey in api_response and resultkey not in result:
                        result[resultkey] = compat_str(api_response[apikey])
                song_id = url_basename(api_response['url']).rpartition('.')[0]
                result['entries'].append({
                    'id': compat_str(api_response.get('id', song_id)),
                    'uploader': api_response.get('artist'),
                    'title': api_response.get('title', song_id),
                    'url': api_response['url'],
                })
        return result

View on GitHub (pinned to 956b8c5855)

Solutions

  1. Verify the album URL in a browser: open http://www.audiomack.com/api/music/url/album/<tag>/0?extended=1 and confirm the JSON contains a non-empty 'url' key.
  2. If the API returns an error envelope, the album tag is wrong or removed — find the current album page URL and re-run with its tag.
  3. If the API JSON shape changed (e.g. 'url' renamed), update the check in _real_extract to match the new schema (audiomack.py:131) and report the breakage upstream.
  4. Distinguish this from the normal end-of-playlist case: end-of-album yields {'url': None} (break), so only a missing/erroring first response means a genuinely invalid URL.

Example fix

// before
api_response = self._download_json('http://www.audiomack.com/api/music/url/album/%s/%d?extended=1&_=%d' % (album_url_tag, track_no, time.time()), album_url_tag, ...)
if 'url' not in api_response or 'error' in api_response:
    raise ExtractorError('Invalid url for track %d of album url %s' % (track_no, url))

// after: validate the first response before entering the loop, so a bad tag fails fast with a clearer message
if track_no == 0 and ('url' not in api_response or 'error' in api_response):
    raise ExtractorError('Invalid album url %s: API returned %r' % (url, api_response), expected=True)
if 'url' not in api_response or 'error' in api_response:
    raise ExtractorError('Invalid url for track %d of album url %s' % (track_no, url))
Defensive patterns

Strategy: validation

Validate before calling

import json, time, urllib.request

def audiomack_album_ok(album_url_tag):
    api = 'http://www.audiomack.com/api/music/url/album/%s/0?extended=1&_=%d' % (album_url_tag, time.time())
    try:
        data = json.load(urllib.request.urlopen(api))
    except Exception:
        return False
    return isinstance(data, dict) and data.get('url') and 'error' not in data

Type guard

def is_valid_audiomack_track_response(r):
    return isinstance(r, dict) and 'url' in r and 'error' not in r

Try / catch

from youtube_dl.utils import ExtractorError
try:
    ydl.extract_info(audiomack_url)
except ExtractorError as e:
    if 'Invalid url for track' in str(e):
        # album tag is wrong or API schema changed; do not retry blindly
        raise ValueError('Audiomack album tag invalid: %s' % audiomack_url) from e
    raise

Prevention

When it happens

Trigger: Calling the audiomack album/playlist extractor with an album_url_tag that does not exist (API responds {'error': ...} or omits 'url' on track 0), or when the site changes its api/music/url/album response schema so 'url' disappears from every response. Any track_no where the response has 'error' set or lacks 'url' triggers it immediately.

Common situations: Typo'd or stale album URL pasted from an old page; album deleted from Audiomack so the tag no longer resolves; Audiomack API schema change (renamed 'url' field or new error envelope); using an uploader name where an album tag is expected because the _VALID_URL groups were misparsed.

Related errors


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