Use a CAPTCHA solver with Playwright

By solvethree3 min read

Solve the reCAPTCHA Enterprise task first, then submit solution.token through your application's form in Playwright. Use the same proxy and the returned browser identity for that browser request.

The example below targets an owned HTTPS form with a known token field and Submit button. It's an explicit SDK-to-form handoff, not a browser plugin.

On this page

Prepare the dependencies and owned page

  1. 1.

    Install Node.js 22+, Playwright and Chromium

    Install the playwright package and its Chromium browser binary. Install the official solvethree JavaScript SDK using the downloadable solvethree-sdk-0.1.0.tgz package; the Node.js integration instructions provide its direct-download installation command.

  2. 2.

    Configure the hostname in solvethree

    Your owned HTTPS page's hostname must have an active reCAPTCHA profile available to your workspace. Set that up in the console before running the example. Sending a hostname and action in a task doesn't create the profile.

  3. 3.

    Set the three environment variables

    Set TARGET_URL to your complete owned HTTPS page URL, SOLVETHREE_PROXY to the proxy URL, and SOLVETHREE_API_KEY to your workspace API key. Run the script server-side; don't put the API key in page JavaScript. The example uses the action login, which you must change if your application uses a different action.

  4. 4.

    Provide the example form

    The page must contain a textarea named g-recaptcha-response and a button whose accessible name is exactly Submit. If your form differs, adapt the handoff described below before running it.

The task's proxy and Playwright's browser proxy are configured separately. A browser context proxy does not automatically route the SDK's server-side API requests. This example supplies one proxy to the task and reuses it for the browser's target traffic.

Solve, then submit through Playwright

Playwright + Node.js · solve an owned HTTPS form
// Install playwright and the official solvethree SDK first.
import { chromium } from 'playwright';
import { Solvethree } from '@solvethree/sdk';

const target = new URL(process.env.TARGET_URL); // Your configured HTTPS page.
const proxy = new URL(process.env.SOLVETHREE_PROXY);
const client = new Solvethree({ apiKey: process.env.SOLVETHREE_API_KEY });
const result = await client.solve({
  site: target.hostname, action: 'login', proxy: process.env.SOLVETHREE_PROXY,
});
const browser = await chromium.launch();
try {
  const context = await browser.newContext({
    proxy: {
      server: `${proxy.protocol}//${proxy.host}`,
      username: decodeURIComponent(proxy.username),
      password: decodeURIComponent(proxy.password),
    },
    userAgent: result.solution.userAgent,
    extraHTTPHeaders: { 'sec-ch-ua': result.solution.secChUa },
  });
  const page = await context.newPage();
  await page.goto(target.href);
  // This example form has this field and a button named Submit.
  // Adapt the selectors/callback to your own application's form contract.
  await page.locator('[name="g-recaptcha-response"]').waitFor({ state: 'attached' });
  await page.locator('[name="g-recaptcha-response"]').evaluate((field, token) => {
    field.value = token;
    field.dispatchEvent(new Event('input', { bubbles: true }));
  }, result.solution.token);
  await Promise.all([
    page.waitForResponse(response =>
      response.request().method() === 'POST' &&
      new URL(response.url()).origin === target.origin),
    page.getByRole('button', { name: 'Submit', exact: true }).click(),
  ]);
  // Check your application's success response here.
} finally {
  await browser.close();
}

solve creates the task once and polls until it is ready or throws. The browser starts only after that call succeeds. Its context uses the original proxy, including any URL-encoded credentials, and the returned solution.userAgent and solution.secChUa.

The form receives solution.token, not the task ID. The example waits for the field to be attached because a token textarea need not be visible. It assigns the token, dispatches an input event, then clicks Submit.

  • TARGET_URL belongs to your application. The solver task receives its hostname as site; Playwright navigates to the complete URL.
  • login is the example's action. Replace it with the action used by your application.
  • [name="g-recaptcha-response"] is the example's token-field selector. Replace it if your application expects the token in another field or request parameter.
  • Submit is the example button's accessible name. Replace that locator, or use your application's actual submission path.
  • The input event is part of this demo's handoff. A real application may also require a callback, application state update, CSRF value or existing session. There is no universal token-fill callback.

If the form doesn't accept the token

Before paying for another solve, inspect the outgoing application request using Playwright's request and response observation. A ready task means a solution is available; the application's response tells you whether the submission was accepted.

The submitted token is missing or unchanged.

Inspect the actual request parameter, not just the textarea's value.

Try this: Pass solution.token through the application's real submission path. Updating the demo field won't help if the application builds its request from separate state.

The request contains the token but is rejected.

Compare the submission's proxy, user agent, client hints, target hostname and action with the solve. Check the application's session and CSRF requirements.

Try this: Keep the solve and submission on the same proxy, apply the returned browser identity, and satisfy the application's form requirements before submitting.

The script fails before opening the browser.

Distinguish an HTTP request error from a terminal failed task. For a failed task, inspect errorCode and error.

Try this: Correct the reported input, profile or connectivity problem rather than repeatedly submitting unchanged inputs. The SDK throws on failure; don't continue to the token-fill step.

Run your first task.

Start with $5 in workspace credit.

Create a workspace