{"record":{"id":"920330645b5a6581","repo":"can1357/oh-my-pi","slug":"google-returned-its-javascript-challenge-instead-o","errorCode":null,"errorMessage":"Google returned its JavaScript challenge instead of rendered search results.","messagePattern":"Google returned its JavaScript challenge instead of rendered search results\\.","errorType":"exception","errorClass":"SearchProviderError","httpStatus":429,"severity":"error","filePath":"packages/coding-agent/src/web/search/providers/google.ts","lineNumber":156,"sourceCode":"\t\t\tthrow new SearchProviderError(\"google\", \"Google browser search timed out.\", 504);\n\t\t}\n\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\tthrow new SearchProviderError(\"google\", `Google browser search failed: ${message}`, 503);\n\t}\n\n\tconst blocked = blockReason(page);\n\tif (blocked === \"traffic\") {\n\t\tthrow new SearchProviderError(\n\t\t\t\"google\",\n\t\t\t\"Google blocked the browser search with an automated-traffic challenge. Try another web search provider or retry later.\",\n\t\t\t429,\n\t\t);\n\t}\n\tif (page.status < 200 || page.status >= 300) {\n\t\tthrow new SearchProviderError(\"google\", `Google HTML error (${page.status})`, page.status);\n\t}\n\tif (blocked === \"javascript\") {\n\t\tthrow new SearchProviderError(\n\t\t\t\"google\",\n\t\t\t\"Google returned its JavaScript challenge instead of rendered search results.\",\n\t\t\t429,\n\t\t);\n\t}\n\treturn page.html;\n}\n\n/** Execute a Google web search with fetch-first loading and a headless-browser fallback. */\nexport async function searchGoogle(params: SearchParams): Promise<SearchResponse> {\n\tconst numResults = clampNumResults(params.numSearchResults ?? params.limit, DEFAULT_NUM_RESULTS, MAX_NUM_RESULTS);\n\tconst html = await callGoogleHtml(params, numResults);\n\tconst parsed = parseHtmlResults(html);\n\n\tconst sources: SearchSource[] = [];\n\tconst seen = new Set<string>();\n\tfor (const result of parsed) {\n\t\tif (seen.has(result.url)) continue;","sourceCodeStart":138,"sourceCodeEnd":174,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/web/search/providers/google.ts#L138-L174","documentation":"Thrown by callGoogleHtml when the page loads with a 2xx status but its HTML contains the '/httpservice/retry/enablejs' marker with no <h3> result headings — Google served its JavaScript challenge/consent page instead of rendered results. The headless-browser fallback that should execute Google's JS either did not run, failed, or still got the no-JS page.","triggerScenarios":"fetch-first path received the enablejs page and the headless-browser fallback was unavailable, timed out at the `a h3` ready selector, or itself returned a page matching blockReason === 'javascript'; page.status is 2xx and not a traffic block.","commonSituations":"Headless browser not installed in the environment (fallback skipped or broken); consent-wall regions (e.g. EU cookie consent variants); Google A/B serving the JS challenge to plain fetch clients.","solutions":["Ensure the headless browser runtime is installed so the browser fallback can render the JS challenge.","Retry later — Google serves the challenge inconsistently.","Switch to an API-backed search provider (Jina, Gemini) which is not affected by JS challenges.","Update the package; detection and fallback heuristics are maintained against Google changes."],"exampleFix":"# before: minimal image without browser\nFROM node:22-slim\n# after: include browser deps for the fallback\nFROM node:22-slim\nRUN npx playwright install --with-deps chromium","handlingStrategy":"fallback","validationCode":null,"typeGuard":"function isJsChallenge(e: unknown): boolean {\n  return e instanceof SearchProviderError && e.provider === 'google'\n    && e.statusCode === 429 && e.message.includes('JavaScript challenge');\n}","tryCatchPattern":"try {\n  return await search({ provider: 'google', query });\n} catch (err) {\n  if (isJsChallenge(err)) return await search({ provider: 'jina', query });\n  throw err;\n}","preventionTips":["Ensure the headless browser fallback is installed so JS challenges can render.","Handle EU/consent-wall regions via an API-backed provider.","Watch for the challenge marker in logs to detect when Google tightens bot detection.","Update the package when Google changes challenge heuristics."],"tags":["scraping","javascript","google","captcha","search-provider"],"backgroundTag":"javascript-challenge-page","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}