CAPTCHA Solving
Browserless detects and solves CAPTCHAs programmatically using Chrome DevTools Protocol events and commands. Use stealth routes to prevent CAPTCHAs from appearing in the first place. This page covers what to do when they still appear.
How it works
The CAPTCHA system operates through Chrome DevTools Protocol (CDP) events and commands:
- Automatic CAPTCHA solving: Add
solveCaptchas=trueto your connection URL to monitor and solve CAPTCHAs in real-time without manual CDP commands - Detection: The
Browserless.captchaFoundevent fires automatically when a CAPTCHA is detected - Solving: The
Browserless.solveCaptchacommand programmatically solves detected CAPTCHAs
Automatic CAPTCHA Solving
Add solveCaptchas=true to your connection URL. Browserless then monitors the entire session for CAPTCHAs and solves them as they appear — including on later navigations, popups, and async-loaded forms. Listeners you attach once at the start of the session keep working across every page, so there's no need to re-attach after navigation.
You only need to wait for Browserless.captchaAutoSolved at points where your next action depends on a solved CAPTCHA — typically before submitting a form. The solved token is automatically injected into the page DOM, so you don't need to read or pass it yourself.
The example below starts on the 2captcha homepage (no CAPTCHA there), then clicks through to a reCAPTCHA v2 demo page. The CAPTCHA only appears after the second navigation — but because the listener was attached at the start of the session, it catches the auto-solve event without any re-attachment.
- Puppeteer
- Playwright
import puppeteer from "puppeteer-core";
const TOKEN = "YOUR_API_TOKEN_HERE";
const browser = await puppeteer.connect({
browserWSEndpoint: `wss://production-sfo.browserless.io/stealth?token=${TOKEN}&proxy=residential&proxyCountry=us&solveCaptchas=true&timeout=300000`,
});
const page = await browser.newPage();
const cdp = await page.createCDPSession();
// Attach BEFORE navigation — the listener survives the whole session.
const captchaSolved = new Promise((resolve) => {
cdp.on("Browserless.captchaAutoSolved", resolve);
});
// No CAPTCHA on the homepage.
await page.goto("https://2captcha.com/", { waitUntil: "networkidle0" });
// Clicking through navigates to the reCAPTCHA v2 demo — a CAPTCHA appears here.
await page.click(
"#order-captchas > table > tbody > tr:nth-child(2) span > a:nth-child(2)"
);
// Wait for autosolve to finish before submitting.
const { solved, token, time } = await captchaSolved;
console.log({ solved, token, time });
await page.click("._actionsItem_151cx_41");
await browser.close();
- Javascript
- Python
- Java
- C#
import playwright from "playwright-core";
const TOKEN = "YOUR_API_TOKEN_HERE";
const browser = await playwright.chromium.connectOverCDP(
`wss://production-sfo.browserless.io/stealth?token=${TOKEN}&proxy=residential&proxyCountry=us&solveCaptchas=true&timeout=300000`
);
// Reuse the existing context and page so Browserless CDP events are visible.
const context = browser.contexts()[0];
const page = context.pages()[0];
const cdp = await page.context().newCDPSession(page);
// Attach BEFORE navigation — the listener survives the whole session.
const captchaSolved = new Promise((resolve) => {
cdp.on("Browserless.captchaAutoSolved", resolve);
});
await page.goto("https://2captcha.com/", { waitUntil: "networkidle" });
await page.click(
"#order-captchas > table > tbody > tr:nth-child(2) span > a:nth-child(2)"
);
const result = await captchaSolved;
console.log(result);
await page.click("._actionsItem_151cx_41");
await browser.close();
import asyncio
from playwright.async_api import async_playwright
TOKEN = "YOUR_API_TOKEN_HERE"
async def main():
async with async_playwright() as p:
browser = await p.chromium.connect_over_cdp(
f"wss://production-sfo.browserless.io/stealth?token={TOKEN}&proxy=residential&proxyCountry=us&solveCaptchas=true&timeout=300000"
)
# Reuse the existing context and page so Browserless CDP events are visible.
context = browser.contexts[0]
page = context.pages[0]
cdp = await page.context.new_cdp_session(page)
# Attach BEFORE navigation — the listener survives the whole session.
captcha_solved = asyncio.get_event_loop().create_future()
cdp.on(
"Browserless.captchaAutoSolved",
lambda event: captcha_solved.set_result(event) if not captcha_solved.done() else None,
)
await page.goto("https://2captcha.com/", wait_until="networkidle")
await page.click(
"#order-captchas > table > tbody > tr:nth-child(2) span > a:nth-child(2)"
)
result = await captcha_solved
print(result)
await page.click("._actionsItem_151cx_41")
await browser.close()
asyncio.run(main())
import com.microsoft.playwright.*;
import com.microsoft.playwright.options.*;
import java.util.concurrent.CompletableFuture;
public class AutoCaptchaSolving {
public static void main(String[] args) throws Exception {
String TOKEN = "YOUR_API_TOKEN_HERE";
String endpoint = "wss://production-sfo.browserless.io/stealth?token=" + TOKEN
+ "&proxy=residential&proxyCountry=us&solveCaptchas=true&timeout=300000";
try (Playwright playwright = Playwright.create()) {
Browser browser = playwright.chromium().connectOverCDP(endpoint);
// Reuse the existing context and page so Browserless CDP events are visible.
BrowserContext context = browser.contexts().get(0);
Page page = context.pages().get(0);
CDPSession cdp = page.context().newCDPSession(page);
// Attach BEFORE navigation — the listener survives the whole session.
CompletableFuture<Object> captchaSolved = new CompletableFuture<>();
cdp.on("Browserless.captchaAutoSolved", event -> captchaSolved.complete(event));
page.navigate("https://2captcha.com/", new Page.NavigateOptions()
.setWaitUntil(LoadState.NETWORKIDLE));
page.click("#order-captchas > table > tbody > tr:nth-child(2) span > a:nth-child(2)");
System.out.println(captchaSolved.get());
page.click("._actionsItem_151cx_41");
browser.close();
}
}
}
using System;
using System.Threading.Tasks;
using Microsoft.Playwright;
class Program
{
static async Task Main(string[] args)
{
var TOKEN = "YOUR_API_TOKEN_HERE";
var endpoint = $"wss://production-sfo.browserless.io/stealth?token={TOKEN}&proxy=residential&proxyCountry=us&solveCaptchas=true&timeout=300000";
var playwright = await Playwright.CreateAsync();
var browser = await playwright.Chromium.ConnectOverCDPAsync(endpoint);
// Use the first context and page so Browserless CDP events are visible.
var context = browser.Contexts[0];
var page = context.Pages[0];
var cdp = await page.Context.NewCDPSessionAsync(page);
// Attach BEFORE navigation — the listener survives the whole session.
var captchaSolved = new TaskCompletionSource<object>();
cdp.On("Browserless.captchaAutoSolved", e => captchaSolved.TrySetResult(e));
await page.GotoAsync("https://2captcha.com/", new PageGotoOptions
{
WaitUntil = WaitUntilState.NetworkIdle
});
await page.ClickAsync("#order-captchas > table > tbody > tr:nth-child(2) span > a:nth-child(2)");
Console.WriteLine(await captchaSolved.Task);
await page.ClickAsync("._actionsItem_151cx_41");
await browser.CloseAsync();
}
}
Across multiple navigations
Because solveCaptchas=true runs for the lifetime of the connection, a single cdp.on("Browserless.captchaAutoSolved", ...) listener handles every CAPTCHA encountered on every subsequent page in the session. Use cdp.on (not cdp.once) when you expect more than one CAPTCHA — there's no need to re-attach after navigations, popups, or reloads. Re-create the awaitable promise each time you need to gate the next action on a fresh solve.
If you await the autosolve event on a page that turns out to have no CAPTCHA, the promise will never resolve. Wrap the wait in a timeout (for example, Promise.race against a setTimeout) so your script can continue when nothing fires.
CAPTCHA Detection
The Browserless.captchaFound CDP event fires when Browserless detects a CAPTCHA on the page. Set up a listener before navigating so you don't miss the event — captchaFound can fire during page.goto() (often before it resolves), so attaching afterwards will sometimes drop the event.
The event payload includes a status field that distinguishes the two modes:
- With
solveCaptchas=trueon the connection URL,captchaFoundfires with{ status: "solving" }— Browserless is already handling it and acaptchaAutoSolvedevent will follow. - In manual mode (without
solveCaptchas=true), it fires with{ status: "found" }— your code is expected to callBrowserless.solveCaptchato trigger solving.
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:
- Puppeteer
- Playwright
const cdp = await page.createCDPSession();
await new Promise((resolve) =>
cdp.on("Browserless.captchaFound", () => {
console.log("Found a captcha!");
return resolve();
})
);
- Javascript
- Python
- Java
- C#
const cdp = await page.context().newCDPSession(page);
await new Promise((resolve) =>
cdp.on("Browserless.captchaFound", () => {
console.log("Found a captcha!");
return resolve();
})
);
cdp = await page.context.new_cdp_session(page)
async def handle_captcha_found(event):
print("Found a captcha!")
return
cdp.on("Browserless.captchaFound", handle_captcha_found)
# Wait for the event to resolve
await asyncio.Future()
CDPSession cdp = page.context().newCDPSession(page);
cdp.addListener("Browserless.captchaFound", event -> {
System.out.println("Found a captcha!");
// You can add additional handling logic here
});
var cdp = await page.Context.NewCDPSessionAsync(page);
cdp.On("Browserless.captchaFound", e =>
{
Console.WriteLine("Found a captcha!");
// Additional logic can be added here
});
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.
Playwright uses its own browser protocols by default. To use Browserless CDP events, connect over CDP and reuse the existing context and page instead of creating new ones. See the full example below.
Here are complete scripts demonstrating CAPTCHA detection and solving in context:
- Puppeteer
- Playwright
import puppeteer from "puppeteer-core";
const waitForCaptcha = (cdpSession) => {
return new Promise((resolve) =>
cdpSession.on("Browserless.captchaFound", resolve)
);
};
const browserWSEndpoint =
"wss://production-sfo.browserless.io/stealth?token=YOUR_API_TOKEN_HERE&timeout=300000";
try {
const browser = await puppeteer.connect({ browserWSEndpoint });
const page = await browser.newPage();
const cdp = await page.createCDPSession();
// Attach BEFORE navigation — captchaFound can fire during page.goto.
const captchaFound = waitForCaptcha(cdp);
await page.goto("https://www.google.com/recaptcha/api2/demo", {
waitUntil: "networkidle0",
});
await captchaFound;
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);
}
- Javascript
- Python
- Java
- C#
import playwright from "playwright-core";
const waitForCaptcha = (cdpSession) => {
return new Promise((resolve) =>
cdpSession.on("Browserless.captchaFound", resolve)
);
};
const pwEndpoint = `wss://production-sfo.browserless.io/stealth?token=YOUR_API_TOKEN_HERE`;
try {
const browser = await playwright.chromium.connectOverCDP(pwEndpoint);
// 👇 Reuse the existing context and page
const context = browser.contexts()[0];
const page = context.pages()[0];
const cdp = await page.context().newCDPSession(page);
// Attach BEFORE navigation — captchaFound can fire during page.goto.
const captchaFound = waitForCaptcha(cdp);
await page.goto("https://www.google.com/recaptcha/api2/demo", {
waitUntil: "networkidle0",
});
await captchaFound;
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);
}
import asyncio
from playwright.async_api import async_playwright
async def main():
pw_endpoint = "wss://production-sfo.browserless.io/stealth?token=YOUR_API_TOKEN_HERE"
async with async_playwright() as p:
try:
# Connect to the browser
browser = await p.chromium.connect_over_cdp(pw_endpoint)
# Use the first context and page
context = browser.contexts[0]
page = context.pages[0]
cdp = await page.context.new_cdp_session(page)
# Attach BEFORE navigation — captchaFound can fire during page.goto.
captcha_found = asyncio.get_event_loop().create_future()
cdp.on(
"Browserless.captchaFound",
lambda event: captcha_found.set_result(event) if not captcha_found.done() else None,
)
# Navigate to the captcha demo page
await page.goto("https://www.google.com/recaptcha/api2/demo", wait_until="networkidle")
await captcha_found
print("Captcha found!")
# Solve the captcha
result = await cdp.send("Browserless.solveCaptcha")
solved, error = result.get("solved"), result.get("error")
print({"solved": solved, "error": error})
# Continue after solving captcha
await page.click("#recaptcha-demo-submit")
await browser.close()
except Exception as e:
print("There was a big error :(", e)
asyncio.run(main())
import com.microsoft.playwright.*;
import com.microsoft.playwright.options.*;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
public class PlaywrightCaptchaExample {
public static void main(String[] args) {
String pwEndpoint = "wss://production-sfo.browserless.io/stealth?token=YOUR_API_TOKEN_HERE";
try (Playwright playwright = Playwright.create()) {
Browser browser = playwright.chromium().connectOverCDP(pwEndpoint);
// Reuse the existing context and page
BrowserContext context = browser.contexts().get(0);
Page page = context.pages().get(0);
CDPSession cdp = page.context().newCDPSession(page);
// Attach BEFORE navigation — captchaFound can fire during page.navigate.
CompletableFuture<Void> captchaFound = new CompletableFuture<>();
cdp.on("Browserless.captchaFound", event -> {
System.out.println("Captcha found!");
captchaFound.complete(null);
});
// Navigate to the captcha demo page
page.navigate("https://www.google.com/recaptcha/api2/demo", new Page.NavigateOptions()
.setWaitUntil(LoadState.NETWORKIDLE));
captchaFound.get(); // Wait for the event
// Solve the captcha
Map<String, Object> result = cdp.send("Browserless.solveCaptcha");
System.out.println("Result: " + result);
// Continue after solving captcha
page.click("#recaptcha-demo-submit");
browser.close();
} catch (ExecutionException | InterruptedException e) {
System.err.println("There was a big error :(" + e.getMessage());
e.printStackTrace();
}
}
}
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.Playwright;
class Program
{
static async Task Main(string[] args)
{
var pwEndpoint = "wss://production-sfo.browserless.io/stealth?token=YOUR_API_TOKEN_HERE";
try
{
var playwright = await Playwright.CreateAsync();
var browser = await playwright.Chromium.ConnectOverCDPAsync(pwEndpoint);
// Use the first context and page
var context = browser.Contexts[0];
var page = context.Pages[0];
var cdp = await page.Context.NewCDPSessionAsync(page);
// Attach BEFORE navigation — captchaFound can fire during page.GotoAsync.
var captchaFound = new TaskCompletionSource<bool>();
cdp.On("Browserless.captchaFound", _ =>
{
Console.WriteLine("Captcha found!");
captchaFound.TrySetResult(true);
});
// Navigate to the captcha demo page
await page.GotoAsync("https://www.google.com/recaptcha/api2/demo", new PageGotoOptions
{
WaitUntil = WaitUntilState.NetworkIdle
});
await captchaFound.Task;
// Solve the captcha
var result = await cdp.SendAsync<Dictionary<string, object>>("Browserless.solveCaptcha");
Console.WriteLine($"Solved: {result["solved"]}, Error: {result["error"]}");
// Continue after solving captcha
await page.ClickAsync("#recaptcha-demo-submit");
await browser.CloseAsync();
}
catch (Exception e)
{
Console.WriteLine("There was a big error :(");
Console.WriteLine(e.Message);
}
}
}
CAPTCHA Solving
Use this approach when you need programmatic control over when CAPTCHAs are solved. Set up a Browserless.captchaFound event listener, then call Browserless.solveCaptcha to trigger solving on demand.
Programmatic Solving
Once a CAPTCHA is detected, use the Browserless.solveCaptcha command to solve it:
- Puppeteer
- Playwright
const cdp = await page.createCDPSession();
const { solved, error } = await cdp.send("Browserless.solveCaptcha");
console.log({
solved,
error,
});
- Javascript
- Python
- Java
- C#
const cdp = await page.context().newCDPSession(page);
const { solved, error } = await cdp.send("Browserless.solveCaptcha");
console.log({
solved,
error,
});
cdp = await page.context.new_cdp_session(page)
result = await cdp.send("Browserless.solveCaptcha")
solved = result.get("solved")
error = result.get("error")
print({
"solved": solved,
"error": error,
})
CDPSession cdp = page.context().newCDPSession(page);
Map<String, Object> result = cdp.send("Browserless.solveCaptcha");
Boolean solved = (Boolean) result.get("solved");
String error = (String) result.get("error");
System.out.println(Map.of(
"solved", solved,
"error", error
));
var cdp = await page.Context.NewCDPSessionAsync(page);
var result = await cdp.SendAsync<Dictionary<string, object>>("Browserless.solveCaptcha");
var solved = result.ContainsKey("solved") ? result["solved"] : null;
var error = result.ContainsKey("error") ? result["error"] : null;
Console.WriteLine(new {
solved,
error
});
Playwright uses its own browser protocols by default. Connect over CDP and reuse the existing context and page instead of creating new ones.
Here are complete scripts demonstrating CAPTCHA detection and solving:
- Puppeteer
- Playwright
import puppeteer from "puppeteer-core";
const waitForCaptcha = (cdpSession) => {
return new Promise((resolve) =>
cdpSession.on("Browserless.captchaFound", resolve)
);
};
const browserWSEndpoint =
"wss://production-sfo.browserless.io/stealth?token=YOUR_API_TOKEN_HERE&timeout=300000";
try {
const browser = await puppeteer.connect({ browserWSEndpoint });
const page = await browser.newPage();
const cdp = await page.createCDPSession();
// Attach BEFORE navigation — captchaFound can fire during page.goto.
const captchaFound = waitForCaptcha(cdp);
await page.goto("https://www.google.com/recaptcha/api2/demo", {
waitUntil: "networkidle0",
});
await captchaFound;
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);
}
- Javascript
- Python
- Java
- C#
import playwright from "playwright-core";
const waitForCaptcha = (cdpSession) => {
return new Promise((resolve) =>
cdpSession.on("Browserless.captchaFound", resolve)
);
};
const pwEndpoint = `wss://production-sfo.browserless.io/stealth?token=YOUR_API_TOKEN_HERE`;
try {
const browser = await playwright.chromium.connectOverCDP(pwEndpoint);
// 👇 Reuse the existing context and page
const context = browser.contexts()[0];
const page = context.pages()[0];
const cdp = await page.context().newCDPSession(page);
// Attach BEFORE navigation — captchaFound can fire during page.goto.
const captchaFound = waitForCaptcha(cdp);
await page.goto("https://www.google.com/recaptcha/api2/demo", {
waitUntil: "networkidle0",
});
await captchaFound;
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);
}
import asyncio
from playwright.async_api import async_playwright
async def main():
pw_endpoint = "wss://production-sfo.browserless.io/stealth?token=YOUR_API_TOKEN_HERE"
async with async_playwright() as p:
try:
# Connect to the browser
browser = await p.chromium.connect_over_cdp(pw_endpoint)
# Use the first context and page
context = browser.contexts[0]
page = context.pages[0]
cdp = await page.context.new_cdp_session(page)
# Attach BEFORE navigation — captchaFound can fire during page.goto.
captcha_found = asyncio.get_event_loop().create_future()
cdp.on(
"Browserless.captchaFound",
lambda event: captcha_found.set_result(event) if not captcha_found.done() else None,
)
# Navigate to the captcha demo page
await page.goto("https://www.google.com/recaptcha/api2/demo", wait_until="networkidle")
await captcha_found
print("Captcha found!")
# Solve the captcha
result = await cdp.send("Browserless.solveCaptcha")
solved, error = result.get("solved"), result.get("error")
print({"solved": solved, "error": error})
# Continue after solving captcha
await page.click("#recaptcha-demo-submit")
await browser.close()
except Exception as e:
print("There was a big error :(", e)
asyncio.run(main())
import com.microsoft.playwright.*;
import com.microsoft.playwright.options.*;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
public class PlaywrightCaptchaExample {
public static void main(String[] args) {
String pwEndpoint = "wss://production-sfo.browserless.io/stealth?token=YOUR_API_TOKEN_HERE";
try (Playwright playwright = Playwright.create()) {
Browser browser = playwright.chromium().connectOverCDP(pwEndpoint);
// Reuse the existing context and page
BrowserContext context = browser.contexts().get(0);
Page page = context.pages().get(0);
CDPSession cdp = page.context().newCDPSession(page);
// Attach BEFORE navigation — captchaFound can fire during page.navigate.
CompletableFuture<Void> captchaFound = new CompletableFuture<>();
cdp.on("Browserless.captchaFound", event -> {
System.out.println("Captcha found!");
captchaFound.complete(null);
});
// Navigate to the captcha demo page
page.navigate("https://www.google.com/recaptcha/api2/demo", new Page.NavigateOptions()
.setWaitUntil(LoadState.NETWORKIDLE));
captchaFound.get(); // Wait for the event
// Solve the captcha
Map<String, Object> result = cdp.send("Browserless.solveCaptcha");
System.out.println("Result: " + result);
// Continue after solving captcha
page.click("#recaptcha-demo-submit");
browser.close();
} catch (ExecutionException | InterruptedException e) {
System.err.println("There was a big error :(" + e.getMessage());
e.printStackTrace();
}
}
}
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.Playwright;
class Program
{
static async Task Main(string[] args)
{
var pwEndpoint = "wss://production-sfo.browserless.io/stealth?token=YOUR_API_TOKEN_HERE";
try
{
var playwright = await Playwright.CreateAsync();
var browser = await playwright.Chromium.ConnectOverCDPAsync(pwEndpoint);
// Use the first context and page
var context = browser.Contexts[0];
var page = context.Pages[0];
var cdp = await page.Context.NewCDPSessionAsync(page);
// Attach BEFORE navigation — captchaFound can fire during page.GotoAsync.
var captchaFound = new TaskCompletionSource<bool>();
cdp.On("Browserless.captchaFound", _ =>
{
Console.WriteLine("Captcha found!");
captchaFound.TrySetResult(true);
});
// Navigate to the captcha demo page
await page.GotoAsync("https://www.google.com/recaptcha/api2/demo", new PageGotoOptions
{
WaitUntil = WaitUntilState.NetworkIdle
});
await captchaFound.Task;
// Solve the captcha
var result = await cdp.SendAsync<Dictionary<string, object>>("Browserless.solveCaptcha");
Console.WriteLine($"Solved: {result["solved"]}, Error: {result["error"]}");
// Continue after solving captcha
await page.ClickAsync("#recaptcha-demo-submit");
await browser.CloseAsync();
}
catch (Exception e)
{
Console.WriteLine("There was a big error :(");
Console.WriteLine(e.Message);
}
}
}
Response Fields
The solveCaptcha response includes information about the solving attempt:
- found: Whether a CAPTCHA was detected on the page
- solved: Whether the CAPTCHA was successfully solved
- time: Time taken to solve the CAPTCHA, in milliseconds
- token: The solved CAPTCHA token, if available
- error: Any errors during execution
Integration with Live Sessions
CAPTCHA solving integrates with Browserless live URL sessions for hybrid automation workflows. This lets a human step in when automated solving fails, providing a fallback for complex CAPTCHAs.
Performance Considerations
- CAPTCHA solving can take several seconds to minutes. Adjust timeouts accordingly.
- Each CAPTCHA solve attempt costs 10 units (see your account dashboard for unit details)
- Use stealth features and residential proxies to reduce CAPTCHA frequency