Tutorials

Solving reCAPTCHA v2 with Node.js Fetch API and CaptchaAI

Node 18+ includes the native fetch API — no axios or node-fetch needed. This guide covers the full reCAPTCHA v2 solve flow with CaptchaAI using only built-in Node.js APIs.


Prerequisites

  • Node.js 18+ (for native fetch)
  • CaptchaAI API key

No external packages required.


Step 1: Submit the reCAPTCHA task

const API_KEY = "YOUR_API_KEY";

async function submitRecaptcha(sitekey, pageurl) {
  const params = new URLSearchParams({
    key: API_KEY,
    method: "userrecaptcha",
    googlekey: sitekey,
    pageurl: pageurl,
    json: "1",
  });

  const response = await fetch("https://ocr.captchaai.com/in.php", {
    method: "POST",
    body: params,
  });

  const data = await response.json();

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

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

Step 2: Poll for the result

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

async function pollResult(taskId) {
  const params = new URLSearchParams({
    key: API_KEY,
    action: "get",
    id: taskId,
    json: "1",
  });

  for (let i = 0; i < 30; i++) {
    await sleep(5000);

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

    if (data.status === 1) {
      console.log("Solved!");
      return data.request;
    }

    if (data.request === "ERROR_CAPTCHA_UNSOLVABLE") {
      throw new Error("CAPTCHA unsolvable");
    }

    console.log(`Polling... (${i + 1}/30)`);
  }

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

Step 3: Complete solve function

async function solveRecaptchaV2(sitekey, pageurl) {
  const taskId = await submitRecaptcha(sitekey, pageurl);
  const token = await pollResult(taskId);
  return token;
}

// Usage
const token = await solveRecaptchaV2(
  "6Le-wvkSAAAAAPBMRTvw0Q4Muexq9bi0DJwx_mJ-",
  "https://example.com/login"
);
console.log(`Token: ${token.substring(0, 50)}...`);

Step 4: Submit the token to the target site

async function submitForm(url, formData) {
  const params = new URLSearchParams(formData);

  const response = await fetch(url, {
    method: "POST",
    headers: {
      "Content-Type": "application/x-www-form-urlencoded",
      "User-Agent":
        "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 Chrome/120.0.0.0 Safari/537.36",
    },
    body: params,
    redirect: "follow",
  });

  return {
    status: response.status,
    url: response.url,
    body: await response.text(),
  };
}

// Full flow
async function loginWithRecaptcha(loginUrl, sitekey, credentials) {
  // Solve reCAPTCHA
  const token = await solveRecaptchaV2(sitekey, loginUrl);

  // Submit login form with token
  const result = await submitForm(loginUrl, {
    ...credentials,
    "g-recaptcha-response": token,
  });

  console.log(`Login result: ${result.status} → ${result.url}`);
  return result;
}

Extracting the sitekey from HTML

async function extractSitekey(url) {
  const response = await fetch(url, {
    headers: {
      "User-Agent":
        "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 Chrome/120.0.0.0 Safari/537.36",
    },
  });
  const html = await response.text();

  // Pattern 1: data-sitekey attribute
  const match = html.match(/data-sitekey=["']([A-Za-z0-9_-]{40})["']/);
  if (match) return match[1];

  // Pattern 2: render parameter in script src
  const renderMatch = html.match(/render=([A-Za-z0-9_-]{40})/);
  if (renderMatch) return renderMatch[1];

  // Pattern 3: grecaptcha.render call
  const renderCall = html.match(
    /grecaptcha\.render\s*\([^,]+,\s*\{[^}]*sitekey\s*:\s*["']([A-Za-z0-9_-]{40})["']/
  );
  if (renderCall) return renderCall[1];

  return null;
}

Production-ready solver class

class RecaptchaV2Solver {
  constructor(apiKey) {
    this.apiKey = apiKey;
  }

  async solve(sitekey, pageurl, options = {}) {
    const taskId = await this.#submit(sitekey, pageurl, options);
    return await this.#poll(taskId);
  }

  async #submit(sitekey, pageurl, options) {
    const body = new URLSearchParams({
      key: this.apiKey,
      method: "userrecaptcha",
      googlekey: sitekey,
      pageurl: pageurl,
      json: "1",
      ...(options.invisible && { invisible: "1" }),
      ...(options.data_s && { "data-s": options.data_s }),
    });

    const resp = await fetch("https://ocr.captchaai.com/in.php", {
      method: "POST",
      body,
    });
    const data = await resp.json();

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

  async #poll(taskId) {
    const params = new URLSearchParams({
      key: this.apiKey,
      action: "get",
      id: taskId,
      json: "1",
    });

    for (let i = 0; i < 30; i++) {
      await new Promise((r) => setTimeout(r, 5000));

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

      if (data.status === 1) return data.request;
      if (data.request === "ERROR_CAPTCHA_UNSOLVABLE") {
        throw new Error("CAPTCHA unsolvable");
      }
    }
    throw new Error("Timed out");
  }
}

// Usage
const solver = new RecaptchaV2Solver("YOUR_API_KEY");
const token = await solver.solve(
  "6Le-wvkSAAAAAPBMRTvw0Q4Muexq9bi0DJwx_mJ-",
  "https://example.com/login"
);

Handling cookies and sessions

async function solveWithSession(loginUrl, sitekey, credentials) {
  // Node.js fetch doesn't handle cookies automatically.
  // Extract Set-Cookie headers manually.

  // Step 1: Get the login page (capture cookies)
  const pageResp = await fetch(loginUrl, { redirect: "manual" });
  const cookies = pageResp.headers.getSetCookie?.() || [];
  const cookieHeader = cookies.map((c) => c.split(";")[0]).join("; ");

  // Step 2: Solve CAPTCHA
  const solver = new RecaptchaV2Solver(API_KEY);
  const token = await solver.solve(sitekey, loginUrl);

  // Step 3: Submit with cookies
  const result = await fetch(loginUrl, {
    method: "POST",
    headers: {
      "Content-Type": "application/x-www-form-urlencoded",
      Cookie: cookieHeader,
    },
    body: new URLSearchParams({
      ...credentials,
      "g-recaptcha-response": token,
    }),
    redirect: "manual",
  });

  return {
    status: result.status,
    location: result.headers.get("location"),
    cookies: result.headers.getSetCookie?.() || [],
  };
}

Troubleshooting

Symptom Cause Fix
fetch is not defined Node.js < 18 Upgrade Node or use node-fetch
ERROR_WRONG_GOOGLEKEY Invalid sitekey Re-extract from the page HTML
Token rejected by server Token expired (>2 min) Submit form faster after solving
Login returns same page Missing CSRF or cookies Extract hidden form fields and send cookies
TypeError: resp.json() Non-JSON response Check response status first

Frequently asked questions

Can I use axios instead of fetch?

Yes. Replace fetch() with axios.post() / axios.get(). The CaptchaAI API works the same regardless of HTTP client.

How long until the token expires?

reCAPTCHA v2 tokens expire after approximately 2 minutes. Solve and submit as quickly as possible.

Does this work with reCAPTCHA v2 Invisible?

Yes. Add invisible: "1" to the submit parameters. The API flow is identical.


Summary

Solve reCAPTCHA v2 with Node.js native fetch and CaptchaAI: extract the sitekey, submit to the API, poll for the token, and inject it into the form POST. No external packages needed on Node 18+.

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.

Related Posts

API Tutorials How to Solve reCAPTCHA v2 Enterprise with Node.js
Solve re CAPTCHA v 2 Enterprise using Node.js and Captcha AI API.

Solve re CAPTCHA v 2 Enterprise using Node.js and Captcha AI API. Complete guide with sitekey detection, task...

Automation reCAPTCHA v2 Node.js
Jan 11, 2026
Reference CAPTCHA Token Injection Methods Reference
Complete reference for injecting solved CAPTCHA tokens into web pages.

Complete reference for injecting solved CAPTCHA tokens into web pages. Covers re CAPTCHA, Turnstile, and Cloud...

Automation Python reCAPTCHA v2
Apr 08, 2026
API Tutorials How to Solve reCAPTCHA v2 Enterprise Using API
Step-by-step guide to solving re CAPTCHA v 2 Enterprise using Captcha AI API.

Step-by-step guide to solving re CAPTCHA v 2 Enterprise using Captcha AI API. Detect Enterprise vs standard, e...

Automation reCAPTCHA v2 reCAPTCHA Enterprise
Jan 26, 2026
API Tutorials Solve reCAPTCHA Invisible with Node.js and CaptchaAI
Step-by-step Node.js tutorial for solving invisible re CAPTCHA v 2 using the Captcha AI API.

Step-by-step Node.js tutorial for solving invisible re CAPTCHA v 2 using the Captcha AI API. Includes site key...

Automation Node.js reCAPTCHA Invisible
Jan 11, 2026
Integrations CAPTCHA Handling in Flutter WebViews with CaptchaAI
Detect and solve re CAPTCHA v 2 and Cloudflare Turnstile CAPTCHAs inside Flutter Web Views using Captcha AI API with Dart code examples and Java Script channel...

Detect and solve re CAPTCHA v 2 and Cloudflare Turnstile CAPTCHAs inside Flutter Web Views using Captcha AI AP...

Automation Python reCAPTCHA v2
Jan 17, 2026
API Tutorials reCAPTCHA Data-S Parameter Explained
Understand the re CAPTCHA data-s parameter: what it is, when it appears, why it matters for solving, and how to extract and include it in API solver requests.

Understand the re CAPTCHA data-s parameter: what it is, when it appears, why it matters for solving, and how t...

Automation reCAPTCHA v2
Jan 23, 2026
API Tutorials How to Solve reCAPTCHA v2 Enterprise with Python
Solve re CAPTCHA v 2 Enterprise using Python and Captcha AI API.

Solve re CAPTCHA v 2 Enterprise using Python and Captcha AI API. Complete guide with sitekey extraction, task...

Automation Python reCAPTCHA v2
Apr 08, 2026
Use Cases CAPTCHA Handling for Domain WHOIS Lookup Automation
Handle re CAPTCHA v 2 and image CAPTCHAs on WHOIS lookup portals to automate domain registration data queries, availability checks, and ownership verification.

Handle re CAPTCHA v 2 and image CAPTCHAs on WHOIS lookup portals to automate domain registration data queries,...

Automation Python reCAPTCHA v2
Jan 20, 2026
Tutorials Pytest Fixtures for CaptchaAI API Testing
Build reusable pytest fixtures to test CAPTCHA-solving workflows with Captcha AI.

Build reusable pytest fixtures to test CAPTCHA-solving workflows with Captcha AI. Covers mocking, live integra...

Automation Python reCAPTCHA v2
Apr 08, 2026
Tutorials Handling Multiple CAPTCHAs on a Single Page
how to detect and solve multiple CAPTCHAs on a single web page using Captcha AI.

Learn how to detect and solve multiple CAPTCHAs on a single web page using Captcha AI. Covers multi-iframe ext...

Python reCAPTCHA v2 Cloudflare Turnstile
Apr 09, 2026
Tutorials Discord Webhook Alerts for CAPTCHA Pipeline Status
Send CAPTCHA pipeline alerts to Discord — webhook integration for balance warnings, error spikes, queue status, and daily summary reports with Captcha AI.

Send CAPTCHA pipeline alerts to Discord — webhook integration for balance warnings, error spikes, queue status...

Automation Python All CAPTCHA Types
Apr 09, 2026
Tutorials Python ThreadPoolExecutor for CAPTCHA Solving Parallelism
Use Python's Thread Pool Executor for concurrent CAPTCHA solving — run multiple Captcha AI requests in parallel without asyncio complexity.

Use Python's Thread Pool Executor for concurrent CAPTCHA solving — run multiple Captcha AI requests in paralle...

Automation Python All CAPTCHA Types
Jan 15, 2026