CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-puppeteer-core

A high-level API to control headless Chrome and Firefox browsers over the DevTools Protocol and WebDriver BiDi

94

1.02x
Overview
Eval results
Files

element-handling.mddocs/

Element Handling

Advanced element selection, interaction, and manipulation with comprehensive locator strategies and event handling.

Capabilities

ElementHandle Interface

Represents a reference to a DOM element in the page, providing methods for interaction and property access.

interface ElementHandle extends JSHandle {
  /** Click the element */
  click(options?: ClickOptions): Promise<void>;
  /** Double-click the element */
  dblclick(options?: ClickOptions): Promise<void>;
  /** Right-click the element */
  rightclick(options?: ClickOptions): Promise<void>;
  /** Focus the element */
  focus(): Promise<void>;
  /** Hover over the element */
  hover(): Promise<void>;
  /** Tap the element (mobile) */
  tap(): Promise<void>;
  /** Type text into the element */
  type(text: string, options?: TypeOptions): Promise<void>;
  /** Press a key */
  press(key: string, options?: PressOptions): Promise<void>;
  /** Select options in a select element */
  select(...values: string[]): Promise<string[]>;
  /** Upload file(s) to input element */
  uploadFile(...filePaths: string[]): Promise<void>;
  /** Get bounding box */
  boundingBox(): Promise<BoundingBox | null>;
  /** Get bounding box relative to main frame */
  boxModel(): Promise<BoxModel | null>;
  /** Take screenshot of element */
  screenshot(options?: ScreenshotOptions): Promise<Buffer>;
  /** Get content frame (for iframe elements) */
  contentFrame(): Promise<Frame | null>;
  /** Scroll element into view if needed */
  scrollIntoView(): Promise<void>;
  /** Scroll within element */
  scroll(options: ScrollOptions): Promise<void>;
  /** Drag element to another element or coordinate */
  drag(target: { x: number; y: number } | ElementHandle): Promise<void>;
  /** Drag and drop element */
  dragAndDrop(target: ElementHandle, options?: DragAndDropOptions): Promise<void>;
  /** Check if element is intersecting viewport */
  isIntersectingViewport(options?: { threshold?: number }): Promise<boolean>;
  /** Get inner text */
  innerText(): Promise<string>;
  /** Get inner HTML */
  innerHTML(): Promise<string>;
  /** Get outer HTML */
  outerHTML(): Promise<string>;
  /** Get text content */
  textContent(): Promise<string>;
  /** Get attribute value */
  getAttribute(name: string): Promise<string | null>;
  /** Get property value */
  getProperty(propertyName: string): Promise<JSHandle>;
  /** Get all properties */
  getProperties(): Promise<Map<string, JSHandle>>;
  /** Get JSON value */
  jsonValue(): Promise<any>;
  /** Convert to ElementHandle if this is an element */
  asElement(): ElementHandle | null;
  /** Dispose the handle */
  dispose(): Promise<void>;
  /** Get execution context */
  executionContext(): ExecutionContext;
  /** Evaluate function with element as this */
  evaluate<T>(pageFunction: Function, ...args: any[]): Promise<T>;
  /** Evaluate function and return handle */
  evaluateHandle(pageFunction: Function, ...args: any[]): Promise<JSHandle>;
  /** Query selector within element */
  $(selector: string): Promise<ElementHandle | null>;
  /** Query selector all within element */
  $$(selector: string): Promise<ElementHandle[]>;
  /** Evaluate with selector within element */
  $eval<T>(selector: string, pageFunction: Function, ...args: any[]): Promise<T>;
  /** Evaluate with selector all within element */
  $$eval<T>(selector: string, pageFunction: Function, ...args: any[]): Promise<T>;
  /** XPath query within element */
  $x(expression: string): Promise<ElementHandle[]>;
  /** Wait for selector within element */
  waitForSelector(selector: string, options?: WaitForSelectorOptions): Promise<ElementHandle | null>;
  /** Wait for XPath within element */
  waitForXPath(xpath: string, options?: WaitForSelectorOptions): Promise<ElementHandle | null>;
  /** Wait for function */
  waitForFunction(pageFunction: Function, options?: WaitForFunctionOptions, ...args: any[]): Promise<JSHandle>;
  /** Check if element is visible */
  isVisible(): Promise<boolean>;
  /** Check if element is hidden */
  isHidden(): Promise<boolean>;
  /** Get owning frame */
  ownerFrame(): Promise<Frame | null>;
  /** Get remote object */
  remoteObject(): Protocol.Runtime.RemoteObject;
}

interface ClickOptions {
  /** Mouse button to use */
  button?: "left" | "right" | "middle";
  /** Number of clicks */
  clickCount?: number;
  /** Delay between mousedown and mouseup */
  delay?: number;
  /** Offset from element center */
  offset?: { x: number; y: number };
  /** Wait for element to be actionable */
  force?: boolean;
  /** Timeout for actionability checks */
  timeout?: number;
  /** Trial run without actually clicking */
  trial?: boolean;
}

interface TypeOptions {
  /** Delay between key presses */
  delay?: number;
  /** Timeout for actionability checks */
  timeout?: number;
  /** Whether to clear existing text first */
  clear?: boolean;
}

interface PressOptions {
  /** Delay between key down and up */
  delay?: number;
  /** Timeout for actionability checks */
  timeout?: number;
}

interface BoundingBox {
  x: number;
  y: number;
  width: number;
  height: number;
}

interface BoxModel {
  content: Quad;
  padding: Quad;
  border: Quad;
  margin: Quad;
  width: number;
  height: number;
}

interface Quad {
  p1: { x: number; y: number };
  p2: { x: number; y: number };
  p3: { x: number; y: number };
  p4: { x: number; y: number };
}

interface ScrollOptions {
  top?: number;
  left?: number;
  behavior?: "auto" | "instant" | "smooth";
}

interface DragAndDropOptions {
  delay?: number;
  force?: boolean;
  timeout?: number;
}

interface WaitForSelectorOptions {
  /** Wait for element to be visible */
  visible?: boolean;
  /** Wait for element to be hidden */
  hidden?: boolean;
  /** Maximum wait time */
  timeout?: number;
  /** Wait for element to be attached to DOM */
  attached?: boolean;
  /** Wait for element to be detached from DOM */
  detached?: boolean;
}

interface WaitForFunctionOptions {
  /** Maximum wait time */
  timeout?: number;
  /** Polling strategy */
  polling?: "raf" | "mutation" | number;
}

Usage Examples:

import puppeteer from "puppeteer-core";

const browser = await puppeteer.launch({ executablePath: "/path/to/chrome" });
const page = await browser.newPage();
await page.goto("https://example.com");

// Basic element selection and interaction
const button = await page.$("#submit-button");
if (button) {
  await button.click();
}

const input = await page.$("input[type='text']");
if (input) {
  await input.type("Hello World", { delay: 100 });
  await input.press("Enter");
}

// Element properties and content
const heading = await page.$("h1");
if (heading) {
  const text = await heading.innerText();
  const html = await heading.innerHTML();
  const id = await heading.getAttribute("id");
  
  console.log("Heading text:", text);
  console.log("Heading HTML:", html);
  console.log("Heading ID:", id);
}

// Element positioning and visibility
const element = await page.$("#target-element");
if (element) {
  const box = await element.boundingBox();
  const isVisible = await element.isVisible();
  const isInViewport = await element.isIntersectingViewport();
  
  console.log("Element bounds:", box);
  console.log("Element visible:", isVisible);
  console.log("Element in viewport:", isInViewport);
}

// File upload
const fileInput = await page.$("input[type='file']");
if (fileInput) {
  await fileInput.uploadFile("/path/to/file.txt", "/path/to/another-file.pdf");
}

// Select options
const selectElement = await page.$("select");
if (selectElement) {
  const selectedValues = await selectElement.select("option1", "option2");
  console.log("Selected values:", selectedValues);
}

await browser.close();

JSHandle Interface

Base interface for JavaScript object references in the page context.

interface JSHandle {
  /** Evaluate function with handle as this */
  evaluate<T>(pageFunction: Function, ...args: any[]): Promise<T>;
  /** Evaluate function and return handle */
  evaluateHandle(pageFunction: Function, ...args: any[]): Promise<JSHandle>;
  /** Get property value */
  getProperty(propertyName: string): Promise<JSHandle>;
  /** Get all properties */
  getProperties(): Promise<Map<string, JSHandle>>;
  /** Get JSON value */
  jsonValue(): Promise<any>;
  /** Convert to ElementHandle if this is an element */
  asElement(): ElementHandle | null;
  /** Dispose the handle */
  dispose(): Promise<void>;
  /** Convert to string representation */
  toString(): string;
  /** Get execution context */
  executionContext(): ExecutionContext;
  /** Get remote object */
  remoteObject(): Protocol.Runtime.RemoteObject;
}

Usage Examples:

// Get JavaScript objects
const windowHandle = await page.evaluateHandle(() => window);
const documentHandle = await page.evaluateHandle(() => document);

// Get object properties
const locationHandle = await windowHandle.getProperty("location");
const href = await locationHandle.jsonValue();

// Evaluate with handle
const title = await documentHandle.evaluate((doc) => doc.title);

// Dispose handles to prevent memory leaks
await windowHandle.dispose();
await documentHandle.dispose();
await locationHandle.dispose();

Element Selection Methods

Various methods for selecting elements in the page:

interface ElementSelectionMethods {
  /** Query single element by CSS selector */
  $(selector: string): Promise<ElementHandle | null>;
  /** Query multiple elements by CSS selector */
  $$(selector: string): Promise<ElementHandle[]>;
  /** Evaluate function with selected element */
  $eval<T>(selector: string, pageFunction: Function, ...args: any[]): Promise<T>;
  /** Evaluate function with all selected elements */
  $$eval<T>(selector: string, pageFunction: Function, ...args: any[]): Promise<T>;
  /** Query elements by XPath */
  $x(expression: string): Promise<ElementHandle[]>;
}

Usage Examples:

// CSS selectors
const header = await page.$("header");
const allButtons = await page.$$("button");
const navLinks = await page.$$("nav a");

// Evaluate with selected elements
const buttonTexts = await page.$$eval("button", (buttons) => 
  buttons.map(btn => btn.textContent)
);

const firstLinkHref = await page.$eval("a", (link) => link.href);

// XPath selectors
const elementsWithText = await page.$x("//div[contains(text(), 'Hello')]");
const tableRows = await page.$x("//table//tr");

// Complex selectors
const specificElement = await page.$(
  "div.container > section:nth-child(2) button[data-action='submit']"
);

Advanced Element Operations

Complex element interactions and advanced features:

interface AdvancedElementOperations {
  /** Drag and drop operations */
  dragAndDrop(source: ElementHandle, target: ElementHandle, options?: DragAndDropOptions): Promise<void>;
  /** Scroll operations */
  scroll(element: ElementHandle, options: ScrollOptions): Promise<void>;
  /** Visibility checks */
  isVisible(element: ElementHandle): Promise<boolean>;
  isHidden(element: ElementHandle): Promise<boolean>;
  /** Wait for element state changes */
  waitForElementState(element: ElementHandle, state: "visible" | "hidden" | "stable"): Promise<void>;
}

Usage Examples:

// Drag and drop
const draggable = await page.$("#draggable-item");
const dropZone = await page.$("#drop-zone");

if (draggable && dropZone) {
  await draggable.dragAndDrop(dropZone, { delay: 100 });
}

// Scroll operations
const scrollableDiv = await page.$("#scrollable-content");
if (scrollableDiv) {
  await scrollableDiv.scroll({ top: 100, behavior: "smooth" });
}

// Advanced waiting
const dynamicElement = await page.$("#dynamic-content");
if (dynamicElement) {
  // Wait for element to become visible
  await page.waitForFunction(
    (el) => el.offsetHeight > 0,
    {},
    dynamicElement
  );
}

// Element screenshots
const chart = await page.$("#sales-chart");
if (chart) {
  await chart.screenshot({ path: "chart.png" });
}

Frame Context

Working with elements in different frames:

interface Frame {
  /** Query selector in frame */
  $(selector: string): Promise<ElementHandle | null>;
  /** Query selector all in frame */
  $$(selector: string): Promise<ElementHandle[]>;
  /** Evaluate with selector in frame */
  $eval<T>(selector: string, pageFunction: Function, ...args: any[]): Promise<T>;
  /** Evaluate with selector all in frame */
  $$eval<T>(selector: string, pageFunction: Function, ...args: any[]): Promise<T>;
  /** XPath query in frame */
  $x(expression: string): Promise<ElementHandle[]>;
  /** Wait for selector in frame */
  waitForSelector(selector: string, options?: WaitForSelectorOptions): Promise<ElementHandle | null>;
  /** Get frame name */
  name(): string;
  /** Get frame URL */
  url(): string;
  /** Get parent frame */
  parentFrame(): Frame | null;
  /** Get child frames */
  childFrames(): Frame[];
  /** Check if frame detached */
  isDetached(): boolean;
  /** Get execution context */
  executionContext(): Promise<ExecutionContext>;
  /** Evaluate in frame */
  evaluate<T>(pageFunction: Function, ...args: any[]): Promise<T>;
  /** Evaluate and return handle in frame */
  evaluateHandle<T>(pageFunction: Function, ...args: any[]): Promise<JSHandle<T>>;
  /** Click in frame */
  click(selector: string, options?: ClickOptions): Promise<void>;
  /** Focus in frame */
  focus(selector: string): Promise<void>;
  /** Hover in frame */
  hover(selector: string): Promise<void>;
  /** Select in frame */
  select(selector: string, ...values: string[]): Promise<string[]>;
  /** Tap in frame */
  tap(selector: string): Promise<void>;
  /** Type in frame */
  type(selector: string, text: string, options?: TypeOptions): Promise<void>;
}

Usage Examples:

// Working with iframes
const frames = page.frames();
const iframe = frames.find(frame => frame.name() === "content-frame");

if (iframe) {
  // Select elements within iframe
  const iframeButton = await iframe.$("#iframe-button");
  if (iframeButton) {
    await iframeButton.click();
  }
  
  // Evaluate within iframe
  const iframeTitle = await iframe.evaluate(() => document.title);
  console.log("Iframe title:", iframeTitle);
}

// Handle nested frames
const childFrames = iframe?.childFrames() || [];
for (const childFrame of childFrames) {
  const childContent = await childFrame.$eval("body", (body) => body.textContent);
  console.log("Child frame content:", childContent);
}

Error Handling

Common errors when working with elements:

class TimeoutError extends Error {
  constructor(message: string);
}

class ElementHandleError extends Error {
  constructor(message: string);
}

Usage Examples:

try {
  // Element might not exist
  const element = await page.waitForSelector("#dynamic-element", { 
    timeout: 5000 
  });
  
  if (element) {
    await element.click();
  }
} catch (error) {
  if (error instanceof TimeoutError) {
    console.log("Element did not appear within timeout");
  } else {
    console.log("Unexpected error:", error.message);
  }
}

// Safe element operations
async function safeClick(page: Page, selector: string) {
  try {
    const element = await page.$(selector);
    if (element) {
      const isVisible = await element.isVisible();
      if (isVisible) {
        await element.click();
        return true;
      }
    }
  } catch (error) {
    console.log(`Failed to click ${selector}:`, error.message);
  }
  return false;
}

// Usage
const success = await safeClick(page, "#submit-button");
if (!success) {
  console.log("Could not click submit button");
}

Install with Tessl CLI

npx tessl i tessl/npm-puppeteer-core

docs

browser-contexts.md

browser-management.md

element-handling.md

index.md

input-simulation.md

locators-selectors.md

network-management.md

page-interaction.md

tile.json