API Tutorials

How to Solve Cloudflare Challenge with Node.js

Cloudflare Challenge is the full-page "Checking your browser…" interstitial that blocks access to protected sites. CaptchaAI solves the challenge and returns a cf_clearance cookie. You use this cookie with the solver's User-Agent and the same proxy IP to access the protected content.

A proxy is required — the cf_clearance cookie is bound to the IP address used during solving.


What you need

Requirement Details
CaptchaAI API key captchaai.com
Node.js 18+ With built-in fetch
Page URL The URL showing the Cloudflare Challenge
HTTP proxy Same IP must be used for solving and subsequent requests

For Node.js versions below 18, install node-fetch:

npm install node-fetch

Step 1: Identify Cloudflare Challenge

Cloudflare Challenge pages show these characteristics:

  • Full-page interstitial with "Checking your browser…" or "Just a moment…"
  • HTTP 403 or 503 status before the challenge is passed
  • After passing, a cf_clearance cookie is set on the domain

If you see an embedded checkbox widget instead, that is Cloudflare Turnstile — use the Turnstile method.


Step 2: Submit the task to CaptchaAI

const API_KEY = "YOUR_API_KEY";
const TARGET_URL = "https://example.com/protected-page";
const PROXY = "user:password@111.111.111.111:8080";

async function submitTask() {
  const params = new URLSearchParams({
    key: API_KEY,
    method: "cloudflare_challenge",
    pageurl: TARGET_URL,
    proxy: PROXY,
    proxytype: "HTTP",
    json: "1",
  });

  const response = await fetch(
    `https://ocr.captchaai.com/in.php?${params}`
  );
  const data = await response.json();

  if (data.status !== 1) {
    throw new Error(`Submit failed: ${data.request}`);
  }

  console.log(`Task submitted. ID: ${data.request}`);
  return data.request;
}

Step 3: Poll for the result

Wait 20 seconds before the first poll, then check every 5 seconds:

function delay(ms) {
  return new Promise((resolve) => setTimeout(resolve, ms));
}

async function pollResult(taskId) {
  await delay(20000);

  for (let attempt = 0; attempt < 30; attempt++) {
    const params = new URLSearchParams({
      key: API_KEY,
      action: "get",
      id: taskId,
      json: "1",
    });

    const response = await fetch(
      `https://ocr.captchaai.com/res.php?${params}`
    );
    const data = await response.json();

    if (data.status === 1) {
      console.log(`Solved. cf_clearance: ${data.request.substring(0, 50)}...`);
      return {
        cfClearance: data.request,
        userAgent: data.user_agent || "",
      };
    }

    if (data.request !== "CAPCHA_NOT_READY") {
      throw new Error(`Solve failed: ${data.request}`);
    }

    console.log(`Attempt ${attempt + 1}: not ready, waiting 5s...`);
    await delay(5000);
  }

  throw new Error("Solve timed out");
}

Step 4: Access the protected page

Use the cf_clearance cookie with the exact same proxy and User-Agent:

async function accessProtectedPage(cfClearance, userAgent) {
  const response = await fetch(TARGET_URL, {
    headers: {
      "User-Agent": userAgent,
      Cookie: `cf_clearance=${cfClearance}`,
    },
  });

  console.log(`Status: ${response.status}`);
  const text = await response.text();
  console.log(`Content length: ${text.length}`);
  return text;
}

Note: The example above uses a direct Cookie header. In production, use the same proxy for this request. With libraries like axios or got, configure the proxy via an HTTP agent.


Complete working script

const API_KEY = "YOUR_API_KEY";
const TARGET_URL = "https://example.com/protected-page";
const PROXY = "user:password@111.111.111.111:8080";

function delay(ms) {
  return new Promise((resolve) => setTimeout(resolve, ms));
}

async function solveCloudflareChallenge() {
  // Submit task
  const submitParams = new URLSearchParams({
    key: API_KEY,
    method: "cloudflare_challenge",
    pageurl: TARGET_URL,
    proxy: PROXY,
    proxytype: "HTTP",
    json: "1",
  });

  const submitRes = await fetch(
    `https://ocr.captchaai.com/in.php?${submitParams}`
  );
  const submitData = await submitRes.json();

  if (submitData.status !== 1) {
    throw new Error(`Submit error: ${submitData.request}`);
  }

  const taskId = submitData.request;
  console.log(`Task ID: ${taskId}`);

  // Poll for result
  await delay(20000);

  for (let i = 0; i < 30; i++) {
    const pollParams = new URLSearchParams({
      key: API_KEY,
      action: "get",
      id: taskId,
      json: "1",
    });

    const pollRes = await fetch(
      `https://ocr.captchaai.com/res.php?${pollParams}`
    );
    const pollData = await pollRes.json();

    if (pollData.status === 1) {
      return {
        cfClearance: pollData.request,
        userAgent: pollData.user_agent || "",
      };
    }

    if (pollData.request !== "CAPCHA_NOT_READY") {
      throw new Error(`Solve error: ${pollData.request}`);
    }

    await delay(5000);
  }

  throw new Error("Solve timed out");
}

(async () => {
  const { cfClearance, userAgent } = await solveCloudflareChallenge();
  console.log(`cf_clearance: ${cfClearance.substring(0, 50)}...`);
  console.log(`User-Agent: ${userAgent}`);

  // Access protected page
  const response = await fetch(TARGET_URL, {
    headers: {
      "User-Agent": userAgent,
      Cookie: `cf_clearance=${cfClearance}`,
    },
  });
  console.log(`Page status: ${response.status}`);
})();

Expected output:

Task ID: 73849562810
cf_clearance: v_5.0.21_1689012345_0_MDE2YWUx...
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64)...
Page status: 200

Troubleshooting

Error Cause Fix
ERROR_BAD_PROXY Proxy is dead or blocked by Cloudflare Use a working residential proxy
ERROR_CAPTCHA_UNSOLVABLE Challenge could not be solved Verify the URL shows a Challenge page, try a different proxy
ERROR_PAGEURL Missing page URL Include the full URL
403 after injecting cookie IP mismatch Use the same proxy for solving and subsequent requests
403 after injecting cookie User-Agent mismatch Use the exact User-Agent returned by CaptchaAI

FAQ

Why is a proxy required for Cloudflare Challenge?

The cf_clearance cookie is bound to the IP address. If you request the site from a different IP, Cloudflare rejects the cookie.

How long does cf_clearance last?

Typically 15–30 minutes. Monitor for 403 responses and re-solve when the cookie expires.

Can I use cf_clearance for multiple pages on the same domain?

Yes. The cookie is domain-scoped, so it works for all pages on that domain within its validity window.

What proxy type works best?

Residential proxies have the highest success rate. Datacenter proxies are more likely to be blocked by Cloudflare.

How is Cloudflare Challenge different from Turnstile?

Challenge is a full-page blocker returning a cf_clearance cookie. Turnstile is an embedded form widget returning a token. Challenge requires a proxy; Turnstile does not.


Start solving Cloudflare Challenges

Get your API key at captchaai.com. Use method=cloudflare_challenge with a proxy to get cf_clearance cookies.


Full Working Code

Complete runnable examples for this article in Python, Node.js, PHP, Go, Java, C#, Ruby, Rust, Kotlin & Bash.

View on GitHub →

Discussions (0)

No comments yet.