Skip to main content
Version: v2

CAPTCHA Solutions

Browserless provides comprehensive CAPTCHA handling capabilities through both passive detection and programmatic solving approaches. The system automatically detects CAPTCHAs on websites and provides APIs to solve them programmatically across multiple automation libraries.

How it works

The CAPTCHA system operates through Chrome DevTools Protocol (CDP) events and commands, providing real-time detection and solving capabilities:

  • Detection: Browserless.captchaFound event automatically fires when CAPTCHAs are detected
  • Solving: Browserless.solveCaptcha command programmatically solves detected CAPTCHAs
  • Integration: Works seamlessly with live URL sessions and hybrid automation workflows

CAPTCHA Detection

Passive Detection with Event Listeners

Set up automatic CAPTCHA detection using CDP event listeners. The system monitors network traffic patterns and automatically emits events when CAPTCHA services are detected:

const cdp = await page.createCDPSession();
await new Promise((resolve) =>
cdp.on("Browserless.captchaFound", () => {
console.log("Found a captcha!");
return resolve();
})
);

Detection Mechanism

The system automatically detects CAPTCHAs by monitoring network requests and matching against known CAPTCHA service patterns. When a CAPTCHA is detected, the Browserless.captchaFound event is emitted to all active CDP sessions for that page.

CAPTCHA Solving

Programmatic Solving

Once a CAPTCHA is detected, use the Browserless.solveCaptcha command to automatically solve it:

const cdp = await page.createCDPSession();
const { solved, error } = await cdp.send("Browserless.solveCaptcha");
console.log({
solved,
error,
});

Advanced Solving Options

The Browserless.solveCaptcha command supports additional parameters for fine-tuned control:

const result = await cdp.send("Browserless.solveCaptcha", {
// How long to wait for a CAPTCHA to appear (default: 10,000ms)
appearTimeout: 30000,
// Additional solving parameters
});

The response includes comprehensive information about the solving attempt:

  • ok: Boolean indicating if the script can proceed
  • captchaFound: Whether a CAPTCHA was detected
  • message: Human-readable description of what occurred
  • solveAttempted: Whether a solve was attempted
  • solved: True only if CAPTCHA was found AND solved
  • error: Any errors during execution

Script Examples

Puppeteer

Here's a sample snippet you can run to demonstrate this works.

import puppeteer from "puppeteer-core";

const waitForCaptcha = (cdpSession) => {
return new Promise((resolve) =>
cdpSession.on("Browserless.captchaFound", resolve)
);
};

const browserWSEndpoint =
"wss://production-sfo.browserless.io/chromium?token=YOUR_API_TOKEN_HERE&timeout=300000";

try {
const browser = await puppeteer.connect({ browserWSEndpoint });

const page = await browser.newPage();
const cdp = await page.createCDPSession();

await page.goto("https://www.google.com/recaptcha/api2/demo", {
waitUntil: "networkidle0",
});

await waitForCaptcha(cdp);
console.log("Captcha found!");

const { solved, error } = await cdp.send("Browserless.solveCaptcha");
console.log({ solved, error });

// Continue...
await page.click("#recaptcha-demo-submit");
await browser.close();
} catch (e) {
console.error("There was a big error :(", e);
process.exit(1);
}

Playwright

Playwright works a bit different than Puppeteer in regards to its pages, as it uses it own browser protocols to communicate. For that reason, you'll need to connect over CDP. And while most of the steps are the same as in Puppeteer, you should use the default existing context and page instead of creating a new one.

import playwright from "playwright-core";

const waitForCaptcha = (cdpSession) => {
return new Promise((resolve) =>
cdpSession.on("Browserless.captchaFound", resolve)
);
};
const pwEndpoint = `wss://production-sfo.browserless.io/chromium?token=YOUR_API_TOKEN_HERE`;

try {
const browser = await playwright.chromium.connectOverCDP(pwEndpoint);
// 👇 Queue we're re-using the existing context and page
const context = browser.contexts()[0];
const page = context.pages()[0];

await page.goto("https://www.google.com/recaptcha/api2/demo", {
waitUntil: "networkidle0",
});

const cdp = await page.context().newCDPSession(page);
await waitForCaptcha(cdp);
console.log("Captcha found!");

const { solved, error } = await cdp.send("Browserless.solveCaptcha");

console.log({ solved, error });

// Continue...
await page.click("#recaptcha-demo-submit");
await browser.close();
} catch (e) {
console.error("There was a big error :(", e);
process.exit(1);
}
tip

Prevention First: Many passive CAPTCHAs can be prevented from appearing with BrowserQL, which hides signs of browser automation through stealth-first automation.

Integration with Live Sessions

CAPTCHA solving integrates seamlessly with Browserless live URL sessions for hybrid automation workflows. This allows for manual intervention when automated solving fails, providing a fallback mechanism for complex CAPTCHAs.

Performance Considerations

  • CAPTCHA solving can take several seconds to minutes - adjust timeouts accordingly
  • Each CAPTCHA solve attempt costs 10 units
  • Use stealth features and residential proxies to reduce CAPTCHA frequency
  • Consider BrowserQL for prevention-first approach to avoid CAPTCHAs entirely

Next Steps

Ready to enhance your CAPTCHA handling capabilities? Explore these advanced features and techniques to build robust automation workflows: