A high-level API to control headless Chrome and Firefox browsers over the DevTools Protocol and WebDriver BiDi
94
Advanced element selection, interaction, and manipulation with comprehensive locator strategies and event handling.
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();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();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']"
);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" });
}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);
}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-coredocs
evals
scenario-1
scenario-2
scenario-3
scenario-4
scenario-5
scenario-6
scenario-7
scenario-8
scenario-9
scenario-10