{"record":{"id":"d3692747991f6250","repo":"yt-dlp/yt-dlp","slug":"unable-to-solve-js-challenge","errorCode":null,"errorMessage":"Unable to solve JS challenge","messagePattern":"Unable to solve JS challenge","errorType":"exception","errorClass":"ExtractorError","httpStatus":null,"severity":"error","filePath":"yt_dlp/extractor/tiktok.py","lineNumber":251,"sourceCode":"        self.to_screen('Solving JS challenge using native Python implementation')\n\n        expected_digest = traverse_obj(challenge_data, (\n            'v', 'c', {str}, {base64.b64decode},\n            {require('challenge expected digest')}))\n\n        base_hash = traverse_obj(challenge_data, (\n            'v', 'a', {str}, {base64.b64decode},\n            {hashlib.sha256}, {require('challenge base hash')}))\n\n        for i in range(1_000_001):\n            number = str(i).encode()\n            test_hash = base_hash.copy()\n            test_hash.update(number)\n            if test_hash.digest() == expected_digest:\n                challenge_data['d'] = base64.b64encode(number).decode()\n                break\n        else:\n            raise ExtractorError('Unable to solve JS challenge')\n\n        wci_cookie_value = base64.b64encode(\n            json.dumps(challenge_data, separators=(',', ':')).encode()).decode()\n\n        # At time of writing, the wci cookie name was `_wafchallengeid`\n        wci_cookie_name = traverse_obj(webpage, (\n            {find_element(id='wci', html=True)}, {extract_attributes},\n            'class', {require('challenge cookie name')}))\n\n        # At time of writing, the **optional** rci cookie name was `waforiginalreid`\n        rci_cookie_name = traverse_obj(webpage, (\n            {find_element(id='rci', html=True)}, {extract_attributes}, 'class'))\n        rci_cookie_value = traverse_obj(webpage, (\n            {find_element(id='rs', html=True)}, {extract_attributes}, 'class'))\n\n        # Actual JS sets Max-Age=1 for the cookies, but we'll manually clear them later instead\n        expire_time = int(time.time()) + (self.get_param('sleep_interval_requests') or 0) + 120\n        self._set_cookie('.tiktok.com', wci_cookie_name, wci_cookie_value, expire_time=expire_time)","sourceCodeStart":233,"sourceCodeEnd":269,"githubUrl":"https://github.com/yt-dlp/yt-dlp/blob/81ecd58b1394793e6da9998cc19fdb45657f1685/yt_dlp/extractor/tiktok.py#L233-L269","documentation":"Raised when TikTok's WAF proof-of-work cannot be completed: the brute-force loop tries up to 1,000,000 SHA-256 candidates against the expected digest and finds no match. That means the challenge parameters no longer correspond to the algorithm yt-dlp implements (digest computed differently or encoded another way).","triggerScenarios":"TikTok changes the challenge encoding or hashing scheme so the implemented formula searches the wrong space; occasionally a malformed challenge payload yields an impossible digest.","commonSituations":"Anti-bot algorithm updates between yt-dlp releases; corrupted challenge JSON from truncated responses.","solutions":["Update yt-dlp to pick up an adjusted solver","Retry — malformed challenges are sometimes served transiently","Use cookies from a browser that already passed the challenge","Report persistent occurrences upstream with -v output"],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":"def is_challenge_solver_failure(exc: Exception) -> bool:\n    return isinstance(exc, ExtractorError) and 'solve JS challenge' in str(exc)","tryCatchPattern":"try:\n    info = ydl.extract_info(url, download=False)\nexcept ExtractorError as e:\n    if 'solve JS challenge' in str(e):\n        # algorithm mismatch: only an update or cookies can fix it\n        upgrade_yt_dlp()\n        return retry_with_cookies_if_still_failing(url)\n    raise","preventionTips":["Update yt-dlp first — solver changes are release-blockers and land fast","Reuse browser cookies to avoid solving challenges altogether","Do not write your own solver fork without upstream coordination"],"tags":["tiktok","anti-bot","proof-of-work","challenge-solver"],"backgroundTag":"bot-detection-challenge","analyzedSha":"81ecd58b1394793e6da9998cc19fdb45657f1685","analyzedAt":"2026-08-22T12:21:25.439Z","schemaVersion":2},"datasetVersion":"2026-08-22T14:17:55.899Z"}