jackwener/OpenCLI · error · CommandExecutionError

Upwork served a Cloudflare challenge page

Error message

Upwork served a Cloudflare challenge page

What it means

A CommandExecutionError thrown when the evaluated Upwork page reports a Cloudflare challenge (payload.challenge). Upwork sits behind Cloudflare, and when the challenge interstitial is served there is no Nuxt state to read. The library detects the challenge markers and tells you to clear it interactively because automated navigation cannot pass it.

Source

Thrown at clis/upwork/search.js:91

                    ready,
                    onLogin,
                    challenge,
                    jobsPresent: !!(state && Object.prototype.hasOwnProperty.call(state, 'jobs')),
                    jobs: state ? state.jobs : undefined,
                    paging: state && state.paging ? state.paging : null,
                    status: state ? state.status : null,
                };
            })()`));
        }
        catch (e) {
            throw new CommandExecutionError(`Failed to read Upwork search state: ${e?.message ?? e}`, 'The Nuxt state global was not reachable; try again after opening Upwork in the connected browser.');
        }

        if (payload?.onLogin) {
            throw new AuthRequiredError('upwork.com', 'Upwork redirected to login. Open https://www.upwork.com in the connected browser and sign in, then retry.');
        }
        if (payload?.challenge) {
            throw new CommandExecutionError('Upwork served a Cloudflare challenge page', 'Open https://www.upwork.com in the connected browser and clear the challenge, then retry.');
        }
        if (!payload?.ready) {
            throw new CommandExecutionError('Upwork search state (window.__NUXT__.state.jobsSearch) was not present within 15s', 'The page may not have finished hydrating, or the SSR state shape may have changed.');
        }
        if (!isPlainObject(payload)) {
            throw new CommandExecutionError('Upwork search returned an unexpected Browser Bridge payload shape');
        }
        if (!payload.jobsPresent || !Array.isArray(payload.jobs)) {
            throw new CommandExecutionError('Upwork search state had an unexpected jobs shape; expected window.__NUXT__.state.jobsSearch.jobs to be an array.');
        }

        const jobs = payload.jobs;
        if (jobs.length === 0) {
            throw new EmptyResultError('upwork search', `No Upwork jobs matched "${query}"${location ? ` in ${location}` : ''}`);
        }

        const offset = (pageNum - 1) * perPage;
        const rows = jobsToListRows(jobs, { offset, limit: perPage });

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Open https://www.upwork.com in the connected browser and solve the Cloudflare challenge manually.
  2. Disable the VPN/proxy or switch to a residential IP, then retry.
  3. Slow down the frequency of automated searches to avoid rate-based challenges.
  4. Use a browser profile with established Upwork cookies so Cloudflare trusts the session.

Example fix

// before
await cli.search('node developer') // CommandExecutionError: Cloudflare challenge page
// after
await openBrowser('https://www.upwork.com'); await solveChallengeManually();
await cli.search('node developer')
Defensive patterns

Strategy: retry

Validate before calling

// detect a challenge page before evaluating state
const challenged = await bridge.eval(() =>
  !!document.querySelector('iframe[src*="challenges.cloudflare.com"], #challenge-form, .cf-turnstile'));
if (challenged) throw new Error('Clear the Cloudflare challenge in the browser first');

Type guard

function isChallengePage(doc) {
  return doc.title.includes('Attention Required') ||
    doc.title.includes('Just a moment') ||
    !!doc.querySelector('.cf-turnstile, #challenge-error-text');
}

Try / catch

try {
  rows = await cli.search(query);
} catch (e) {
  if (String(e.message).includes('Cloudflare challenge')) {
    await waitForUserToClearChallenge('https://www.upwork.com'); // long timeout, user-driven
    rows = await cli.search(query);
  } else throw e;
}

Prevention

When it happens

Trigger: Running upwork search while the connected browser is being served a Cloudflare managed challenge / Turnstile interstitial on upwork.com, so the in-page script sets the challenge flag.

Common situations: Requests from a datacenter/VPN IP flagged by Cloudflare; too many rapid searches triggering rate-based challenges; fresh browser profile with no established cookies; Upwork raising protection levels during abuse waves.

Related errors


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