{"record":{"id":"c5d648c0ad8233c0","repo":"jackwener/OpenCLI","slug":"trip-com-is-asking-for-a-verification-complete-it-c5d648","errorCode":null,"errorMessage":"Trip.com is asking for a verification; complete it in your browser session and retry","messagePattern":"Trip\\.com is asking for a verification; complete it in your browser session and retry","errorType":"exception","errorClass":"AuthRequiredError","httpStatus":null,"severity":"warning","filePath":"clis/trip/tour.js","lineNumber":59,"sourceCode":"        'rank',\n        'name', 'type',\n        'rating', 'reviews',\n        'price', 'currency',\n        'url',\n    ],\n    func: async (page, kwargs) => {\n        const query = parseKeyword('query', kwargs.query);\n        const tourType = parseTourType(kwargs.type);\n        const limit = parseListLimit(kwargs.limit);\n\n        const searchUrl = buildTourSearchUrl(query, tourType);\n        await page.goto(searchUrl);\n        const result = await page.evaluate(buildTourSearchJs(query));\n        if (!result || typeof result !== 'object') {\n            throw new CommandExecutionError('Trip.com tour search returned malformed data');\n        }\n        if (result.status === 'captcha') {\n            throw new AuthRequiredError('trip.com', 'Trip.com is asking for a verification; complete it in your browser session and retry');\n        }\n        if (result.status === 'empty') {\n            throw new EmptyResultError('trip tour', `No ${kwargs.type || 'private'} tours for \"${query}\"`);\n        }\n        if (result.status !== 'content') {\n            throw new CommandExecutionError(`Trip.com tour search did not return results (state=${String(result.status)})`);\n        }\n        // Products captured but none carry a name is drift (schema moved), not an empty search;\n        // a genuine no-match resolves as status 'empty' above off the page's \"0 routes found\".\n        const rows = Array.isArray(result.rows) ? result.rows.filter((r) => r.name) : [];\n        if (rows.length === 0) {\n            throw new CommandExecutionError('Trip.com tour search captured products but none carried a name (the product markup may have changed)');\n        }\n        return rows.slice(0, limit).map((r, i) => ({\n            rank: i + 1,\n            name: r.name,\n            type: r.type,\n            rating: r.rating,","sourceCodeStart":41,"sourceCodeEnd":77,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/trip/tour.js#L41-L77","documentation":"This AuthRequiredError is thrown when Trip.com serves a CAPTCHA/verification challenge instead of tour results. Browser-automation-driven scraping trips Trip.com's bot detection, and the library cannot proceed until a human solves the challenge in the shared browser session.","triggerScenarios":"The tour search page's evaluate reports result.status === 'captcha' — typically after rapid repeated searches, from datacenter IPs/VPNs, or with a browser session lacking prior cookies.","commonSituations":"Scripting many tour queries in quick succession; running from cloud CI with an unwarmed browser profile; Trip.com tightening anti-bot rules for your region/IP.","solutions":["Open the browser session interactively, complete the CAPTCHA, then rerun the command — cookies carry over.","Slow down: add delays between searches and reduce request volume.","Run from a residential IP or disable VPN/datacenter egress.","Rebuild the browser session with a warmed, logged-in profile so bot checks are less aggressive."],"exampleFix":"// before\nfor (const q of queries) await searchTours(q); // rapid loop -> captcha\n// after\nfor (const q of queries) {\n  await searchTours(q).catch(e => { if (e.name === 'AuthRequiredError') pauseForHumanVerification(); else throw e; });\n  await sleep(5000);\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":"function isCaptchaResult(r) { return r != null && typeof r === 'object' && r.status === 'captcha'; }","tryCatchPattern":"try {\n  const rows = await tourSearch(query, type);\n} catch (e) {\n  if (e instanceof AuthRequiredError) {\n    await openBrowserForManualVerification(e.message); // user solves CAPTCHA\n    return tourSearch(query, type);\n  }\n  throw e;\n}","preventionTips":["Space out searches; avoid tight loops of Trip.com requests.","Use a persistent, cookie-warmed browser profile, ideally logged in.","Avoid datacenter/VPN IPs; prefer residential egress.","Handle AuthRequiredError by pausing for human verification rather than hammering retries."],"tags":["captcha","bot-detection","authentication"],"backgroundTag":"captcha-challenge","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}