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

window-frame-evasions.mddocs/

Window and Frame Evasions

Evasion techniques that fix window dimension and iframe-related detection methods. These evasions address inconsistencies in window properties and iframe behavior that can reveal headless browser automation.

Capabilities

Window Outer Dimensions Evasion

Fixes missing window.outerWidth and window.outerHeight properties in headless mode.

// Evasion name: 'window.outerdimensions'
// Fixes: window.outerWidth, window.outerHeight, and viewport consistency

This evasion:

  • Sets realistic window.outerWidth and window.outerHeight values in headless mode
  • Ensures outer dimensions are larger than inner dimensions (like real browsers)
  • Automatically adjusts viewport to match window dimensions unless specified by user
  • Prevents detection through missing or inconsistent window dimension properties

Detection Method Prevented:

// This detection method will be fooled:
if (window.outerWidth === 0 || window.outerHeight === 0) {
  // Would detect headless mode (missing outer dimensions)
} else if (window.outerWidth <= window.innerWidth) {
  // Would detect unusual dimension relationship
} else {
  // Assumes normal browser with proper window chrome
}

Usage Examples:

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

// Enable window dimensions evasion
const windowStealth = StealthPlugin({
  enabledEvasions: new Set(['window.outerdimensions'])
});

puppeteer.use(windowStealth);

const browser = await puppeteer.launch({ headless: true });
const page = await browser.newPage();

// Window dimensions will now be realistic
await page.evaluate(() => {
  console.log('Inner:', window.innerWidth, 'x', window.innerHeight);
  console.log('Outer:', window.outerWidth, 'x', window.outerHeight);
  
  // Outer dimensions will be larger than inner (accounting for browser chrome)
  console.log('Has window chrome:', window.outerWidth > window.innerWidth);
  // Returns: true (like a real browser)
});

Iframe Content Window Evasion

Fixes iframe detection issues, particularly with srcdoc powered iframes.

// Evasion name: 'iframe.contentWindow'
// Fixes: iframe.contentWindow.chrome detection and related iframe issues

This evasion:

  • Prevents detection through iframe content window properties
  • Fixes Chrome object availability in iframe contexts
  • Addresses Chromium bugs with srcdoc iframes
  • Ensures consistent behavior across iframe boundaries

Detection Method Prevented:

// This detection method will be fooled:
const iframe = document.createElement('iframe');
iframe.srcdoc = '<html><body></body></html>';
document.body.appendChild(iframe);

iframe.onload = () => {
  if (iframe.contentWindow.chrome) {
    // Assumes real Chrome browser
  } else {
    // Would detect headless/automation through missing Chrome object in iframe
  }
};

Implementation Details:

The iframe content window evasion:

  1. Monitors Iframe Creation: Watches for new iframe elements
  2. Patches Content Windows: Applies stealth modifications to iframe content windows
  3. Handles srcdoc Iframes: Specifically addresses Chromium bug with srcdoc-powered iframes
  4. Maintains Consistency: Ensures Chrome objects are available across frame boundaries
  5. Prevents Leakage: Stops detection methods that rely on iframe property differences

Usage Examples:

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

// Enable iframe evasion along with Chrome API evasions
const iframeStealth = StealthPlugin({
  enabledEvasions: new Set([
    'iframe.contentWindow',
    'chrome.runtime',
    'chrome.app'
  ])
});

puppeteer.use(iframeStealth);

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

// Test iframe behavior
await page.evaluate(() => {
  const iframe = document.createElement('iframe');
  iframe.srcdoc = `
    <html>
      <body>
        <script>
          // This will now work properly without detection
          console.log('Chrome in iframe:', typeof chrome !== 'undefined');
          console.log('Chrome runtime:', typeof chrome?.runtime !== 'undefined');
        </script>
      </body>
    </html>
  `;
  
  document.body.appendChild(iframe);
  
  return new Promise(resolve => {
    iframe.onload = () => {
      // iframe content window now has proper Chrome objects
      resolve(typeof iframe.contentWindow.chrome !== 'undefined');
    };
  });
});

Window Dimension Management

Automatic Viewport Adjustment

The window outer dimensions evasion automatically adjusts the browser viewport to create realistic dimension relationships:

// The evasion automatically calculates appropriate dimensions
// Inner dimensions: Set by user or browser defaults
// Outer dimensions: Inner + realistic browser chrome size

const chromeSize = 85; // Typical browser chrome height
const outerWidth = innerWidth + 16; // Small width addition for scrollbars
const outerHeight = innerHeight + chromeSize; // Browser chrome height

Custom Viewport Handling

If you set a custom viewport, the evasion respects your settings:

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

// Set custom viewport - evasion will adjust outer dimensions accordingly
await page.setViewport({ width: 1366, height: 768 });

// Outer dimensions will be calculated based on this viewport
// outerWidth: ~1382, outerHeight: ~853

Cross-Frame Consistency

Both window and iframe evasions ensure consistency across different execution contexts:

Main Frame vs Iframe

// Main frame and all iframes will have consistent Chrome object availability
await page.evaluate(() => {
  // Main frame
  console.log('Main chrome:', typeof chrome);
  
  const iframe = document.createElement('iframe');
  iframe.srcdoc = '<script>parent.postMessage(typeof chrome, "*")</script>';
  
  window.addEventListener('message', (e) => {
    console.log('Iframe chrome:', e.data);
    // Both will show 'object' if Chrome evasions are enabled
  });
  
  document.body.appendChild(iframe);
});

Multiple Windows

Window evasions apply to all windows opened from the page:

await page.evaluate(() => {
  const newWindow = window.open('about:blank');
  
  // New window will also have proper outer dimensions
  setTimeout(() => {
    console.log('New window outer:', newWindow.outerWidth, newWindow.outerHeight);
    console.log('New window chrome:', typeof newWindow.chrome);
    newWindow.close();
  }, 100);
});

Browser Compatibility

Window and frame evasions are designed for:

  • Chrome/Chromium: Primary target with specific bug fixes
  • Headless Mode: Specifically addresses headless-mode limitations
  • Cross-Platform: Works consistently across Windows, macOS, and Linux
  • Multiple Versions: Handles different Chrome/Chromium version behaviors

Advanced Usage Patterns

Selective Window Evasions

// Only fix window dimensions, not iframe behavior
const windowOnly = StealthPlugin({
  enabledEvasions: new Set(['window.outerdimensions'])
});

// Only fix iframe behavior, keep original window dimensions
const iframeOnly = StealthPlugin({
  enabledEvasions: new Set(['iframe.contentWindow', 'chrome.runtime'])
});

Integration with Other Evasions

Window and frame evasions work best when combined with related evasions:

// Comprehensive window/frame protection
const windowFrameStealth = StealthPlugin({
  enabledEvasions: new Set([
    'window.outerdimensions',     // Fix window dimensions
    'iframe.contentWindow',       // Fix iframe behavior
    'chrome.runtime',            // Provide Chrome objects in iframes
    'chrome.app',               // Complete Chrome API simulation
    'navigator.webdriver'        // Remove automation indicators
  ])
});

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