Puppeteer Stealth Tips to Avoid Captchas and IP Bans

Websites have gotten sharp. They spot bots a mile away. Cloudflare, anti-spam guards, and clever scripts easily flag a poorly configured Puppeteer. What happens next? Instant bans, endless captchas, and zero data collection.
But there’s a way through. Puppeteer Stealth mode turns your bot into a digital chameleon — it mimics real users so well, it slips past defenses like a ghost.
This guide shows you how to install Puppeteer Stealth, use plugins to bypass anti-bot defenses, and test your setup to avoid blocks. By the end, your scraper will run smoothly and stay under the radar.

Step 1: Download Puppeteer and Activate Stealth Mode

Setting up Stealth mode is straightforward. You need Puppeteer itself, the puppeteer-extra framework for plugins, and the puppeteer-extra-plugin-stealth to mask automation signs.

Run this in your terminal:

npm install puppeteer puppeteer-extra puppeteer-extra-plugin-stealth

Quick breakdown:

  • puppeteer: The core Chrome automation library.
  • puppeteer-extra: Allows adding plugins easily.
  • puppeteer-extra-plugin-stealth: Makes your bot look human by hiding telltale automation markers.

By default, Puppeteer reveals itself — headers like HeadlessChrome give it away. Stealth mode erases those fingerprints.

Step 2: Add the Stealth Plugin

Create index.js and add this:

const puppeteer = require('puppeteer-extra');
const StealthPlugin = require('puppeteer-extra-plugin-stealth');

puppeteer.use(StealthPlugin());

(async () => {
    const browser = await puppeteer.launch({ headless: true });
    const page = await browser.newPage();

    await page.goto('https://bot.sannysoft.com/');
    await page.screenshot({ path: 'result.png' });

    console.log('Test complete. Screenshot saved.');
    await browser.close();
})();

Run this. The screenshot shows how stealthy your bot really is.

Step 3: Enhance Stealth with Browser Startup Flags

Make your bot even more convincing by tweaking launch options:

const browser = await puppeteer.launch({
    headless: true,
    args: [
        '--no-sandbox',
        '--disable-setuid-sandbox',
        '--disable-dev-shm-usage',
        '--disable-accelerated-2d-canvas',
        '--disable-gpu'
    ]
});

Why? These flags reduce resource use and dodge some server checks.

  • --no-sandbox: avoids certain Linux security restrictions.
  • --disable-gpu: prevents rendering artifacts that hint automation.

Step 4: Test on Real Sites

Verify your setup using these key sites:

  • bot.sannysoft.com — Tests your browser’s human-like behavior.
  • whatismybrowser.com — Shows exactly what your bot “looks” like to servers.
  • httpbin.org/headers — Reveals HTTP headers your bot sends.

If these sites think you’re a real user — you’re winning.

Step 5: Hide Your IP Address with Proxies

One IP address? That’s a red flag. Too many requests from a single IP and you’re banned.

Enter proxies.

Pick the right proxy:

  • Server proxies: speed + stability — great for heavy scraping.
  • Mobile proxies: mimic real users — harder to detect.

Add a proxy to Puppeteer like this:

const browser = await puppeteer.launch({
    headless: true,
    args: ['--proxy-server=http://username:password@proxy_address:port']
});

Swap out username, password, proxy_address, and port accordingly.

Step 6: Rotate Proxies to Beat IP Limits

Static proxies? Not enough. Rotate proxies with each request to spread risk.

Here’s a sample proxy rotation setup:

const proxyList = [
    'http://user1:pass1@proxy1:port',
    'http://user2:pass2@proxy2:port',
    'http://user3:pass3@proxy3:port'
];

const getRandomProxy = () => proxyList[Math.floor(Math.random() * proxyList.length)];

(async () => {
    for (let i = 0; i < 5; i++) {
        const proxy = getRandomProxy();

        const browser = await puppeteer.launch({
            headless: true,
            args: [`--proxy-server=${proxy}`]
        });

        const page = await browser.newPage();
        await page.goto('https://httpbin.org/ip');

        console.log(`Request sent via proxy: ${proxy}`);

        await browser.close();
    }
})();

This randomly picks a proxy every time, keeping you off the radar.

Step 7: Validate Proxy Stability

Before full deployment, test proxies thoroughly:

  • Load multiple pages through each proxy to ensure reliability.
  • Measure connection speed — slow proxies waste time.
  • Match proxy location with target site requirements (e.g. US content needs US IPs).

Step 8: Final Testing and Debugging

Bots fail silently. You may see errors like access denied or weird browser crashes.

Run tests against the same bot detection sites:

  • bot.sannysoft.com for behavior analysis
  • whatismybrowser.com for fingerprint checks
  • httpbin.org/headers for header inspection

Here’s a quick test script:

const puppeteer = require('puppeteer-extra');
const StealthPlugin = require('puppeteer-extra-plugin-stealth');

puppeteer.use(StealthPlugin());

(async () => {
    const browser = await puppeteer.launch({ headless: true });
    const page = await browser.newPage();

    await page.goto('https://bot.sannysoft.com/');
    await page.screenshot({ path: 'stealth-test.png' });

    console.log('Stealth test complete. Screenshot saved.');
    await browser.close();
})();

Once your bot passes these, you’ve built a stealthy, resilient scraping tool ready for the wild.

Wrapping Up

Puppeteer Stealth, paired with smart proxy use and proper testing, transforms your scraper from a blatant bot into a stealthy data hunter. No more captchas. No more blocks. Just smooth, uninterrupted scraping.