Skip to main content

Captcha Solver

When navigating a page with Browser API, our integrated CAPTCHA solver automatically solves all CAPTCHAs by default. You can monitor this auto-solving process in your code with the following custom CDP functions.
If you would like to disable CAPTCHA solver entirely through the Control Panel see our feature for Disable Captcha Solver
Once a CAPTCHA is solved, if there is a form to submit, it will be submitted by default.

CAPTCHA Solver - Automatic Solve

Use this command to return the status after the captcha was solved, failed, or not detected. Use this command to return the status after the captcha was solved, failed, or not detected.
Captcha.solve({
    detectTimeout?: number // Detect timeout in millisecond for solver to detect captcha  
    options?: CaptchaOptions[] // Configuration options for captcha solving  
}) : SolveResult
Examples
const page = await browser.newPage();
const client = await page.target().createCDPSession();
await page.goto('[https://site-with-captcha.com](https://site-with-captcha.com/)');  

// Note 1: If no captcha was found it will return not_detected status after detectTimeout   
// Note 2: Once a CAPTCHA is solved, if there is a form to submit, it will be submitted by default   

const client = await page.target().createCDPSession();  
const {status} = await client.send('Captcha.solve', {detectTimeout: 30*1000});   
console.log(`Captcha solve status: ${status}`)
If CAPTCHA-solving fails, please attempt a retry. If the issue persists, submit a support reques detailing the specific problem you encountered.
Use the commands below to pinpoint a more specific stage in the CAPTCHA solving flow:
Captcha.detectedBrowser API has encountered a CAPTCHA and has begun to solve it
Captcha.solveFinishedBrowser API successfully solved the CAPTCHA
Captcha.solveFailedBrowser API failed in solving the CAPTCHA
Captcha.waitForSolveBrowser API waits for CAPTCHA solver to finish
Examples
  • Asynchronous
  • Synchronous
The following code sets up a CDP session, listens for CAPTCHA events, and handles timeouts:
// Node.js - Puppeteer - waiting for CAPTCHA solving events  
const client = await page.target().createCDPSession();   
await new Promise((resolve, reject)=>{   
  client.on('Captcha.solveFinished', resolve);   
  client.on('Captcha.solveFailed', ()=>reject(new Error('Captcha failed')));   
  setTimeout(reject, 5 * 60 * 1000, new Error('Captcha solve timeout'));  
});

CAPTCHA Solver - Manual Control

If you would like to either manually configure or fully disable our default CAPTCHA solver and instead call the solver manually or solve on your own, see the following CDP commands and functionality.
This command is used to control the auto-solving of a CAPTCHA. You can disable auto-solve or configure algorithms for different CAPTCHA types and manually trigger this:
Captcha.setAutoSolve({  
  autoSolve: boolean // Whether to automatically solve captcha after navigate  
  options?: CaptchaOptions[] // Configuration options for captcha auto-solving  
}) : void
Examples of CDP commands to disable auto-solver completely within the session:
// Node.js Puppeteer - Disable Captcha auto-solver completely  
const page = await browser.newPage();  
const client = await page.target().createCDPSession();  
await client.send('Captcha.setAutoSolve', { autoSolve: false })
// Node.js Puppeteer - Disable Captcha auto-solver for ReCaptcha only  
const page = await browser.newPage();  
const client = await page.target().createCDPSession();  
await client.send('Captcha.setAutoSolve', {  
    autoSolve: true,  
    options: [{  
        type: 'usercaptcha',  
        disabled: true,  
    }],  
});
// Node.js Puppeteer - manually solving CAPTCHA after navigation  
const page = await browser.newPage();  
const client = await page.target().createCDPSession();  
await client.send('Captcha.setAutoSolve', { autoSolve: false });  
await page.goto('https://site-with-captcha.com', { timeout: 2*60*1000 });  
const {status} = await client.send('Captcha.solve', { detectTimeout: 30*1000 });  
console.log('Captcha solve status:', status);
For the following three CAPTCHA types we support the following additional options to control and configure our auto-solving algorithm.
  • CF Challenge
  • HCaptcha
  • usercaptcha (reCAPTCHA)
CF Challenge
timeout: 40000  
selector: '#challenge-body-text, .challenge-form'  
check_timeout: 300  
error_selector: '#challenge-error-title'  
success_selector: '#challenge-success[style*=inline]'  
check_success_timeout: 300  
btn_selector: '#challenge-stage input[type=button]'  
cloudflare_checkbox_frame_selector: '#turnstile-wrapper iframe'  
checkbox_area_selector: '.ctp-checkbox-label .mark'  
wait_timeout_after_solve: 500  
wait_networkidle: {timeout: 500}

Emulation Functions

Use this command to get a list of all possible devices that can be emulated. This method returns an array of device options that can be used with the setDevice command.
Example
Emulation.getSupportedDevices().then(devices => { console.log(devices);});
Once you’ve received the list above of supported devices, you can emulate a specific device using the Emulation.setDevice command. This command changes the screen width, height, userAgent, and devicePixelRatio to match the specified device.
Emulation.setDevice({device: '[device_name]'});

Landscape mode

If you wish to change the orientation to landscape (for devices that support it), add the string landscape after the device_name.
Example
Emulation.setDevice({device: 'iPhone X landscape'});

Ad Blocker

Enabling our AdBlock feature can help reduce bandwidth usage and improve performance on ad-heavy websites.

CDP Commands

  • Unblocker.enableAdBlock – Enables ad blocker (default: off)
  • Unblocker.disableAdBlock – Disables ad blocker
We recommend enabling ad blocking before navigating to the target page.
Example
// Enable ad blocking before navigating
const client = await page.createCDPSession();

try {
    await client.send('Unblocker.enableAdBlock', {
        list: [null],
    });
} catch (e) {
    console.error(e.stack || e);
}

await page.goto('https://www.w3schools.com/html/html_forms.asp');
See the full ad blocker example script.

Session Persistence

Use this command to reuse the same proxy peer across multiple browsing sessions. This is useful for scenarios where maintaining a consistent session is required, such as preserving browser states or IP-based continuity.

CDP Commands

  • Proxy.useSession – Associates a session with a specific session ID.
  • sessionId – A unique string that identifies your session.
Use the CDP command before navigation to the target page.
Example
const client = await page.createCDPSession();
await client.send('Proxy.useSession', { sessionId });
await page.goto('https://geo.brdtest.com/mygeo.json');

File Download

You can automate file downloads in your Browser API flows using the custom Download CDP domain. This is useful for workflows that require downloading files (e.g., CSV, PDF) directly during browser automation.

CDP Commands

  • Download.enable – Enables file downloads for specified content types.
  • Download.downloadRequest – Fires when request results in download.
  • Download.getLastCompleted – Retrieves information about the last completed download.
  • Download.getDownloadedBody – Gets the actual downloaded file content.
Example
const client = await page.createCDPSession();

// Enable downloads for binary files like CSV
await client.send('Download.enable', { allowedContentTypes: ['application/octet-stream'] });

// initiate download file
await Promise.all([
  new Promise(resolve => client.once('Download.downloadRequest', resolve)),
  page.click(selector),
]);

// After download completes:
const { id } = await client.send('Download.getLastCompleted');
const { body, base64Encoded } = await client.send('Download.getDownloadedBody', { id });
const fs = require('fs');
fs.writeFileSync('./downloaded_file.csv', base64Encoded ? Buffer.from(body, 'base64') : body);

Faster Text Input

For scenarios that need rapid or bulk text input, use the custom Input.type CDP command. This approach is much faster than standard CDP text input methods, making it well suited for automation tasks requiring high-speed typing or handling large volumes of text.

CDP Commands

  • Input.type - Sends keystrokes or simulates typing the specified text into the currently focused element.
Example
const client = await page.createCDPSession();

// Focus the input element
await page.focus('input');

// Type a message
await client.send('Input.type', {
  text: 'what is the best place to try pizza and pasta?'
});

Custom Client SSL/TLS Certificates

Use this command to install custom client SSL/TLS certificates where required for specific domain authentication. These certificates are applied for the duration of a single Browser API session and are automatically removed once the session ends.
Browser.addCertificate(params: {
  cert: string // base64 encoded certificate file
  pass: string // password for the certificate
}) : void
  • Replace placeholder values SBR_ZONE_FULL_USERNAME:SBR_ZONE_PASSWORD with your valid Browser API credentials.
  • Replace client.pfx with the actual path to your certificate file. This file should be a valid SSL/TLS client certificate in .pfx format.
  • Replace secret with the actual password for the certificate.
    const puppeteer = require('puppeteer-core');
    const fs = require('fs/promises');
    const {
      AUTH = 'SBR_ZONE_FULL_USERNAME:SBR_ZONE_PASSWORD',
      TARGET_URL = 'https://example.com',
      CERT_FILE = 'client.pfx',
      CERT_PASS = 'secret',
    } = process.env;
    
    async function scrape(url = TARGET_URL, file = CERT_FILE, pass = CERT_PASS) {
      if (AUTH == 'SBR_ZONE_FULL_USERNAME:SBR_ZONE_PASSWORD') {
        throw new Error(`Provide Browser API credentials in AUTH`
            + ` environment variable or update the script.`);
      }
      console.log(`Connecting to Browser...`);
      const browserWSEndpoint = `wss://${AUTH}@brd.superproxy.io:9222`;
      const browser = await puppeteer.connect({ browserWSEndpoint });
      try {
        console.log(`Connected! Installing ${file} certificate...`);
        const page = await browser.newPage();
        const client = await page.createCDPSession();
        const cert = (await fs.readFile(CERT_FILE)).toString('base64');
        await client.send('Browser.addCertificate', { cert, pass });
        console.log(`Installed! Navigating to ${url}...`);
        await page.goto(url, { timeout: 2 * 60 * 1000 });
        console.log(`Navigated! Scraping page content...`);
        const data = await page.content();
        console.log(`Scraped! Data: ${data}`);
      } finally {
        await browser.close();
      }
    }
    
    scrape();