stealth-browser
Installation
SKILL.md
Stealth Browser π΅οΈ
Bypass Cloudflare Turnstile and other anti-bot detection systems using puppeteer-extra with stealth plugin. Access websites that block headless browsers.
When to Use
- Websites protected by Cloudflare Turnstile
- Sites that block automated/headless browsers
- Need screenshots or visual content
- Require JavaScript execution and interaction
- Anti-scraping detection systems
Known Working Sites
- β linux.do (Cloudflare Turnstile)
- β Bossη΄θ (ζ»ειͺθ―η )
- β ζεΎη½ (ιΏιδΊζ»ειͺθ―)
- β Most Cloudflare-protected websites
Installation
# Install dependencies
npm install puppeteer-extra puppeteer-extra-plugin-stealth
# The skill wrapper is ready to use
Quick Start
Command Line
# Quick visit and screenshot
node /root/.openclaw/workspace/skills/stealth-browser/wrapper.js \
https://linux.do \
linux-do-screenshot.png
In Code
const { quickVisit, StealthBrowser } = require('/root/.openclaw/workspace/skills/stealth-browser/wrapper.js');
// Method 1: Quick visit
const result = await quickVisit('https://linux.do', 'screenshot.png');
console.log(result);
// { success: true, title: 'LINUX DO - ...', screenshotPath: '...' }
// Method 2: Full control
const browser = new StealthBrowser();
await browser.launch();
await browser.goto('https://linux.do');
const title = await browser.getTitle();
await browser.screenshot('homepage.png');
await browser.close();
In Subagent
const { quickVisit } = require('/root/.openclaw/workspace/skills/stealth-browser/wrapper.js');
const result = await quickVisit('https://linux.do', 'linux-do.png');
if (result.success) {
// Send screenshot via message tool
message({
action: "send",
channel: "telegram",
media: result.screenshotPath,
message: "Linux.do homepage"
});
}
API Reference
quickVisit(url, filename)
Quick visit a website and take a screenshot.
Parameters:
url(string): Target URLfilename(string): Screenshot filename
Returns:
{
success: boolean,
title: string,
screenshotPath: string
}
StealthBrowser Class
Constructor
new StealthBrowser(options)
Options:
headless: 'new' | true | false (default: 'new')viewport: { width, height } (default: { width: 1920, height: 1080 })userAgent: string (default: Chrome 131)screenshotPath: string (default: '/root/.openclaw/media/browser/')
Methods
launch()- Start browsergoto(url, options?)- Navigate to URLscreenshot(filename)- Take screenshotgetTitle()- Get page titlegetContent()- Get HTML contentevaluate(fn, ...args)- Execute JavaScriptcheckSuccess(keywords)- Check if visit succeededclose()- Close browservisitAndScreenshot(url, filename)- Shortcut method
How It Works
Why OpenClaw Default Browser Fails
navigator.webdriver = true- Explicitly identifies as automated browser- Uses legacy headless mode with obvious fingerprints
- Missing real browser fingerprints
- No plugin list or language settings
How StealthPlugin Solves It
-
Hides automation indicators:
- Changes
navigator.webdrivertoundefined - Overrides
Function.prototype.toString - Fixes iframe detection
- Changes
-
Mimics real fingerprints:
- Adds real plugin list
- Simulates language settings
- Fixes
window.outerWidth/Height - Adds touch support
-
Uses new headless mode:
headless: 'new'uses real Chrome rendering engine- Much harder to detect
-
Disables automation features:
--disable-blink-features=AutomationControlled--no-sandbox--disable-setuid-sandbox
Detection Point Comparison
| Detection Point | OpenClaw Default | StealthPlugin |
|---|---|---|
| navigator.webdriver | true β | undefined β |
| headless fingerprints | obvious β | hidden β |
| browser fingerprints | missing β | complete β |
| plugin list | empty β | real β |
| window.outerWidth | 0 β | 1920 β |
Examples
Example 1: Basic Visit
const { StealthBrowser } = require('/root/.openclaw/workspace/skills/stealth-browser/wrapper.js');
const browser = new StealthBrowser();
await browser.launch();
await browser.goto('https://linux.do');
const title = await browser.getTitle();
console.log('Title:', title);
await browser.screenshot('linux-do.png');
await browser.close();
Example 2: Multiple Pages
const { StealthBrowser } = require('/root/.openclaw/workspace/skills/stealth-browser/wrapper.js');
const browser = new StealthBrowser();
await browser.launch();
const urls = [
'https://linux.do',
'https://linux.do/latest',
'https://linux.do/c/develop/4'
];
for (const url of urls) {
await browser.goto(url);
const title = await browser.getTitle();
console.log('Title:', title);
const filename = url.replace(/https?:\/\/|\/$/g, '').replace(/\//g, '-') + '.png';
await browser.screenshot(filename);
}
await browser.close();
Example 3: Custom Configuration
const { StealthBrowser } = require('/root/.openclaw/workspace/skills/stealth-browser/wrapper.js');
const browser = new StealthBrowser({
headless: 'new',
viewport: { width: 2560, height: 1440 },
userAgent: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36'
});
await browser.goto('https://linux.do', { waitMs: 5000 });
const content = await browser.getContent();
console.log('Content length:', content.length);
await browser.close();
Known Issues
- Requires graphics environment: Headed mode needs X server
- Resource intensive: More resource usage than pure text fetching
- Slower speed: Requires launching full browser
Alternative Solutions
If you only need text content, consider using r.jina.ai proxy:
curl -s "https://r.jina.ai/http://linux.do/latest"
Pros:
- Faster
- Lighter
- 100% reliable
Cons:
- Cannot take screenshots
- Cannot interact
- Depends on third-party service
Files
wrapper.js- Main wrapper scriptexamples.js- Usage examplesREADME.md- Detailed documentation
Changelog
- 2026-02-11: Created skill with puppeteer-extra + stealth plugin
- 2026-02-11: Successfully bypassed Cloudflare Turnstile on linux.do
- 2026-02-11: Added comprehensive API and examples