Captcha bypass tutorials

How to bypass captcha with Playwright

How to Integrate captcha solver with Playwright

Learn how to bypass captchass using Playwright and the captcha sovler API — code examples and practical tips.

The problem with captchas in bypass Playwright

Captchas exist to stop bots — and they’re good at it. Whether it’s a signup form, a login page, or a simple contact submission, captchas are the first line of defense against automated access. But if your job is testing or scraping, they’re not just a challenge — they’re a blocker.

In this guide, you’ll learn how to detect captchas on the page, submit them to 2Captcha, wait for a valid token, and inject the solution — all through Playwright.

Playwright capabilities

API for all browsers and platforms:

  • Cross-browser: Playwright works with Chromium, WebKit, and Firefox — no need to change your code to switch engines.
  • Cross-platform: Write once, run anywhere — Linux, macOS, Windows. Headless or full browser mode. Local or CI.
  • Cross-language: Use it with TypeScript, JavaScript, Python, .NET, or Java — whatever fits your stack.
  • Mobile web testing: Emulate Chrome for Android and Safari on iOS using the same engine and APIs. Works identically on desktop and cloud environments.

Use cases

  • Scraping JavaScript-heavy sites: Capture dynamic content that only appears after the page loads and renders in the browser.
  • Handling complex user flows: Automate multi-step forms, login sequences, or any page behind interaction barriers.
  • Extracting from single-page apps: Navigate and pull data from Vue, React, or Angular apps without relying on static HTML.
  • Test automation with real browsers: Combine scraping and testing — collect data while validating that the page works as expected.
  • Run headless in production: Automate everything without opening a GUI — perfect for servers and pipelines.

Install dependencies

To get started, you’ll need a Node.js environment with Playwright installed, a way to make HTTP requests, and access to your {{site_name}} API key.

Step 1: Initialize your project

mkdir captcha-playwright && cd captcha-playwright
npm init -y

Step 2: Install required packages

npm install playwright node-fetch dotenv

Step 3: Create .env and store your API key

API_KEY=your_2captcha_api_key_here
require('dotenv').config();
const API_KEY = process.env.API_KEY;

Detect the captcha type

Before you can solve a captcha, you need to know what you’re dealing with.

Step 1: Inspect the page

<div class="g-recaptcha" data-sitekey="...">
src="https://www.google.com/recaptcha/api.js"

Step 2: Extract the sitekey

To solve a CAPTCHA, you need the sitekey used by the CAPTCHA provider. This is a public identifier embedded in the HTML of the target page. You can find it using browser devtools.

Look for an element like this:

<div class="g-recaptcha" data-sitekey="6LeIxAcTAAAAAJcZVRqyHh71UMIEGNQ_MXjiZKhI"></div>

Or for invisible CAPTCHAs:

<script src="https://www.google.com/recaptcha/api.js?render=SITE_KEY"></script>

Copy the value of the data-sitekey or the render parameter. You'll need it when submitting the CAPTCHA-solving request.

Step 3: Note the URL

You also need the full URL of the page where the CAPTCHA is displayed. This is required by most CAPTCHA-solving APIs to simulate a realistic browser environment.

In Playwright, you can get it programmatically:

const url = page.url();

Or simply copy it from the browser’s address bar. Combine it with the sitekey in your API request to solve the captcha correctly.

Chrome extension

Install the captcha solver extension for Chrome.

Submit

Step 1: Send the task

API v1

const res = await fetch('https://2captcha.com/in.php', {
  method: 'POST',
  body: new URLSearchParams({
    key: API_KEY,
    method: 'userrecaptcha',
    googlekey: SITE_KEY,
    pageurl: SITE_URL,
    json: '1',
  }),
});

API v2

const res = await fetch('https://api.2captcha.com/createTask', {
  method: 'POST',
  body: JSON.stringify({
    clientKey: API_KEY,
    task: {
      type: "RecaptchaV2TaskProxyless",
      websiteURL: SITE_URL,
      websiteKey: SITE_KEY,
      isInvisible: false
    }
  }),
});

Step 2: Wait for the token

After submitting the task, the API needs some time to solve the CAPTCHA. You must poll the API periodically until the solution is ready.

API v1

const waitForToken = async (captchaId) => {
  const url = `https://2captcha.com/res.php?key=${API_KEY}&action=get&id=${captchaId}&json=1`;

  for (let i = 0; i < 20; i++) {
    const res = await fetch(url);
    const data = await res.json();

    if (data.status === 1) return data.request; // solution is ready
    if (data.request !== 'CAPCHA_NOT_READY') throw new Error(`Unexpected error: ${data.request}`);

    await new Promise(resolve => setTimeout(resolve, 5000)); // wait 5 seconds
  }

  throw new Error('Timeout: CAPTCHA solution not received within expected time');
};

API v2

const waitForToken = async (taskId) => {
  const url = 'https://api.2captcha.com/getTaskResult';
  const body = {
    clientKey: API_KEY,
    taskId,
  };

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

    const res = await fetch(url, {
      method: 'POST',
      body: JSON.stringify(body),
    });

    const json = await res.json();
    if (json.status === 'ready') return json.solution.gRecaptchaResponse;
    if (json.status === 'failed') throw new Error(`Captcha failed: ${JSON.stringify(json)}`);
  }

  throw new Error('Timeout: CAPTCHA solution not ready after multiple attempts');
};

This logic ensures the program waits for a valid CAPTCHA solution before proceeding. It's essential to include this in any implementation involving CAPTCHA solving, especially in real-world scenarios where delays are common.

Step 3: Poll for the result

API v1

const res = await fetch(`https://2captcha.com/res.php?key=${API_KEY}&action=get&id=${captchaId}&json=1`);

API v2

const res = await fetch('https://api.2captcha.com/getTaskResult', {
  method: 'POST',
  body: JSON.stringify({
    clientKey: API_KEY,
    taskId
  }),
});

Inject the response

await page.evaluate((token) => {
  document.querySelector('[name="g-recaptcha-response"]').value = token;
}, token);

Full working example

The final example includes launching Playwright, solving a captcha, and submitting a form.

Debugging tips

  • Check sitekey and pageurl
  • Retry if CAPCHA_NOT_READY
  • Use real user-agent and add wait times

Final words

Playwright + {{site_name}} allows you to automate and bypass most captcha challenges reliably.