How to Use Puppeteer Stealth to Avoid Detection

Web scraping has become a critical tool for developers working on data aggregation, competitive analysis, and automation workflows. However, many websites deploy anti-bot systems that can easily detect and block headless browsers like Puppeteer. This is where Puppeteer Stealth comes in. In this guide, you will learn how to integrate the stealth plugin with Puppeteer, understand why detection occurs, and implement real-world solutions to avoid detection reliably. We will explore use cases involving proxies, headers, fingerprint masking, and how to simulate authentic browser behavior while still controlling everything programmatically.
Why Puppeteer Gets Detected
Before jumping into code, it is essential to understand how websites detect automation tools like Puppeteer. Common methods include:
- Checking for the presence of WebDriver or headless browser signatures
- Detecting missing or default browser attributes like plugins or languages
- Analyzing rapid user actions that do not resemble human behavior
- Looking at default window size and device memory inconsistencies
To avoid detection, the Puppeteer Stealth plugin modifies several of these behaviors to make the automated browser session appear more human-like.
Installing Puppeteer and Puppeteer Extra Stealth
First, you need to install Puppeteer and the required plugins:
npm install puppeteer npm install puppeteer-extra npm install puppeteer-extra-plugin-stealth
These three packages provide the core Puppeteer functionality along with the extra plugins that improve stealthiness.
Basic Setup with Puppeteer Stealth
Now integrate the stealth plugin into your Puppeteer workflow:
const puppeteer = require('puppeteer-extra') const StealthPlugin = require('puppeteer-extra-plugin-stealth') puppeteer.use(StealthPlugin()) async function runStealthExample() { const browser = await puppeteer.launch({ headless: true, args: ['--no-sandbox', '--disable-setuid-sandbox'] }) const page = await browser.newPage() await page.goto('https://www.whatismybrowser.com/') await page.screenshot({ path: 'browser_check.png' }) await browser.close() } runStealthExample()
This script launches Puppeteer with stealth mode enabled and navigates to a browser check site. The screenshot output will show that automation-related flags are masked or removed.
Using Custom User Agents and Viewports
Real users do not use the default Chromium user agent or window size. To appear human, configure these explicitly:
await page.setUserAgent('Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36') await page.setViewport({ width: 1280, height: 800, deviceScaleFactor: 1 })
This change removes common headless fingerprints and aligns the session more closely with real browser behavior.
Using Proxies with Puppeteer Stealth
Another way to avoid detection is by rotating IPs using residential proxies. Many scraping targets block requests from known datacenter IP ranges. To use a proxy:
const browser = await puppeteer.launch({ headless: true, args: [ '--proxy-server=http://your-proxy-ip:port', '--no-sandbox', '--disable-setuid-sandbox' ] })
If the proxy requires authentication, handle it like this:
await page.authenticate({ username: 'proxyuser', password: 'proxypass' })
Residential or rotating proxies are typically best for evading IP-based restrictions.
Masking Fingerprints with Stealth Plugins
The stealth plugin automatically patches several browser properties. Here are some of the most important ones:
- window.navigator.webdriver is set to false
- navigator.plugins and navigator.languages are spoofed
- WebGL and canvas fingerprints are randomized
- iframe behavior is normalized
This reduces the chance of being flagged by advanced browser fingerprinting scripts.
Simulating Realistic User Behavior
Even with stealth plugins and proxies, your bot may still be detected if it acts too fast or unnaturally. Here are techniques to improve realism:
- Wait for elements before clicking using
page.waitForSelector
- Add randomized delays between actions using
await page.waitForTimeout
- Use
page.mouse
andpage.keyboard
APIs to simulate input
Here is a simple example of typing into a form realistically:
await page.click('#username') await page.keyboard.type('testuser', { delay: 100 }) await page.click('#password') await page.keyboard.type('securepass123', { delay: 120 }) await page.click('#login-button')
Each keypress is spaced out to resemble human typing, reducing automation suspicion.
Real-World Scraping Workflow Example
Now let’s put it all together by scraping a website that uses bot protection, such as a job listing site.
const puppeteer = require('puppeteer-extra') const StealthPlugin = require('puppeteer-extra-plugin-stealth') puppeteer.use(StealthPlugin()) async function scrapeJobs() { const browser = await puppeteer.launch({ headless: true, args: ['--no-sandbox'] }) const page = await browser.newPage() await page.setUserAgent('Mozilla/5.0 (Windows NT 10.0; Win64; x64)...') await page.setViewport({ width: 1366, height: 768 }) await page.goto('https://example-jobsite.com/search?query=developer', { waitUntil: 'domcontentloaded' }) const jobs = await page.$$eval('.job-post', posts => { return posts.map(post => { return { title: post.querySelector('.title')?.innerText, company: post.querySelector('.company')?.innerText, location: post.querySelector('.location')?.innerText } }) }) console.log(jobs) await browser.close() } scrapeJobs()
This script demonstrates how Puppeteer Stealth can be used to reliably extract structured data while remaining undetected by bot filters.
When Puppeteer Stealth Is Not Enough
There are scenarios where Puppeteer Stealth alone is not sufficient. Some websites deploy behavior-based detection systems that analyze scrolling patterns, mouse movement, or session history. In such cases, consider combining Puppeteer with solutions like:
- Browser automation with real user session emulation
- Captcha solving services
- Dedicated fingerprint spoofing libraries
Additionally, monitor changes to the site’s anti-bot logic. Periodic adjustments to your scraping logic might be required to keep bypassing defenses effectively.
Key Takeaways and How to Use Puppeteer Stealth Effectively
Puppeteer Stealth offers a robust set of tools for masking automation signatures and enabling successful web scraping. By combining fingerprint spoofing, custom headers, realistic user actions, and proxy rotation, developers can significantly reduce the chances of being blocked or flagged. Still, staying undetected is an ongoing process. Regularly validate your scripts, monitor success rates, and test against different targets.
As a next step, consider building a modular scraping pipeline with Puppeteer Stealth, rotating proxies, and captcha solvers. For large-scale operations, integrate queue-based task runners and data storage pipelines like MongoDB or PostgreSQL. This will ensure your scraper remains performant, undetectable, and scalable.
Continue learning how to use Puppeteer Stealth more effectively by exploring advanced plugins, tracking evolving detection methods, and designing scrapers that mimic human behavior as closely as possible. Staying ahead in web automation requires not just tools, but strategic implementation and adaptability.