jackwener/OpenCLI · warning · AuthRequiredError
guazi ${contextHint} hit an anti-bot challenge — Guazi may h
Error message
guazi ${contextHint} hit an anti-bot challenge — Guazi may have started gating the mobile site. What it means
After fetching the page, guaziFetch scans the HTML for anti-bot markers (瑞数, reese84, captcha, 滑动验证, verify.guazi, 安全验证) and throws AuthRequiredError when one appears and the page is not a real car-detail page. This signals Guazi has started gating the mobile site behind a JavaScript/CAPTCHA challenge, meaning plain HTTP scraping can no longer proceed.
Source
Thrown at clis/guazi/utils.js:125
let resp;
try {
resp = await fetch(`${GUAZI_M_BASE}${path}`, {
headers: {
'User-Agent': UA,
Referer: `${GUAZI_M_BASE}/`,
'Accept-Language': 'zh-CN,zh;q=0.9',
},
});
} catch (err) {
throw new CommandExecutionError(`guazi ${contextHint} network error: ${err?.message || err}`);
}
if (!resp.ok) {
throw new CommandExecutionError(`guazi ${contextHint} HTTP ${resp.status}`);
}
const html = await resp.text();
// Guazi may eventually push the mobile pages behind their JS challenge.
if (/瑞数|reese84|captcha|滑动验证|verify\.guazi|安全验证/i.test(html) && !/car-detail\/c\d+/.test(html)) {
throw new AuthRequiredError(
'guazi.com',
`guazi ${contextHint} hit an anti-bot challenge — Guazi may have started gating the mobile site.`,
);
}
return html;
}
export { ArgumentError, CommandExecutionError, EmptyResultError };
View on GitHub (pinned to 49907e53dc)
Solutions
- Switch to a residential IP or lower request rate and retry
- Open the same URL in a real browser to confirm whether gating is site-wide or IP-specific
- If gating is permanent, migrate to Guazi's official API or a headless-browser approach that can solve the JS challenge
- Handle AuthRequiredError in the CLI to surface an actionable message to the user
Example fix
// before
const html = await guaziFetch('/car/123', 'car page');
// AuthRequiredError: guazi car page hit an anti-bot challenge...
// after
try {
const html = await guaziFetch('/car/123', 'car page');
} catch (e) {
if (e instanceof AuthRequiredError) {
// fall back to cached data or inform user the site is gated
}
} Defensive patterns
Strategy: fallback
Validate before calling
const probe = await fetch(`${GUAZI_M_BASE}/`, { headers: { 'User-Agent': UA } });
const body = await probe.text();
const gated = /瑞数|reese84|captcha|滑动验证|verify\.guazi|安全验证/i.test(body);
if (gated) throw new Error('guazi is gated for this IP — use a proxy or headless browser'); Type guard
const isAuthRequired = (e) => e instanceof AuthRequiredError;
Try / catch
try {
const html = await guaziFetch(path, hint);
} catch (e) {
if (isAuthRequired(e)) {
// fall back to cached data or a headless-browser path
return headlessFetch(path);
}
throw e;
} Prevention
- Use residential IPs rather than datacenter/VPN ranges
- Keep request rates low and randomized to avoid tripping the WAF
- Pre-warm a headless browser session as a fallback path
- Detect the challenge markers early and alert instead of hammering the site
When it happens
Trigger: guaziFetch returning HTML whose body matches the anti-bot regex while lacking a car-detail/c\d+ marker — i.e. Guazi served a challenge/captcha interstitial instead of content.
Common situations: IP reputation-based gating (datacenter/VPN IPs); Guazi deploying a JS challenge (e.g. RiverSecurity/瑞数) sitewide; burst traffic from the scraper tripping the WAF.
Related errors
- hotels.ctrip.com
- vacations.ctrip.com
- [taxonomy=selector_drift] site=powerchina command=search log
- Trip.com is asking for a verification; complete it in your b
- 请先在共享 Chrome 完成 1688 登录/验证,再重试(${action})
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/2bf5b5095e2cbc1d.
Report an issue: GitHub.