🚨 Warning

This is not (Puppeteer or Selenium). It doesn't use the same API!

This module runs as a real Chrome extension, making it stealthy and hard to detect.

It uses a completely separate API to interact with the browser via WebSocket.

Introduction to pear3

pear3 is a powerful browser automation library for Node.js that provides direct control over Chrome/Chromium through WebSocket communication. Unlike traditional automation tools, pear3 operates as a Chrome extension, making it:

  • Stealthy - Hard to detect by anti-bot systems
  • Fast - Direct communication without protocol overhead
  • Reliable - Real browser environment, not headless simulation
  • Feature-rich - Full access to modern web APIs

Perfect for web scraping, automated testing, form automation, and browser behavior analysis.

Installation

Install pear3 using npm:

npm install pear3

Requirements:

pear3 requires Chrome or Chromium. It can automatically download Chromium or use your system's Chrome installation.

Getting Started

Basic usage example:

const Pear = require("pear3");

async function main() {
  const browser = await Pear({
    viewport: { width: 1280, height: 800 },
    headless: false
  });

  const page = await browser.newPage();
  await page.goto("https://google.com");
  
  // Type in search box
  await page.directType('textarea', 'Hello Pear!');
  await page.keypress('Enter');
  
  // Take screenshot
  const screenshot = await page.screenshot();
  
  await browser.close();
}

main().catch(console.error);

Browser API

Initialization Options

Configure pear3 with these options:

const browser = await Pear({
  browserPath: "/path/to/chrome",       // Custom Chrome executable path
  profileDir: "./chrome-profile",      // Chrome user data directory
  args: ["--disable-gpu"],             // Additional Chrome arguments
  userAgent: "Custom User Agent",      // Set custom user agent
  viewport: { width: 1280, height: 720 }, // Default viewport size
  incognito: false,                    // Use incognito mode
  headless: false,                     // Run in headless mode
  disableGpu: false,                   // Disable GPU acceleration
  nosandbox: false,                    // Disable sandbox (Linux)
  proxy: "http://proxy:8080",          // Proxy server
  muteaudio: false,                    // Mute audio
  cookies: cookieArray                 // Pre-load cookies
});

Browser Methods

  • .newPage()

    Creates a new page (tab) and returns a Page object for interaction.

  • .newTab()

    Alias for newPage(). Creates a new tab.

  • .close()

    Closes the browser instance and all associated resources.

Page API

Core page navigation and content methods:

  • .goto(url)

    Navigate to the specified URL.

    await page.goto("https://example.com");
  • .url()

    Get the current page URL.

    const currentUrl = await page.url();
  • .reload()

    Reload the current page.

    await page.reload();
  • .content()

    Get the full HTML content of the page.

    const html = await page.content();
  • .close()

    Close the current page/tab.

    await page.close();

Mouse & Keyboard Events

Keyboard Events

Simulate keyboard interactions with precise control:

// Basic key press (keydown + keyup)
await page.keypress('Enter');
await page.keypress('Tab');
await page.keypress('Escape');

// Key down (hold key)
await page.keydown('Shift');
await page.keydown('Control');

// Key up (release key)
await page.keyup('Shift');

// Target specific element (optional)
await page.keypress('Enter', '#search-input');

// With options
await page.keypress('a', '#input', { 
  ctrlKey: true,  // Ctrl+A
  shiftKey: false 
});

Mouse Events

Full mouse interaction support:

// Click types
await page.leftclick('#button');        // Left click
await page.rightclick('#menu-trigger');  // Right click (context menu)
await page.middleclick('#link');         // Middle click (new tab)
await page.dblclick('#file');            // Double click

// Mouse actions
await page.mousedown('#draggable');      // Mouse down
await page.mouseup('#draggable');        // Mouse up
await page.mousemove('#target');         // Move mouse to element

// With custom coordinates
await page.leftclick('#element', { x: 10, y: 20 });

// Scroll actions
await page.scroll(null, { x: 0, y: 500 });  // Scroll window
await page.scroll('#container', { y: -200 }); // Scroll element up

Text Input Methods

Two methods for text input with different behaviors:

  • .type(selector, text)

    Simulates natural typing - fires keyboard events for each character. Slower but more realistic.

    await page.type('#username', 'john_doe');
    // Triggers keydown, input, keyup events for each character
  • .directType(selector, text)

    Direct value assignment - faster but bypasses keyboard events. Good for large text blocks.

    await page.directType('#message', 'This is a long message...');
    // Sets value directly, fires single input event

When to use which?

type(): For forms that listen to keyboard events, character validation, or when you need realistic typing simulation.

directType(): For bulk text entry, textareas, or when speed is more important than event simulation.

Element API

Methods for interacting with page elements:

  • .getAttribute(selector, attribute)

    Get an element's attribute value.

    const href = await page.getAttribute('a#main-link', 'href');
    const className = await page.getAttribute('.item', 'class');
  • .getText(selector)

    Get an element's text content.

    const buttonText = await page.getText('#submit-btn');
    const headingText = await page.getText('h1');

Screenshots

Capture page screenshots as base64 or buffer:

// Get screenshot as buffer
const screenshotBuffer = await page.screenshot();

// Save to file
const fs = require('fs');
fs.writeFileSync('screenshot.png', screenshotBuffer);

File Upload

Upload files to file input elements:

// Upload single file (URL or local path)
await page.uploadFile('#file-input', 'https://example.com/image.jpg');

// Note: Local file paths must be accessible to the browser
// For local files, use file:// URLs or serve them via HTTP

File Path Requirements:

Files must be accessible via HTTP/HTTPS URLs. Local file:// paths have browser security restrictions. Consider serving local files through a local HTTP server.

Wait Methods

Wait for elements or conditions before proceeding:

  • .waitForSelector(selector, options)

    Wait for an element to appear in the DOM.

    // Basic usage
    await page.waitForSelector('.loading-complete');
    
    // With timeout and check interval
    await page.waitForSelector('#dynamic-content', {
      timeout: 10000,      // Wait max 10 seconds
      checkInterval: 200   // Check every 200ms
    });
    
    // Disable timeout (wait indefinitely)
    await page.waitForSelector('.element', { timeout: 0 });

Complete Examples

Google Search Automation

const Pear = require("pear3");

async function googleSearch() {
  const browser = await Pear({
    viewport: { width: 1280, height: 800 }
  });

  const page = await browser.newPage();
  await page.goto("https://google.com");
  
  // Wait for search box and type query
  await page.waitForSelector('textarea[name="q"]');
  await page.type('textarea[name="q"]', 'pear browser automation');
  await page.keypress('Enter');
  
  // Wait for results and take screenshot
  await page.waitForSelector('#search');
  const screenshot = await page.screenshot();
  
  require('fs').writeFileSync('search-results.png', screenshot);
  console.log('Search completed and screenshot saved!');
  
  await browser.close();
}

googleSearch().catch(console.error);

Form Automation

const Pear = require("pear3");

async function fillForm() {
  const browser = await Pear();
  const page = await browser.newPage();
  
  await page.goto("https://example.com/contact-form");
  
  // Fill form fields
  await page.type('#name', 'John Doe');
  await page.type('#email', 'john@example.com');
  await page.directType('#message', `
    This is a longer message that I'm typing
    into the contact form using directType
    for better performance.
  `);
  
  // Select dropdown option
  await page.leftclick('#country');
  await page.waitForSelector('#country option[value="US"]');
  await page.leftclick('#country option[value="US"]');
  
  // Upload file
  await page.uploadFile('#attachment', 'https://example.com/document.pdf');
  
  // Submit form
  await page.leftclick('#submit-button');
  
  // Wait for confirmation
  await page.waitForSelector('.success-message');
  console.log('Form submitted successfully!');
  
  await browser.close();
}

fillForm().catch(console.error);

Web Scraping with Mouse Interactions

const Pear = require("pear3");

async function scrapeWithInteraction() {
  const browser = await Pear({ headless: false });
  const page = await browser.newPage();
  
  await page.goto("https://example-spa.com");
  
  // Wait for page to load
  await page.waitForSelector('.content-loaded');
  
  // Hover to reveal dropdown menu
  await page.mousemove('.menu-trigger');
  await page.waitForSelector('.dropdown-menu');
  
  // Right-click to open context menu
  await page.rightclick('.data-item');
  await page.leftclick('.context-export');
  
  // Scroll to load more content
  for (let i = 0; i < 5; i++) {
    await page.scroll(null, { y: 500 });
    await page.waitForSelector(`.item-${i + 6}`, { timeout: 2000 });
  }
  
  // Extract all data
  const content = await page.content();
  // Process content...
  
  await browser.close();
}

scrapeWithInteraction().catch(console.error);

Multi-tab Management

const Pear = require("pear3");

async function multiTabExample() {
  const browser = await Pear();
  
  // Open multiple tabs
  const page1 = await browser.newPage();
  const page2 = await browser.newPage();
  const page3 = await browser.newPage();
  
  // Work with different tabs simultaneously
  await Promise.all([
    page1.goto("https://site1.com"),
    page2.goto("https://site2.com"),
    page3.goto("https://site3.com")
  ]);
  
  // Take screenshots of all tabs
  const screenshots = await Promise.all([
    page1.screenshot(),
    page2.screenshot(),
    page3.screenshot()
  ]);
  
  // Save screenshots
  const fs = require('fs');
  screenshots.forEach((screenshot, index) => {
    fs.writeFileSync(`tab-${index + 1}.png`, screenshot);
  });
  
  // Close specific tabs
  await page2.close();
  await page3.close();
  
  // Continue working with page1
  await page1.type('#search', 'final search');
  
  await browser.close();
}

multiTabExample().catch(console.error);