Repository: yt-dlp/yt-dlp
File: yt_dlp/extractor/bandcamp.py (Python)

Code before:
        },
    }, {
        'url': 'https://bandcamp.com/?blah/blah@&show=228',
        'only_matching': True,
    }]

    def _real_extract(self, url):
        show_id = self._match_id(url)
        show_data = self._download_json(
            'https://bandcamp.com/api/bcradio_api/1/get_show',
            show_id,
            'Downloading Show Data.',
            data=json.dumps({'id': show_id}).encode(),
            headers={
                'Content-Type': 'application/json',
                'Origin': 'https://bandcamp.com',
                'Referer': 'https://bandcamp.com/',
            },
        )
        raw_metadata = self._extract_data_attr(
            self._download_webpage(
                url,
                show_id,
                'Downloading Show Metadata.',
            ), show_id, 'blob',
        )
        metadata = traverse_obj(raw_metadata, (
            'appData', 'shows', lambda _, mb: int(mb.get('showId')) == int(show_id),
            any))

        audio_data = show_data['radioShowAudio']
        thum_id = metadata.get('imageId')
        thum_url = f'https://f4.bcbits.com/img/000{thum_id}_171.jpg' if thum_id else None

        return {
            'id': show_id,
            'title': metadata.get('title'),
            'thumbnail': thum_url or None,
            'description': metadata.get('desc') or metadata.get('short_desc'),
            'duration': float_or_none(show_data.get('duration')),
            'is_live': False,
            'release_date': unified_strdate(metadata.get('date')),
            'timestamp': unified_timestamp(metadata.get('date')),
            'series': 'Bandcamp Weekly',
            'episode_id': show_id,
            'url': audio_data.get('streamUrl'),
            'ext': 'mp3',
            'vcodec': 'none',
            'format_id': f'mp3-{show_id}',
        }


Review comment (refactor):
this should be non-fatal because the only values we can't also get from the API response data are the `description` and `thumbnail`
```suggestion
        raw_metadata = self._extract_data_attr(
            self._download_webpage(url, show_id, fatal=False), show_id, 'blob', fatal=False)
```

Code after:
            'duration': 5829.77,
        },
        'params': {
            'format': 'mp3-128',
        },
    }, {
        'url': 'https://bandcamp.com/radio/?foo=bar&show=224',
        'only_matching': True,
    }]

    def _real_extract(self, url):
        show_id = self._match_id(url)
        audio_data = self._download_json(
            'https://bandcamp.com/api/bcradio_api/1/get_show',
            show_id, 'Downloading radio show JSON',
            data=json.dumps({'id': show_id}).encode(),
            headers={'Content-Type': 'application/json'})['radioShowAudio']

        stream_url = audio_data['streamUrl']
        format_id = traverse_obj(stream_url, ({parse_qs}, 'enc', -1))
        encoding, _, bitrate_str = (format_id or '').partition('-')

        webpage = self._download_webpage(url, show_id, fatal=False)
        metadata = traverse_obj(
            self._extract_data_attr(webpage, show_id, 'blob', fatal=False),
            ('appData', 'shows', lambda _, v: str(v['showId']) == show_id, any)) or {}

        series_title = audio_data.get('title') or metadata.get('title')
        release_timestamp = unified_timestamp(audio_data.get('date')) or unified_timestamp(metadata.get('date'))

        return {
            'id': show_id,
            'episode_id': show_id,
            'title': join_nonempty(series_title, strftime_or_none(release_timestamp, '%Y-%m-%d'), delim=', '),
            'series': series_title,
            'thumbnail': format_field(metadata, 'imageId', 'https://f4.bcbits.com/img/%s_0.jpg', default=None),
            'description': metadata.get('desc') or metadata.get('short_desc'),
            'duration': float_or_none(audio_data.get('duration')),
            'release_timestamp': release_timestamp,
            'formats': [{
                'url': stream_url,
                'format_id': format_id,
                'ext': encoding or 'mp3',
                'acodec': encoding or None,
                'vcodec': 'none',
                'abr': int_or_none(bitrate_str),
            }],
        }


class BandcampUserIE(InfoExtractor):