jackwener/OpenCLI · error · AuthRequiredError
Ctrip is asking for a captcha; complete it in your browser s
Error message
Ctrip is asking for a captcha; complete it in your browser session and retry
What it means
An AuthRequiredError raised by `ctrip tour` when WAIT_FOR_VACATIONS_JS detects that vacations.ctrip.com is serving a captcha challenge instead of search results. The library's cookie-based browser session is not trusted by Ctrip's anti-bot system, so it requires the user to solve the captcha interactively in their own browser session and retry.
Source
Thrown at clis/ctrip/tour.js:47
{ name: 'destination', required: true, positional: true, help: 'Destination keyword (e.g. 北京 / 三亚 / 马尔代夫)' },
{ name: 'limit', default: 20, help: 'Number of packages (1-50)' },
],
columns: [
'rank',
'title', 'subtitle',
'tags', 'score', 'sold', 'reviews',
'price',
'url',
],
func: async (page, kwargs) => {
const destination = parsePlaceName('destination', kwargs.destination);
const limit = parseListLimit(kwargs.limit);
const searchUrl = buildTourListUrl(destination);
await page.goto(searchUrl);
const waitResult = await page.evaluate(WAIT_FOR_VACATIONS_JS);
if (waitResult === 'captcha') {
throw new AuthRequiredError('vacations.ctrip.com', 'Ctrip is asking for a captcha; complete it in your browser session and retry');
}
if (waitResult === 'empty') {
throw new EmptyResultError('ctrip tour', `No tour packages for "${destination}"`);
}
if (waitResult !== 'content') {
throw new CommandExecutionError(`Ctrip tour page did not render package cards (state=${String(waitResult)})`);
}
const raw = await page.evaluate(buildVacationsExtractJs());
if (!Array.isArray(raw)) {
throw new CommandExecutionError('Ctrip tour DOM extraction returned malformed rows');
}
if (raw.length === 0) {
throw new CommandExecutionError('Ctrip tour cards rendered but parser did not find required package anchors');
}
return raw.slice(0, limit).map((r, i) => ({
rank: i + 1,
title: r.title,
subtitle: r.subtitle,View on GitHub (pinned to 49907e53dc)
Solutions
- Open vacations.ctrip.com in your normal browser, solve the captcha, and refresh your session cookies used by the CLI
- Re-export fresh cookies after logging in again on ctrip.com
- Slow down request frequency and add delays between commands
- Switch off VPN/proxy or use a residential IP
- Retry the command after completing the captcha
Defensive patterns
Strategy: retry
Validate before calling
// before running: confirm cookies are fresh
if (!fs.existsSync(cookieFile) || isOlderThan(cookieFile, DAYS_7)) {
console.error('Refresh your ctrip.com session cookies first');
process.exit(1);
} Try / catch
try {
const tours = await runCli('ctrip', 'tour', dest);
} catch (e) {
if (e.name === 'AuthRequiredError') {
console.error('Solve the captcha at vacations.ctrip.com in your browser, refresh cookies, then retry');
} else throw e;
} Prevention
- Solve captchas in your normal browser session and re-export cookies regularly
- Avoid datacenter IPs/VPNs that Ctrip risk control flags
- Throttle request frequency; add delays between scrapes
- Use a non-headless or well-configured browser profile to reduce bot detection
When it happens
Trigger: Running `opencli ctrip tour <destination>` when page.evaluate(WAIT_FOR_VACATIONS_JS) returns 'captcha' — Ctrip's risk control intercepted the headless/cookie-authenticated request after page.goto(buildTourListUrl(destination)).
Common situations: Expired or missing login cookies (Strategy.COOKIE); running from a datacenter/VPN IP flagged by Ctrip; too many rapid successive scrapes triggering rate limiting; headless browser fingerprint detection.
Related errors
- Ctrip is asking for a captcha; complete it in your browser s
- Ctrip is asking for a captcha; complete it in your browser s
- 请先在共享 Chrome 完成 1688 登录/验证,再重试(${action})
- Ctrip is asking for a captcha; complete it in your browser s
- Ctrip is asking for a captcha; complete it in your browser s
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/ee0d4503b4ef1e4f.
Report an issue: GitHub.