How to bypass captchas with Playwright + 2Captcha (or SolveCaptcha)
If you're automating with Playwright and run into captchas — welcome to reality. reCAPTCHA, hCaptcha — they're everywhere. Playwright alone won't help. But pair it with a captcha solving service and you're through.
TL;DR: You send the sitekey and URL to a solving service (like 2Captcha or SolveCaptcha), get back a token, inject it into the page with Playwright, and move on.
When this is useful
- scraping JS-heavy sites
- bypassing auth flows or post-login content
- crawling React/Vue SPAs
- testing flows that include captchas
Setup
npm install playwright node-fetch dotenv
# .env
API_KEY=your_2captcha_or_solvecaptcha_key
Detect the captcha
Use Chrome DevTools or the captcha bypass extension to find data-sitekey. You'll need:
- sitekey
- page URL
Submit captcha to API
const params = {
"clientKey": "YOUR_API_KEY",
"task": {
"type": "RecaptchaV2TaskProxyless",
"websiteURL": "https://2captcha.com/demo/recaptcha-v2",
"websiteKey": "6LfD3PIbAAAAAJs_eEHvoOl75_83eXSqpPSRFJ_u",
"isInvisible": false
}
};
const res = await fetch('https://api.2captcha.com/createTask', {
method: 'POST',
body: JSON.stringify(params),
});
const { taskId } = await res.json();
Poll for solution
const params = {
clientKey: "YOUR_API_KEY",
taskId
}
for (let i = 0; i < 20; i++) {
await new Promise(r => setTimeout(r, 5000));
const res = await fetch('https://api.2captcha.com/getTaskResult', {
method: 'POST',
body: JSON.stringify(params),
});
const json = await res.json();
if (json.status === 'ready') {
token = json.solution.token;
break;
}
}
Inject token in Playwright
await page.evaluate(token => {
const field = document.querySelector('[name="g-recaptcha-response"]');
if (field) field.value = token;
else {
const el = document.createElement('textarea');
el.name = 'g-recaptcha-response';
el.style.display = 'none';
el.value = token;
document.body.appendChild(el);
}
}, token);
Then click the button or trigger submit:
await page.click('#submit-button');
Full script
Use Google demo page to test:
const { chromium } = require('playwright');
// see full working example above (same structure)
Notes
- Works with 2Captcha, SolveCaptcha (same format)
- SolveCaptcha can be faster on some sites, and supports other types too
- Don’t reuse old tokens — they expire fast
- Invisible captchas might auto-submit after token injection
Problems?
- UNSOLVABLE? Retry with new captchaId
- CAPCHA_NOT_READY forever? Wrong sitekey or expired token
- Page does nothing after injection? You missed a JS trigger or need to submit manually
Done.
This isn’t fancy — it’s just reliable. SolveCaptcha or 2Captcha + Playwright will take you through most captchas. Production ready? Depends on your IP pool and solve delay. But it works.
Use proxies. Parallelize solves. Inject and go. Done.