Skip to content

bosniankicks/stealthwright

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

7 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Stealthwright

Stealthwright is a browser automation library with a Playwright-like API using the Chrome DevTools Protocol (CDP) for improved detection avoidance.

Features

  • Playwright-compatible API: Familiar syntax for easy migration from Playwright
  • Detection Avoidance: Custom CDP implementation for better evasion of anti-bot measures
  • Human-like Interaction: Simulate realistic typing with mistakes, natural pauses, and mouse movements
  • Proxy Support: Built-in proxy rotation and authentication handling
  • Cookie Management: Save and load cookies for session persistence
  • Headful/Headless Support: Run with or without visible browser windows

Installation

npm install stealthwright

Quick Start

const { stealthwright } = require('stealthwright');

(async () => {
  // Launch a browser
  const browser = await stealthwright().launch({
    headless: false,
  });
  
  // Create a browser context
  const context = browser.defaultBrowserContext();
  
  // Open a new page
  const page = await context.newPage();
  
  // Navigate to a URL
  await page.goto('https://example.com');
  
  // Take a screenshot
  await page.screenshot({ path: 'example.png' });
  
  // Close the browser
  await browser.close();
})();

API Overview

Stealthwright mimics Playwright's API structure, so if you're familiar with Playwright, you'll feel right at home.

Browser Management

// Launch a browser
const browser = await stealthwright().launch({
  headless: false,                // Run in visible mode
  proxy: 'http://user:pass@host:port',  // Use a proxy
  startURL: 'https://example.com',      // Initial URL
  ignoreHTTPSErrors: true              // Ignore SSL errors
});

// Connect to an existing browser
const browser = await stealthwright().connect({
  wsEndpoint: 'ws://localhost:9222/devtools/browser/...'
});

// Close browser
await browser.close();

Page Actions

// Navigation
await page.goto('https://example.com');
await page.goBack();
await page.goForward();
await page.reload();

// Interaction
await page.click('#button');
await page.fill('#input', 'text');
await page.type('#input', 'text', { delay: 100 });
await page.typeWithMistakes('#input', 'text', { mistakeProbability: 0.2 });
await page.press('#input', 'Enter');
await page.setChecked('#checkbox', true);
await page.selectOption('#select', 'option1');
await page.hover('#element');

// Evaluation
const text = await page.textContent('#element');
const value = await page.evaluate(() => document.title);
const exists = await page.isVisible('#element');

Locator Pattern

You can also use the locator pattern, which is helpful for repeated interactions with the same element:

const inputField = page.locator('#input');
await inputField.fill('text');
await inputField.press('Enter');
const text = await inputField.textContent();

Waiting

// Wait for elements
await page.waitForSelector('#element');
await page.waitForSelector('#element', { state: 'visible' });

// Wait for navigation
await page.waitForNavigation();
await page.waitForNavigation({ waitUntil: 'networkidle0' });

// Wait for a specific condition
await page.waitForFunction(() => window.status === 'ready');

// Wait for a specific amount of time
await page.waitForTimeout(1000); // 1 second

Screenshots and Content

// Take a screenshot
await page.screenshot({ path: 'screenshot.png' });
await page.screenshot({ path: 'fullpage.png', fullPage: true });

// Get page content
const html = await page.content();
const title = await page.title();

Cookies

// Get all cookies
const cookies = await page.cookies();

// Set cookies
await page.setCookies([
  { name: 'cookie1', value: 'value1', domain: 'example.com', path: '/' }
]);

// Delete cookies
await page.deleteCookies();

// Save cookies to file
await page.saveCookies('cookies.json');

// Load cookies from file
await page.loadCookies('cookies.json');

Advanced Features

Human-like Typing

Stealthwright can simulate human typing with realistic mistakes:

// Type with random mistakes that are corrected
await page.typeWithMistakes('#username', 'example@email.com', {
  delay: 100, // Time between keypresses in ms
  mistakeProbability: 0.3 // Probability of making a typing mistake
});

Proxy Authentication

const browser = await stealthwright().launch({
  proxy: 'http://username:password@proxy-host:port',
});

Direct CDP Access

// Execute CDP commands directly
const result = await page.cdp('Runtime.evaluate', {
  expression: 'document.title',
  returnByValue: true
});

Browser Context

Browser contexts provide an isolated environment similar to incognito mode:

// Create a browser context
const context = browser.defaultBrowserContext();

// Create a page in the context
const page = await context.newPage();

// Close the context when done
await context.close();

Error Handling

try {
  await page.click('#non-existent-element');
} catch (error) {
  if (error instanceof TimeoutError) {
    console.log('Element not found within timeout period');
  } else {
    console.error('Unexpected error:', error);
  }
}

Examples

Login to a Website

const { stealthwright } = require('stealthwright');
const fs = require('fs');

(async () => {
  const browser = await stealthwright().launch({ headless: false });
  const context = browser.defaultBrowserContext();
  const page = await context.newPage();
  
  try {
    // Navigate to login page
    await page.goto('https://example.com/login');
    
    // Fill in the login form
    await page.fill('#username', 'user@example.com');
    await page.fill('#password', 'password123');
    
    // Click the login button
    await page.click('#login-button');
    
    // Wait for navigation
    await page.waitForNavigation();
    
    // Save cookies for future sessions
    await page.saveCookies('auth-cookies.json');
    
    console.log('Login successful!');
  } catch (error) {
    console.error('Login failed:', error);
  } finally {
    await browser.close();
  }
})();

Scraping Data

const { stealthwright } = require('stealthwright');
const fs = require('fs');

(async () => {
  const browser = await stealthwright().launch();
  const page = await browser.defaultBrowserContext().newPage();
  
  try {
    await page.goto('https://example.com/products');
    
    // Extract product information
    const products = await page.evaluate(() => {
      return Array.from(document.querySelectorAll('.product')).map(product => ({
        title: product.querySelector('.title').textContent,
        price: product.querySelector('.price').textContent,
        url: product.querySelector('a').href
      }));
    });
    
    // Save the data
    fs.writeFileSync('products.json', JSON.stringify(products, null, 2));
    console.log(`Scraped ${products.length} products`);
  } catch (error) {
    console.error('Scraping failed:', error);
  } finally {
    await browser.close();
  }
})();

Comparison with Playwright

Stealthwright provides a similar API to Playwright but with enhanced detection avoidance:

// Playwright:
const { chromium } = require('playwright');
const browser = await chromium.launch();

// stealthwright:
const { stealthwright } = require('stealthwright');
const browser = await stealthwright().launch();

// The rest of your code can remain almost identical

License

MIT