jackwener/OpenCLI · error · CommandExecutionError

Booking.com served a verification / captcha page; retry…

Error message

Booking.com served a verification / captcha page; retry later or change profile

What it means

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.

Solutions

  1. Wait and retry later — blocks are usually temporary.
  2. Switch to a different browser profile / clear cookies as the message suggests.
  3. Use a less detectable browser setup (non-headless mode, realistic user agent).
  4. Change IP address or route through a residential proxy.
  5. Slow down request rate between searches to avoid triggering rate-based detection.

Example fix

// before (rapid loop, same profile)
for (const d of destinations) await search(d);
// after (throttled, rotating profiles)
for (const d of destinations) { await search(d, { profile: nextProfile() }); await sleep(5000); }
Defensive patterns

Strategy: retry

Try / catch

try {
  return await booking.search(params);
} catch (e) {
  if (/verification \/ captcha/.test(e.message)) {
    await sleep(60_000);            // back off before retrying
    return booking.search({ ...params, profile: rotateProfile() });
  }
  throw e;
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29). Data as JSON: /api/errors/a76ac76f6b449ecc. Report an issue: GitHub.

Appendix: source

Thrown at clis/booking/search.js:284

    } catch (_) {
      // selector wait is best-effort — extractor handles empty case explicitly
    }

    let raw;
    try {
      raw = await page.evaluate(EXTRACTOR);
    } catch (err) {
      throw new CommandExecutionError(`Failed to extract Booking.com cards: ${err?.message || err}`);
    }

    if (raw && typeof raw === 'object' && raw.data && raw.session) {
      raw = raw.data;
    }
    if (!raw || typeof raw !== 'object') {
      throw new CommandExecutionError('Booking.com page returned no extractable data');
    }
    if (raw.blocked) {
      throw new CommandExecutionError('Booking.com served a verification / captcha page; retry later or change profile');
    }

    if (raw.ok !== true) {
      throw new CommandExecutionError('Booking.com extractor returned an invalid status');
    }
    if (!Array.isArray(raw.items)) {
      throw new CommandExecutionError('Booking.com extractor returned malformed items');
    }

    const items = raw.items;
    if (items.length === 0) {
      const totalText = String(raw.totalText || '').trim();
      if (hasPositiveResultCount(totalText)) {
        throw new CommandExecutionError(
          `Booking.com page declared results but no property cards were parsed: ${totalText}`,
        );
      }
      throw new EmptyResultError(

View on GitHub (pinned to 49907e53dc)