jackwener/OpenCLI · error · AuthRequiredError

Ctrip flight API returned HTTP ${status}; complete any verif

Error message

Ctrip flight API returned HTTP ${status}; complete any verification in the browser and retry

What it means

This AuthRequiredError is thrown when a captured Ctrip batchSearch response comes back with HTTP 401 or 403, meaning flights.ctrip.com rejected the request as unauthenticated or forbidden. The library drives a real browser and captures the API response via CDP; Ctrip's risk-control layer (login state, device fingerprint, anti-bot checks) decides who may call the endpoint, so a 401/403 means the session needs human verification rather than a code fix. The library throws this instead of a generic error so callers know to complete any CAPTCHA/verification in the browser and retry.

Source

Thrown at clis/ctrip/flight.js:69

function cabinLabel(value) {
    const labels = { Y: '经济舱', S: '超级经济舱', C: '公务舱', F: '头等舱' };
    const codes = [...new Set(cleanString(value).toUpperCase().match(/[YSCF]/g) || [])];
    return codes.length > 0 ? codes.map((code) => labels[code]).join('/') : (cleanString(value) || null);
}

function parseBatchSearchCaptures(entries) {
    if (!Array.isArray(entries)) {
        throw new CommandExecutionError('Ctrip flight network capture returned malformed entries');
    }
    const captured = entries.filter((entry) => String(entry?.url || '').includes(CAPTURE_PATTERN));
    if (captured.length === 0) return null;

    const byId = new Map();
    let finished = false;
    for (const entry of captured) {
        const status = Number(entry?.responseStatus || 0);
        if (status === 401 || status === 403) {
            throw new AuthRequiredError('flights.ctrip.com', `Ctrip flight API returned HTTP ${status}; complete any verification in the browser and retry`);
        }
        if (status !== 200) {
            throw new CommandExecutionError(`Ctrip flight API returned HTTP ${status || 'unknown'}`);
        }
        if (entry?.responseBodyTruncated === true) {
            throw new CommandExecutionError('Ctrip flight API response exceeded the browser capture limit');
        }
        if (typeof entry?.responsePreview !== 'string') {
            throw new CommandExecutionError('Ctrip flight API response body was unavailable');
        }
        let payload;
        try {
            payload = JSON.parse(entry.responsePreview);
        }
        catch {
            throw new CommandExecutionError('Ctrip flight API returned invalid JSON');
        }
        if (payload?.status !== 0) {

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Open the browser session used by the CLI, complete any CAPTCHA or login/verification prompt on flights.ctrip.com, then re-run the itineraries command.
  2. Re-authenticate (log into Ctrip in the automation browser) so the session has valid credentials before retrying.
  3. Slow down request rate or rotate to a residential IP if Ctrip risk control keeps blocking the session.
  4. Catch AuthRequiredError in your wrapper and surface an interactive-retry step to the user instead of auto-retrying.

Example fix

// before: blind retry loop
while (tries--) { await cli.itineraries(args); }
// after: catch auth error and prompt for human verification
try {
  const rows = await cli.itineraries(args);
} catch (err) {
  if (err instanceof AuthRequiredError) {
    console.error('Complete verification in the browser, then rerun.');
    await promptUserToVerifyBrowser(); // then retry once
  } else throw err;
}
Defensive patterns

Strategy: try-catch

Try / catch

try {
  const rows = await cli.itineraries(args);
} catch (err) {
  if (err instanceof AuthRequiredError) {
    // surface to user: open browser, complete CAPTCHA/login on flights.ctrip.com, retry once
    await interactiveVerifyAndRetry();
  } else { throw err; }
}

Prevention

When it happens

Trigger: Any itineraries search run where the captured /international/search/api/search/batchSearch response has responseStatus 401 or 403 — e.g. an expired or missing Ctrip login session, a flagged bot-like session, or Ctrip's risk control serving a challenge that the automated flow did not complete.

Common situations: Running the CLI after long gaps so the Ctrip session cookie expired; headless-browser fingerprints tripping Ctrip's anti-bot; running from datacenter IPs or high request volume; the in-page CAPTCHA (验证码/安全验证) appearing mid-flow.

Related errors


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