CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-puppeteer-extra-plugin-stealth

Stealth mode plugin for puppeteer-extra that applies various techniques to make detection of headless browsers harder.

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

misc-evasions.mddocs/

Miscellaneous Evasions

Additional evasion techniques for launch arguments modification and source code obfuscation. These evasions address various detection methods that don't fit into other categories but are important for comprehensive stealth operation.

Capabilities

Default Arguments Evasion

Modifies default Puppeteer launch arguments to prevent detection through command-line argument analysis.

// Evasion name: 'defaultArgs'
// Modifies: Default Chrome launch arguments to remove automation indicators

This evasion:

  • Removes or modifies Chrome launch arguments that indicate automation
  • Adds arguments that make the browser appear more like a regular user's browser
  • Handles arguments that could reveal headless or automated operation
  • Ensures the browser is launched with stealth-friendly default arguments

Common Argument Modifications:

  • Removes --enable-automation flag
  • Modifies --disable-blink-features to hide automation features
  • Adjusts user data directory settings
  • Configures extension and plugin arguments for realistic behavior

Detection Method Prevented:

// Process inspection that could detect automation arguments
// This happens outside the browser context, in the system process list
// Example: ps aux | grep chrome | grep "enable-automation"
// The evasion ensures such automation indicators are not present

Usage Examples:

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

// Enable default arguments evasion
const argsStealth = StealthPlugin({
  enabledEvasions: new Set(['defaultArgs'])
});

puppeteer.use(argsStealth);

// Launch arguments will be automatically modified
const browser = await puppeteer.launch({
  headless: true,
  // The evasion will modify the final launch arguments
  // to remove automation indicators
});

Source URL Evasion

Removes source URL traces from injected JavaScript code to prevent detection through source inspection.

// Evasion name: 'sourceurl'
// Removes: //# sourceURL= comments from injected scripts

This evasion:

  • Strips //# sourceURL= comments from injected JavaScript
  • Removes file path traces that could reveal automation
  • Cleans up source mapping information that indicates injection
  • Prevents detection through JavaScript source inspection

Detection Method Prevented:

// This detection method will be fooled:
const scripts = Array.from(document.scripts);
const hasSourceURL = scripts.some(script => 
  script.innerHTML.includes('sourceURL=')
);

if (hasSourceURL) {
  // Would detect injected code with source URL traces
} else {
  // Assumes naturally loaded scripts
}

Source URL Examples:

Before evasion:

// Injected code might contain:
function myFunction() { /* code */ }
//# sourceURL=__puppeteer_evaluation_script__

After evasion:

// Clean code without source traces:
function myFunction() { /* code */ }

Usage Examples:

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

// Enable source URL evasion
const sourceStealth = StealthPlugin({
  enabledEvasions: new Set(['sourceurl'])
});

puppeteer.use(sourceStealth);

const browser = await puppeteer.launch();
const page = await browser.newPage();

// Injected code will not contain source URL traces
await page.evaluate(() => {
  // This code injection will not leave sourceURL traces
  return document.title;
});

// Check for source URL traces (will find none with evasion enabled)
const hasTraces = await page.evaluate(() => {
  return Array.from(document.scripts).some(script => 
    script.innerHTML.includes('sourceURL=') || 
    script.innerHTML.includes('puppeteer')
  );
});

console.log('Has source traces:', hasTraces); // false

Implementation Details

Default Arguments Processing

The default arguments evasion works during the browser launch phase:

  1. Argument Interception: Captures the default Chrome launch arguments
  2. Automation Flag Removal: Removes --enable-automation and similar flags
  3. Stealth Argument Addition: Adds arguments that improve stealth operation
  4. User Agent Coordination: Ensures arguments align with user agent settings
  5. Extension Handling: Configures extension-related arguments appropriately

Common Arguments Modified:

// Arguments that may be removed or modified:
'--enable-automation'                    // Removed (automation indicator)
'--disable-blink-features=AutomationControlled'  // Added by other evasions
'--disable-default-apps'                 // May be modified
'--disable-extensions'                   // May be modified for realism

Source URL Cleaning

The source URL evasion processes injected code:

  1. Code Injection Interception: Monitors all page.evaluate() and similar calls
  2. Source URL Detection: Finds //# sourceURL= comments in injected code
  3. Trace Removal: Strips source URL comments before execution
  4. Clean Execution: Runs the code without detectable injection traces
  5. Error Preservation: Maintains error handling while removing traces

Source URL Patterns Removed:

//# sourceURL=__puppeteer_evaluation_script__
//# sourceURL=pptr:evaluate
//# sourceURL=playwright:evaluate
//# sourceURL=/tmp/temporary-script

Advanced Configuration

Selective Argument Control

// Enable only default arguments evasion
const argsOnly = StealthPlugin({
  enabledEvasions: new Set(['defaultArgs'])
});

// Combine with other evasions for comprehensive stealth
const fullStealth = StealthPlugin({
  enabledEvasions: new Set([
    'defaultArgs',      // Clean launch arguments
    'sourceurl',        // Clean injected code
    'navigator.webdriver', // Remove webdriver property
    'user-agent-override'  // Clean user agent
  ])
});

Manual Launch Argument Override

Even with the default arguments evasion, you can still provide custom arguments:

const browser = await puppeteer.launch({
  headless: true,
  args: [
    '--no-sandbox',
    '--disable-setuid-sandbox',
    '--custom-argument'
  ]
  // The evasion will still process and clean these arguments
});

Security and Debugging Considerations

Source URL Impact on Debugging

The source URL evasion removes debugging information that could be useful during development:

// For development, you might want to disable source URL evasion
const devStealth = StealthPlugin({
  enabledEvasions: new Set([
    'navigator.webdriver',
    'user-agent-override'
    // 'sourceurl' disabled for easier debugging
  ])
});

Launch Arguments and Security

The default arguments evasion modifies security-related arguments:

  • Removes automation flags: Improves stealth but may affect some automation features
  • Modifies extension settings: May impact extension-based functionality
  • Changes default policies: Could affect browser security posture

Production Usage

For production environments, both evasions are recommended:

// Production stealth configuration
const productionStealth = StealthPlugin({
  enabledEvasions: new Set([
    'defaultArgs',        // Clean launch arguments
    'sourceurl',          // Remove code injection traces
    'navigator.webdriver', // Remove automation indicators
    'user-agent-override', // Clean user agent
    'chrome.runtime'      // Provide Chrome APIs
  ])
});

Browser Compatibility

Miscellaneous evasions are designed for:

  • Chrome/Chromium: Primary target for launch argument modification
  • Puppeteer: Full compatibility with all Puppeteer launch options
  • Playwright: Compatible with playwright-extra argument handling
  • Cross-Platform: Works across different operating systems and environments

Troubleshooting

Launch Arguments Issues

If you experience issues with modified launch arguments:

// Debug launch arguments
const browser = await puppeteer.launch({
  headless: true,
  dumpio: true // Enable console output to see actual arguments
});

Source URL Detection Issues

If source URL cleaning affects debugging:

// Temporarily disable for debugging
const debugStealth = StealthPlugin({
  enabledEvasions: new Set(['navigator.webdriver']) // Minimal set
});

// Or check if source URLs are being properly cleaned
await page.evaluate(() => {
  return document.documentElement.innerHTML.includes('sourceURL=');
});

Install with Tessl CLI

npx tessl i tessl/npm-puppeteer-extra-plugin-stealth

docs

chrome-evasions.md

core-plugin.md

fingerprinting-evasions.md

index.md

misc-evasions.md

navigator-evasions.md

window-frame-evasions.md

tile.json