ytdl-org/youtube-dl · error · ExtractorError

The page doesn't contain any tracks

Error message

The page doesn't contain any tracks

What it means

Raised by BandcampAlbumIE._real_extract when the embedded 'tralbum' JSON blob (read from the page's data attribute) has no 'trackinfo' key or an empty/null trackinfo list. The extractor treats a bandcamp album or discography page as a playlist of tracks; if the embedded metadata carries no track entries there is nothing to return, so it fails with this ExtractorError instead of returning an empty playlist.

Solutions

  1. Confirm the URL points to a real album (contains '/album/') rather than an artist or discography root page.
  2. View page source and check the data-tralbum (or equivalent) attribute actually contains a populated trackinfo array for that URL.
  3. If trackinfo exists but all entries lack 'duration', note the extractor filters those out; a fully filtered list still passes this check, so verify at least one track has duration in the raw JSON.
  4. If the attribute name/schema changed, update _extract_data_attr usage in bandcamp.py:303 to the new embed location.

Example fix

// before
tralbum = self._extract_data_attr(webpage, playlist_id)
track_info = tralbum.get('trackinfo')
if not track_info:
    raise ExtractorError('The page doesn\'t contain any tracks')

// after: distinguish 'no data at all' from 'data present but empty', which aids debugging
tralbum = self._extract_data_attr(webpage, playlist_id)
track_info = tralbum.get('trackinfo')
if not track_info:
    raise ExtractorError('The page doesn\'t contain any tracks' if tralbum else 'Unable to extract album data from page', expected=True)
Defensive patterns

Strategy: validation

Validate before calling

import json, re, requests

def bandcamp_page_has_tracks(url):
    html = requests.get(url).text
    m = re.search(r'data-tralbum="([^"]+)"', html)
    if not m:
        return False
    tralbum = json.loads(m.group(1).replace('"', '"'))
    return bool(tralbum.get('trackinfo'))

Type guard

def has_playable_tracks(tralbum):
    return (
        isinstance(tralbum, dict)
        and isinstance(tralbum.get('trackinfo'), list)
        and any(t.get('duration') for t in tralbum['trackinfo'])
    )

Try / catch

try:
    ydl.extract_info(bc_url)
except ExtractorError as e:
    if "doesn't contain any tracks" in str(e):
        # artist/merch page or layout change; not transient - do not retry
        log.skip(bc_url)
    else:
        raise

Prevention

When it happens

Trigger: Extracting a Bandcamp URL whose _VALID_URL matched (album_id or uploader_id) but whose page's data-tralbum attribute contains trackinfo that is missing, null, or [] — e.g. an artist/discography landing page with no playable album embedded, a track-only page that leaked through suitable(), or a page layout change that moved the tralbum JSON so _extract_data_attr pulls an empty object.

Common situations: Passing a bandcamp artist homepage instead of a specific album URL; Bandcamp A/B testing or redesign moving the embedded tralbum payload; pages region-locked or behind an age/country interstitial that lacks trackinfo; a band whose album has no streaming tracks (merch-only page).

Related errors


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

Appendix: source

Thrown at youtube_dl/extractor/bandcamp.py:303

            'description': 'md5:b3cf845ee41b2b1141dc7bde9237255f',
        },
        'playlist_count': 2,
    }]

    @classmethod
    def suitable(cls, url):
        return (False
                if BandcampWeeklyIE.suitable(url) or BandcampIE.suitable(url)
                else super(BandcampAlbumIE, cls).suitable(url))

    def _real_extract(self, url):
        uploader_id, album_id = re.match(self._VALID_URL, url).groups()
        playlist_id = album_id or uploader_id
        webpage = self._download_webpage(url, playlist_id)
        tralbum = self._extract_data_attr(webpage, playlist_id)
        track_info = tralbum.get('trackinfo')
        if not track_info:
            raise ExtractorError('The page doesn\'t contain any tracks')
        # Only tracks with duration info have songs
        entries = [
            self.url_result(
                urljoin(url, t['title_link']), BandcampIE.ie_key(),
                str_or_none(t.get('track_id') or t.get('id')), t.get('title'))
            for t in track_info
            if t.get('duration')]

        current = tralbum.get('current') or {}

        return {
            '_type': 'playlist',
            'uploader_id': uploader_id,
            'id': playlist_id,
            'title': current.get('title'),
            'description': current.get('about'),
            'entries': entries,
        }

View on GitHub (pinned to 956b8c5855)