ytdl-org/youtube-dl · error · ExtractorError
Unable to extract client id
Error message
Unable to extract client id
What it means
SoundcloudIE._update_client_id scrapes soundcloud.com, walks all <script src> URLs in reverse order, and searches each script for a 32-char client_id literal. If no script yields one, it raises 'Unable to extract client id' (unexpected severity in practice - a broken extractor, not a content error). Without a valid client_id every Soundcloud API request would 403, so this fails fast instead.
Source
Thrown at youtube_dl/extractor/soundcloud.py:289
'original': 0,
}
def _store_client_id(self, client_id):
self._downloader.cache.store('soundcloud', 'client_id', client_id)
def _update_client_id(self):
webpage = self._download_webpage('https://soundcloud.com/', None)
for src in reversed(re.findall(r'<script[^>]+src="([^"]+)"', webpage)):
script = self._download_webpage(src, None, fatal=False)
if script:
client_id = self._search_regex(
r'client_id\s*:\s*"([0-9a-zA-Z]{32})"',
script, 'client id', default=None)
if client_id:
self._CLIENT_ID = client_id
self._store_client_id(client_id)
return
raise ExtractorError('Unable to extract client id')
def _download_json(self, *args, **kwargs):
non_fatal = kwargs.get('fatal') is False
if non_fatal:
del kwargs['fatal']
query = kwargs.get('query', {}).copy()
for _ in range(2):
query['client_id'] = self._CLIENT_ID
kwargs['query'] = query
try:
return super(SoundcloudIE, self)._download_json(*args, **compat_kwargs(kwargs))
except ExtractorError as e:
if isinstance(e.cause, compat_HTTPError) and e.cause.code == 401:
self._store_client_id(None)
self._update_client_id()
continue
elif non_fatal:
self._downloader.report_warning(error_to_compat_str(e))View on GitHub (pinned to 956b8c5855)
Solutions
- Update to yt-dlp / latest youtube-dl - this is a site-change breakage fixed upstream typically within days.
- Clear the Soundcloud cache entry (or run --no-cache-dir) so a stale client id is not reused.
- Open https://soundcloud.com in a browser and confirm it loads normally; if the site is down or blocking your IP, wait or change network.
- As a stopgap, extract the current client_id from your browser's network tab and cache it via the extractor's stored-id mechanism.
Example fix
// before
client_id = self._search_regex(
r'client_id\s*:\s*"([0-9a-zA-Z]{32})"',
script, 'client id', default=None)
// after (tolerate single quotes and varied lengths)
client_id = self._search_regex(
r'client_id["\']?\s*[:=]\s*["\']([0-9a-zA-Z]{20,40})["\']',
script, 'client id', default=None) Defensive patterns
Strategy: retry
Validate before calling
webpage = requests.get('https://soundcloud.com/').text
if not re.search(r'<script[^>]+src=', webpage):
warn('Soundcloud unreachable or layout changed - extraction will fail') Type guard
def page_has_script_sources(webpage: str) -> bool:
return bool(re.search(r'<script[^>]+src="([^"]+)"', webpage)) Try / catch
try:
extract(url)
except ExtractorError as e:
if 'Unable to extract client id' == str(e):
update_ytdlp_or_cache_browser_client_id()
else:
raise Prevention
- Update yt-dlp immediately when this appears - it is a site-change breakage.
- Clear the Soundcloud cache entry so a fresh client id is scanned.
- Confirm soundcloud.com loads normally from your network first.
When it happens
Trigger: Soundcloud changes its JS bundle layout: the client_id either moves to a file not referenced by a plain <script src> tag, the regex 'client_id\s*:\s*"([0-9a-zA-Z]{32})"' no longer matches (different quoting/length), or the homepage HTML fails to load. The loop over reversed script tags finding nothing triggers the raise.
Common situations: Soundcloud frontend deploy invalidating the stored/derived client id; an expired cached client_id in the user's cache forcing a re-scan during a Soundcloud outage; network middleboxes mangling the homepage HTML; running an old youtube-dl against a changed Soundcloud build.
Related errors
- unable to download video webpage: %s
- Unable to parse __NEXT_DATA__
- no video on the webpage
- No video found
AI-assisted analysis of ytdl-org/youtube-dl@956b8c5855 (2026-08-14).
Data as JSON: /api/errors/e9e0188aa8487239.
Report an issue: GitHub.