{"record":{"id":"e9e0188aa8487239","repo":"ytdl-org/youtube-dl","slug":"unable-to-extract-client-id","errorCode":null,"errorMessage":"Unable to extract client id","messagePattern":"Unable to extract client id","errorType":"exception","errorClass":"ExtractorError","httpStatus":null,"severity":"error","filePath":"youtube_dl/extractor/soundcloud.py","lineNumber":289,"sourceCode":"        'original': 0,\n    }\n\n    def _store_client_id(self, client_id):\n        self._downloader.cache.store('soundcloud', 'client_id', client_id)\n\n    def _update_client_id(self):\n        webpage = self._download_webpage('https://soundcloud.com/', None)\n        for src in reversed(re.findall(r'<script[^>]+src=\"([^\"]+)\"', webpage)):\n            script = self._download_webpage(src, None, fatal=False)\n            if script:\n                client_id = self._search_regex(\n                    r'client_id\\s*:\\s*\"([0-9a-zA-Z]{32})\"',\n                    script, 'client id', default=None)\n                if client_id:\n                    self._CLIENT_ID = client_id\n                    self._store_client_id(client_id)\n                    return\n        raise ExtractorError('Unable to extract client id')\n\n    def _download_json(self, *args, **kwargs):\n        non_fatal = kwargs.get('fatal') is False\n        if non_fatal:\n            del kwargs['fatal']\n        query = kwargs.get('query', {}).copy()\n        for _ in range(2):\n            query['client_id'] = self._CLIENT_ID\n            kwargs['query'] = query\n            try:\n                return super(SoundcloudIE, self)._download_json(*args, **compat_kwargs(kwargs))\n            except ExtractorError as e:\n                if isinstance(e.cause, compat_HTTPError) and e.cause.code == 401:\n                    self._store_client_id(None)\n                    self._update_client_id()\n                    continue\n                elif non_fatal:\n                    self._downloader.report_warning(error_to_compat_str(e))","sourceCodeStart":271,"sourceCodeEnd":307,"githubUrl":"https://github.com/ytdl-org/youtube-dl/blob/956b8c585591b401a543e409accb163eeaaa1193/youtube_dl/extractor/soundcloud.py#L271-L307","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nclient_id = self._search_regex(\n    r'client_id\\s*:\\s*\"([0-9a-zA-Z]{32})\"',\n    script, 'client id', default=None)\n\n// after (tolerate single quotes and varied lengths)\nclient_id = self._search_regex(\n    r'client_id[\"\\']?\\s*[:=]\\s*[\"\\']([0-9a-zA-Z]{20,40})[\"\\']',\n    script, 'client id', default=None)","handlingStrategy":"retry","validationCode":"webpage = requests.get('https://soundcloud.com/').text\nif not re.search(r'<script[^>]+src=', webpage):\n    warn('Soundcloud unreachable or layout changed - extraction will fail')","typeGuard":"def page_has_script_sources(webpage: str) -> bool:\n    return bool(re.search(r'<script[^>]+src=\"([^\"]+)\"', webpage))","tryCatchPattern":"try:\n    extract(url)\nexcept ExtractorError as e:\n    if 'Unable to extract client id' == str(e):\n        update_ytdlp_or_cache_browser_client_id()\n    else:\n        raise","preventionTips":["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."],"tags":["soundcloud","client-id","site-layout-change","extractor-breakage"],"backgroundTag":null,"analyzedSha":"956b8c585591b401a543e409accb163eeaaa1193","analyzedAt":"2026-08-14T18:59:47.863Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}