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 URL
  • filename (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 browser
  • goto(url, options?) - Navigate to URL
  • screenshot(filename) - Take screenshot
  • getTitle() - Get page title
  • getContent() - Get HTML content
  • evaluate(fn, ...args) - Execute JavaScript
  • checkSuccess(keywords) - Check if visit succeeded
  • close() - Close browser
  • visitAndScreenshot(url, filename) - Shortcut method

How It Works

Why OpenClaw Default Browser Fails

  1. navigator.webdriver = true - Explicitly identifies as automated browser
  2. Uses legacy headless mode with obvious fingerprints
  3. Missing real browser fingerprints
  4. No plugin list or language settings

How StealthPlugin Solves It

  1. Hides automation indicators:

    • Changes navigator.webdriver to undefined
    • Overrides Function.prototype.toString
    • Fixes iframe detection
  2. Mimics real fingerprints:

    • Adds real plugin list
    • Simulates language settings
    • Fixes window.outerWidth/Height
    • Adds touch support
  3. Uses new headless mode:

    • headless: 'new' uses real Chrome rendering engine
    • Much harder to detect
  4. 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

  1. Requires graphics environment: Headed mode needs X server
  2. Resource intensive: More resource usage than pure text fetching
  3. 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 script
  • examples.js - Usage examples
  • README.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

References

Weekly Installs
2
First Seen
Mar 14, 2026