Stealth mode plugin for puppeteer-extra that applies various techniques to make detection of headless browsers harder.
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
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.
Modifies default Puppeteer launch arguments to prevent detection through command-line argument analysis.
// Evasion name: 'defaultArgs'
// Modifies: Default Chrome launch arguments to remove automation indicatorsThis evasion:
Common Argument Modifications:
--enable-automation flag--disable-blink-features to hide automation featuresDetection 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 presentUsage 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
});Removes source URL traces from injected JavaScript code to prevent detection through source inspection.
// Evasion name: 'sourceurl'
// Removes: //# sourceURL= comments from injected scriptsThis evasion:
//# sourceURL= comments from injected JavaScriptDetection 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); // falseThe default arguments evasion works during the browser launch phase:
--enable-automation and similar flagsCommon 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 realismThe source URL evasion processes injected code:
page.evaluate() and similar calls//# sourceURL= comments in injected codeSource URL Patterns Removed:
//# sourceURL=__puppeteer_evaluation_script__
//# sourceURL=pptr:evaluate
//# sourceURL=playwright:evaluate
//# sourceURL=/tmp/temporary-script// 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
])
});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
});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
])
});The default arguments evasion modifies security-related arguments:
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
])
});Miscellaneous evasions are designed for:
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
});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