{"record":{"id":"a76ac76f6b449ecc","repo":"jackwener/OpenCLI","slug":"booking-com-served-a-verification-captcha-page","errorCode":null,"errorMessage":"Booking.com served a verification / captcha page; retry later or change profile","messagePattern":"Booking\\.com served a verification / captcha page; retry later or change profile","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/booking/search.js","lineNumber":284,"sourceCode":"    } catch (_) {\n      // selector wait is best-effort — extractor handles empty case explicitly\n    }\n\n    let raw;\n    try {\n      raw = await page.evaluate(EXTRACTOR);\n    } catch (err) {\n      throw new CommandExecutionError(`Failed to extract Booking.com cards: ${err?.message || err}`);\n    }\n\n    if (raw && typeof raw === 'object' && raw.data && raw.session) {\n      raw = raw.data;\n    }\n    if (!raw || typeof raw !== 'object') {\n      throw new CommandExecutionError('Booking.com page returned no extractable data');\n    }\n    if (raw.blocked) {\n      throw new CommandExecutionError('Booking.com served a verification / captcha page; retry later or change profile');\n    }\n\n    if (raw.ok !== true) {\n      throw new CommandExecutionError('Booking.com extractor returned an invalid status');\n    }\n    if (!Array.isArray(raw.items)) {\n      throw new CommandExecutionError('Booking.com extractor returned malformed items');\n    }\n\n    const items = raw.items;\n    if (items.length === 0) {\n      const totalText = String(raw.totalText || '').trim();\n      if (hasPositiveResultCount(totalText)) {\n        throw new CommandExecutionError(\n          `Booking.com page declared results but no property cards were parsed: ${totalText}`,\n        );\n      }\n      throw new EmptyResultError(","sourceCodeStart":266,"sourceCodeEnd":302,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/booking/search.js#L266-L302","documentation":"This CommandExecutionError is thrown when the extractor reports raw.blocked === true, meaning Booking.com served a verification/captcha (bot-detection) page instead of search results. The library detects this state and refuses to continue, telling the user to retry later or switch the browser profile.","triggerScenarios":"The extractor's blocked flag is set because the loaded page contains Booking.com's challenge/captcha markup — headless-browser detection, too many rapid requests from one IP, or a flagged cookie/profile.","commonSituations":"Running many searches in a loop from one IP in CI; default headless Chromium fingerprint flagged by the anti-bot system; shared datacenter IP with poor reputation; reused profile whose cookies were marked suspicious.","solutions":["Wait and retry later — blocks are usually temporary.","Switch to a different browser profile / clear cookies as the message suggests.","Use a less detectable browser setup (non-headless mode, realistic user agent).","Change IP address or route through a residential proxy.","Slow down request rate between searches to avoid triggering rate-based detection."],"exampleFix":"// before (rapid loop, same profile)\nfor (const d of destinations) await search(d);\n// after (throttled, rotating profiles)\nfor (const d of destinations) { await search(d, { profile: nextProfile() }); await sleep(5000); }","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  return await booking.search(params);\n} catch (e) {\n  if (/verification \\/ captcha/.test(e.message)) {\n    await sleep(60_000);            // back off before retrying\n    return booking.search({ ...params, profile: rotateProfile() });\n  }\n  throw e;\n}","preventionTips":["Throttle searches (multi-second delays) instead of tight loops.","Rotate browser profiles/cookies across runs.","Prefer non-headless or stealth-configured browsers for scraping Booking.com.","Avoid known datacenter IPs; use residential connections where possible.","Stop and back off on the first captcha instead of hammering retries."],"tags":["captcha","bot-detection","scraping"],"backgroundTag":"captcha-challenge","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}