Playwright + CaptchaSonic
Solve reCAPTCHA, Turnstile, and more inside Playwright with the CaptchaSonic SDK — solved server-side over gRPC and injected as a token.
Automate captcha solving across Chromium, Firefox, and WebKit in Playwright. CaptchaSonic solves the challenge server-side over a native gRPC connection and returns a ready-to-inject token, so your script submits the form as if a human passed the challenge.
TIP
This walkthrough uses the token flow. The repo also ships a script solver (ScriptSolver) for challenges you want solved in-page.
The complete, runnable project lives on GitHub: playwright-solver.
Install
npm install captchasonic playwright
npx playwright install chromium
export CAPTCHASONIC_API_KEY=sonic_your_key_here # dashboard → API Keys
You need a CaptchaSonic API key with credits (get one, then add funds) and the target page's reCAPTCHA sitekey — found in the page HTML as data-sitekey="…".
Quick start
import { chromium } from 'playwright';
import { CaptchaSonic } from 'captchasonic';
// Solves over a native gRPC connection (no HTTP overhead).
const client = new CaptchaSonic(process.env.CAPTCHASONIC_API_KEY);
const browser = await chromium.launch({ headless: true });
const page = await browser.newPage();
await page.goto('https://example.com/login');
// 1. Read the sitekey from the page.
const sitekey = await page.getAttribute('[data-sitekey]', 'data-sitekey');
// 2. Ask CaptchaSonic for a token (auto-polls, returns when ready).
const result = await client.solveRecaptchaV2Token({
websiteURL: page.url(),
websiteKey: sitekey,
});
const token = result.solution.gRecaptchaResponse;
// 3. Inject the token and submit the form.
await page.evaluate((t) => {
document.querySelector('#g-recaptcha-response').value = t;
}, token);
await page.click('button[type="submit"]');
await browser.close();
How it works
- Read the sitekey from the target page (
data-sitekey). - Solve —
solveRecaptchaV2Token()sends the sitekey and URL to CaptchaSonic over gRPC and resolves once a token is ready. - Inject the returned
gRecaptchaResponseinto the hidden#g-recaptcha-responsefield. - Submit the form — the site's handler reads the token exactly as if a human solved the challenge.
The same client solves reCAPTCHA v3, Cloudflare Turnstile, GeeTest, AWS WAF, and image captchas — see the Node.js SDK reference.
Common pitfalls
- Token bound via callback. Some sites bind the token through a JS callback (
data-callback="…") instead of the field. Call that function with the token:await page.evaluate((t) => window.onCaptchaSolved(t), token). - Token expires before submit. reCAPTCHA tokens live ~120 s — solve as late as possible, right before the submit click.
- Sitekey differs per environment. Read it from the live page at runtime rather than hard-coding it.
- Geo-locked validation. Pass a
proxyoption so the token is solved through your IP when the target validates IP↔token coherence.
See also
- playwright-solver on GitHub — the full example project
- Node.js SDK — every solve method and return shape
- Recipe: reCAPTCHA in Playwright — a focused end-to-end login flow
- reCAPTCHA v2 · Turnstile — task-type references