jackwener/OpenCLI · error · CommandExecutionError

Indeed served a Cloudflare challenge page

Error message

Indeed served a Cloudflare challenge page

What it means

Thrown when the Indeed search page is detected as a Cloudflare challenge page ('Just a moment' title or cf-* elements). The CLI detects and surfaces this instead of returning empty or broken results.

Source

Thrown at clis/indeed/search.js:98

                        jk,
                        title: b.querySelector('h2.jobTitle span')?.textContent?.trim() ?? '',
                        company: b.querySelector('[data-testid="company-name"]')?.textContent?.trim() ?? '',
                        location: b.querySelector('[data-testid="text-location"]')?.textContent?.trim() ?? '',
                        salary: b.querySelector('.salary-snippet-container span')?.textContent?.trim() ?? '',
                        tags,
                    });
                }
                const blockedHeadline = document.title || '';
                const challenge = blockedHeadline.includes('Just a moment') || !!document.querySelector('[id^="cf-"]');
                return { cards: out, challenge, ready };
            })()`);
        }
        catch (e) {
            throw new CommandExecutionError(`Failed to scrape Indeed search DOM: ${e?.message ?? e}`, 'The page may not have fully loaded; try again.');
        }

        if (cards?.challenge) {
            throw new CommandExecutionError('Indeed served a Cloudflare challenge page', 'Open https://www.indeed.com in the connected browser and clear the challenge, then retry.');
        }
        if (!cards?.ready) {
            throw new CommandExecutionError('Indeed search page did not expose result or empty-state markers within 15s', 'Indeed may still be loading or the DOM shape may have changed; retry after opening Indeed in the connected browser.');
        }

        const list = Array.isArray(cards?.cards) ? cards.cards : [];
        if (list.length === 0) {
            throw new EmptyResultError('indeed search', `No Indeed jobs matched "${query}"${location ? ` in ${location}` : ''}`);
        }
        return list.slice(0, limit).map((c, i) => searchCardToRow(c, start + i + 1));
    },
});

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Open https://www.indeed.com in the connected browser and clear the challenge, then retry
  2. Switch to a normal browser profile (non-headless) and a residential IP
  3. Disable VPN/proxy or change network
  4. Add delays between searches to reduce rate-based flagging
  5. Browse Indeed normally once to obtain clearance cookies before scraping
Defensive patterns

Strategy: retry

Validate before calling

const title = await page.title();
if (title.includes('Just a moment') || (await page.$('[id^="cf-"]'))) {
  // clear the challenge manually in the connected browser first
}

Try / catch

try {
  const rows = await indeed.search({ query, location });
} catch (e) {
  if (e.message.includes('Cloudflare challenge')) {
    // pause, ask user to solve challenge in connected browser, then retry
  }
  throw e;
}

Prevention

When it happens

Trigger: cards.challenge is true after evaluating the search page DOM.

Common situations: Flagged IP (VPN/datacenter/proxy); headless browser automation detected; burst of searches from one session; missing Cloudflare clearance cookies after cache clear.

Related errors


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