jackwener/OpenCLI · warning · AuthRequiredError

触发了验证码,请先在浏览器中完成验证

Error message

触发了验证码,请先在浏览器中完成验证

What it means

assertNotBlocked inspects the rendered page state after every gotoKe navigation. If the URL was redirected to a captcha page (hip.ke.com/captcha or any /captcha path), it throws AuthRequiredError telling the user to complete the captcha in the browser before CLI scraping can continue. This is Beike's anti-bot gate, not a bug in the command.

Source

Thrown at clis/ke/utils.js:54

      } catch(e) {
        return { href: '', title: '', body_text: '' };
      }
    })()
  `);
    if (!result) {
        return { href: '', title: '', body_text: '' };
    }
    return {
        href: cleanText(result.href),
        title: cleanText(result.title),
        body_text: cleanText(result.body_text),
    };
}

export function assertNotBlocked(state) {
    const { href, title, body_text } = state;
    if (href.includes('hip.ke.com/captcha') || href.includes('/captcha')) {
        throw new AuthRequiredError('ke.com', '触发了验证码,请先在浏览器中完成验证');
    }
    if (CAPTCHA_TEXT_PATTERNS.some(p => title.includes(p) || body_text.includes(p))) {
        throw new AuthRequiredError('ke.com', '触发了验证码,请先在浏览器中完成滑块验证');
    }
    if (LOGIN_TEXT_PATTERNS.some(p => title.includes(p))) {
        throw new AuthRequiredError('ke.com', '未登录,请先在浏览器中登录贝壳找房');
    }
}

export async function gotoKe(page, url) {
    await page.goto(url, { settleMs: 2500 });
    await page.wait(2);
    const state = await readPageState(page);
    assertNotBlocked(state);
    return state;
}

/**

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Open the blocked URL in the managed browser and solve the captcha manually
  2. Slow down / add delays between ke.com requests
  3. Log in (lianjia_token) — authenticated sessions get fewer captchas
  4. Switch network/IP (leave VPN/datacenter ranges) and retry

Example fix

// before
for (const id of ids) await gotoKe(page, url(id)); // captcha after N rapid hits
// after
for (const id of ids) {
  await gotoKe(page, url(id));
  await page.wait(5 + Math.random() * 5); // human-like pacing
}
Defensive patterns

Strategy: retry

Validate before calling

const state = await readPageState(page);
if (state.href.includes('/captcha')) {
  console.log('Captcha detected — solve it in the browser, then re-run');
  process.exit(2);
}

Try / catch

try {
  const state = await gotoKe(page, url);
} catch (e) {
  if (e instanceof AuthRequiredError && e.message.includes('验证码')) {
    console.error('Solve the captcha at ' + url + ' in the browser, then retry');
    await backoff(60_000);
    return gotoKe(page, url); // retry after manual solve / cooldown
  }
  throw e;
}

Prevention

When it happens

Trigger: Any ke.com command whose page.goto results in a redirect to a captcha URL — typically after too-frequent requests, datacenter IP, or a flagged session.

Common situations: Heavy polling/looping over ke.com endpoints; running from a cloud/VPN IP that Beike rate-limits; cookie-less or freshly logged-in session triggering risk control.

Related errors


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