0
# Element Handling
1
2
Advanced element selection, interaction, and manipulation with comprehensive locator strategies and event handling.
3
4
## Capabilities
5
6
### ElementHandle Interface
7
8
Represents a reference to a DOM element in the page, providing methods for interaction and property access.
9
10
```typescript { .api }
11
interface ElementHandle extends JSHandle {
12
/** Click the element */
13
click(options?: ClickOptions): Promise<void>;
14
/** Double-click the element */
15
dblclick(options?: ClickOptions): Promise<void>;
16
/** Right-click the element */
17
rightclick(options?: ClickOptions): Promise<void>;
18
/** Focus the element */
19
focus(): Promise<void>;
20
/** Hover over the element */
21
hover(): Promise<void>;
22
/** Tap the element (mobile) */
23
tap(): Promise<void>;
24
/** Type text into the element */
25
type(text: string, options?: TypeOptions): Promise<void>;
26
/** Press a key */
27
press(key: string, options?: PressOptions): Promise<void>;
28
/** Select options in a select element */
29
select(...values: string[]): Promise<string[]>;
30
/** Upload file(s) to input element */
31
uploadFile(...filePaths: string[]): Promise<void>;
32
/** Get bounding box */
33
boundingBox(): Promise<BoundingBox | null>;
34
/** Get bounding box relative to main frame */
35
boxModel(): Promise<BoxModel | null>;
36
/** Take screenshot of element */
37
screenshot(options?: ScreenshotOptions): Promise<Buffer>;
38
/** Get content frame (for iframe elements) */
39
contentFrame(): Promise<Frame | null>;
40
/** Scroll element into view if needed */
41
scrollIntoView(): Promise<void>;
42
/** Scroll within element */
43
scroll(options: ScrollOptions): Promise<void>;
44
/** Drag element to another element or coordinate */
45
drag(target: { x: number; y: number } | ElementHandle): Promise<void>;
46
/** Drag and drop element */
47
dragAndDrop(target: ElementHandle, options?: DragAndDropOptions): Promise<void>;
48
/** Check if element is intersecting viewport */
49
isIntersectingViewport(options?: { threshold?: number }): Promise<boolean>;
50
/** Get inner text */
51
innerText(): Promise<string>;
52
/** Get inner HTML */
53
innerHTML(): Promise<string>;
54
/** Get outer HTML */
55
outerHTML(): Promise<string>;
56
/** Get text content */
57
textContent(): Promise<string>;
58
/** Get attribute value */
59
getAttribute(name: string): Promise<string | null>;
60
/** Get property value */
61
getProperty(propertyName: string): Promise<JSHandle>;
62
/** Get all properties */
63
getProperties(): Promise<Map<string, JSHandle>>;
64
/** Get JSON value */
65
jsonValue(): Promise<any>;
66
/** Convert to ElementHandle if this is an element */
67
asElement(): ElementHandle | null;
68
/** Dispose the handle */
69
dispose(): Promise<void>;
70
/** Get execution context */
71
executionContext(): ExecutionContext;
72
/** Evaluate function with element as this */
73
evaluate<T>(pageFunction: Function, ...args: any[]): Promise<T>;
74
/** Evaluate function and return handle */
75
evaluateHandle(pageFunction: Function, ...args: any[]): Promise<JSHandle>;
76
/** Query selector within element */
77
$(selector: string): Promise<ElementHandle | null>;
78
/** Query selector all within element */
79
$$(selector: string): Promise<ElementHandle[]>;
80
/** Evaluate with selector within element */
81
$eval<T>(selector: string, pageFunction: Function, ...args: any[]): Promise<T>;
82
/** Evaluate with selector all within element */
83
$$eval<T>(selector: string, pageFunction: Function, ...args: any[]): Promise<T>;
84
/** XPath query within element */
85
$x(expression: string): Promise<ElementHandle[]>;
86
/** Wait for selector within element */
87
waitForSelector(selector: string, options?: WaitForSelectorOptions): Promise<ElementHandle | null>;
88
/** Wait for XPath within element */
89
waitForXPath(xpath: string, options?: WaitForSelectorOptions): Promise<ElementHandle | null>;
90
/** Wait for function */
91
waitForFunction(pageFunction: Function, options?: WaitForFunctionOptions, ...args: any[]): Promise<JSHandle>;
92
/** Check if element is visible */
93
isVisible(): Promise<boolean>;
94
/** Check if element is hidden */
95
isHidden(): Promise<boolean>;
96
/** Get owning frame */
97
ownerFrame(): Promise<Frame | null>;
98
/** Get remote object */
99
remoteObject(): Protocol.Runtime.RemoteObject;
100
}
101
102
interface ClickOptions {
103
/** Mouse button to use */
104
button?: "left" | "right" | "middle";
105
/** Number of clicks */
106
clickCount?: number;
107
/** Delay between mousedown and mouseup */
108
delay?: number;
109
/** Offset from element center */
110
offset?: { x: number; y: number };
111
/** Wait for element to be actionable */
112
force?: boolean;
113
/** Timeout for actionability checks */
114
timeout?: number;
115
/** Trial run without actually clicking */
116
trial?: boolean;
117
}
118
119
interface TypeOptions {
120
/** Delay between key presses */
121
delay?: number;
122
/** Timeout for actionability checks */
123
timeout?: number;
124
/** Whether to clear existing text first */
125
clear?: boolean;
126
}
127
128
interface PressOptions {
129
/** Delay between key down and up */
130
delay?: number;
131
/** Timeout for actionability checks */
132
timeout?: number;
133
}
134
135
interface BoundingBox {
136
x: number;
137
y: number;
138
width: number;
139
height: number;
140
}
141
142
interface BoxModel {
143
content: Quad;
144
padding: Quad;
145
border: Quad;
146
margin: Quad;
147
width: number;
148
height: number;
149
}
150
151
interface Quad {
152
p1: { x: number; y: number };
153
p2: { x: number; y: number };
154
p3: { x: number; y: number };
155
p4: { x: number; y: number };
156
}
157
158
interface ScrollOptions {
159
top?: number;
160
left?: number;
161
behavior?: "auto" | "instant" | "smooth";
162
}
163
164
interface DragAndDropOptions {
165
delay?: number;
166
force?: boolean;
167
timeout?: number;
168
}
169
170
interface WaitForSelectorOptions {
171
/** Wait for element to be visible */
172
visible?: boolean;
173
/** Wait for element to be hidden */
174
hidden?: boolean;
175
/** Maximum wait time */
176
timeout?: number;
177
/** Wait for element to be attached to DOM */
178
attached?: boolean;
179
/** Wait for element to be detached from DOM */
180
detached?: boolean;
181
}
182
183
interface WaitForFunctionOptions {
184
/** Maximum wait time */
185
timeout?: number;
186
/** Polling strategy */
187
polling?: "raf" | "mutation" | number;
188
}
189
```
190
191
**Usage Examples:**
192
193
```typescript
194
import puppeteer from "puppeteer-core";
195
196
const browser = await puppeteer.launch({ executablePath: "/path/to/chrome" });
197
const page = await browser.newPage();
198
await page.goto("https://example.com");
199
200
// Basic element selection and interaction
201
const button = await page.$("#submit-button");
202
if (button) {
203
await button.click();
204
}
205
206
const input = await page.$("input[type='text']");
207
if (input) {
208
await input.type("Hello World", { delay: 100 });
209
await input.press("Enter");
210
}
211
212
// Element properties and content
213
const heading = await page.$("h1");
214
if (heading) {
215
const text = await heading.innerText();
216
const html = await heading.innerHTML();
217
const id = await heading.getAttribute("id");
218
219
console.log("Heading text:", text);
220
console.log("Heading HTML:", html);
221
console.log("Heading ID:", id);
222
}
223
224
// Element positioning and visibility
225
const element = await page.$("#target-element");
226
if (element) {
227
const box = await element.boundingBox();
228
const isVisible = await element.isVisible();
229
const isInViewport = await element.isIntersectingViewport();
230
231
console.log("Element bounds:", box);
232
console.log("Element visible:", isVisible);
233
console.log("Element in viewport:", isInViewport);
234
}
235
236
// File upload
237
const fileInput = await page.$("input[type='file']");
238
if (fileInput) {
239
await fileInput.uploadFile("/path/to/file.txt", "/path/to/another-file.pdf");
240
}
241
242
// Select options
243
const selectElement = await page.$("select");
244
if (selectElement) {
245
const selectedValues = await selectElement.select("option1", "option2");
246
console.log("Selected values:", selectedValues);
247
}
248
249
await browser.close();
250
```
251
252
### JSHandle Interface
253
254
Base interface for JavaScript object references in the page context.
255
256
```typescript { .api }
257
interface JSHandle {
258
/** Evaluate function with handle as this */
259
evaluate<T>(pageFunction: Function, ...args: any[]): Promise<T>;
260
/** Evaluate function and return handle */
261
evaluateHandle(pageFunction: Function, ...args: any[]): Promise<JSHandle>;
262
/** Get property value */
263
getProperty(propertyName: string): Promise<JSHandle>;
264
/** Get all properties */
265
getProperties(): Promise<Map<string, JSHandle>>;
266
/** Get JSON value */
267
jsonValue(): Promise<any>;
268
/** Convert to ElementHandle if this is an element */
269
asElement(): ElementHandle | null;
270
/** Dispose the handle */
271
dispose(): Promise<void>;
272
/** Convert to string representation */
273
toString(): string;
274
/** Get execution context */
275
executionContext(): ExecutionContext;
276
/** Get remote object */
277
remoteObject(): Protocol.Runtime.RemoteObject;
278
}
279
```
280
281
**Usage Examples:**
282
283
```typescript
284
// Get JavaScript objects
285
const windowHandle = await page.evaluateHandle(() => window);
286
const documentHandle = await page.evaluateHandle(() => document);
287
288
// Get object properties
289
const locationHandle = await windowHandle.getProperty("location");
290
const href = await locationHandle.jsonValue();
291
292
// Evaluate with handle
293
const title = await documentHandle.evaluate((doc) => doc.title);
294
295
// Dispose handles to prevent memory leaks
296
await windowHandle.dispose();
297
await documentHandle.dispose();
298
await locationHandle.dispose();
299
```
300
301
### Element Selection Methods
302
303
Various methods for selecting elements in the page:
304
305
```typescript { .api }
306
interface ElementSelectionMethods {
307
/** Query single element by CSS selector */
308
$(selector: string): Promise<ElementHandle | null>;
309
/** Query multiple elements by CSS selector */
310
$$(selector: string): Promise<ElementHandle[]>;
311
/** Evaluate function with selected element */
312
$eval<T>(selector: string, pageFunction: Function, ...args: any[]): Promise<T>;
313
/** Evaluate function with all selected elements */
314
$$eval<T>(selector: string, pageFunction: Function, ...args: any[]): Promise<T>;
315
/** Query elements by XPath */
316
$x(expression: string): Promise<ElementHandle[]>;
317
}
318
```
319
320
**Usage Examples:**
321
322
```typescript
323
// CSS selectors
324
const header = await page.$("header");
325
const allButtons = await page.$$("button");
326
const navLinks = await page.$$("nav a");
327
328
// Evaluate with selected elements
329
const buttonTexts = await page.$$eval("button", (buttons) =>
330
buttons.map(btn => btn.textContent)
331
);
332
333
const firstLinkHref = await page.$eval("a", (link) => link.href);
334
335
// XPath selectors
336
const elementsWithText = await page.$x("//div[contains(text(), 'Hello')]");
337
const tableRows = await page.$x("//table//tr");
338
339
// Complex selectors
340
const specificElement = await page.$(
341
"div.container > section:nth-child(2) button[data-action='submit']"
342
);
343
```
344
345
### Advanced Element Operations
346
347
Complex element interactions and advanced features:
348
349
```typescript { .api }
350
interface AdvancedElementOperations {
351
/** Drag and drop operations */
352
dragAndDrop(source: ElementHandle, target: ElementHandle, options?: DragAndDropOptions): Promise<void>;
353
/** Scroll operations */
354
scroll(element: ElementHandle, options: ScrollOptions): Promise<void>;
355
/** Visibility checks */
356
isVisible(element: ElementHandle): Promise<boolean>;
357
isHidden(element: ElementHandle): Promise<boolean>;
358
/** Wait for element state changes */
359
waitForElementState(element: ElementHandle, state: "visible" | "hidden" | "stable"): Promise<void>;
360
}
361
```
362
363
**Usage Examples:**
364
365
```typescript
366
// Drag and drop
367
const draggable = await page.$("#draggable-item");
368
const dropZone = await page.$("#drop-zone");
369
370
if (draggable && dropZone) {
371
await draggable.dragAndDrop(dropZone, { delay: 100 });
372
}
373
374
// Scroll operations
375
const scrollableDiv = await page.$("#scrollable-content");
376
if (scrollableDiv) {
377
await scrollableDiv.scroll({ top: 100, behavior: "smooth" });
378
}
379
380
// Advanced waiting
381
const dynamicElement = await page.$("#dynamic-content");
382
if (dynamicElement) {
383
// Wait for element to become visible
384
await page.waitForFunction(
385
(el) => el.offsetHeight > 0,
386
{},
387
dynamicElement
388
);
389
}
390
391
// Element screenshots
392
const chart = await page.$("#sales-chart");
393
if (chart) {
394
await chart.screenshot({ path: "chart.png" });
395
}
396
```
397
398
### Frame Context
399
400
Working with elements in different frames:
401
402
```typescript { .api }
403
interface Frame {
404
/** Query selector in frame */
405
$(selector: string): Promise<ElementHandle | null>;
406
/** Query selector all in frame */
407
$$(selector: string): Promise<ElementHandle[]>;
408
/** Evaluate with selector in frame */
409
$eval<T>(selector: string, pageFunction: Function, ...args: any[]): Promise<T>;
410
/** Evaluate with selector all in frame */
411
$$eval<T>(selector: string, pageFunction: Function, ...args: any[]): Promise<T>;
412
/** XPath query in frame */
413
$x(expression: string): Promise<ElementHandle[]>;
414
/** Wait for selector in frame */
415
waitForSelector(selector: string, options?: WaitForSelectorOptions): Promise<ElementHandle | null>;
416
/** Get frame name */
417
name(): string;
418
/** Get frame URL */
419
url(): string;
420
/** Get parent frame */
421
parentFrame(): Frame | null;
422
/** Get child frames */
423
childFrames(): Frame[];
424
/** Check if frame detached */
425
isDetached(): boolean;
426
/** Get execution context */
427
executionContext(): Promise<ExecutionContext>;
428
/** Evaluate in frame */
429
evaluate<T>(pageFunction: Function, ...args: any[]): Promise<T>;
430
/** Evaluate and return handle in frame */
431
evaluateHandle<T>(pageFunction: Function, ...args: any[]): Promise<JSHandle<T>>;
432
/** Click in frame */
433
click(selector: string, options?: ClickOptions): Promise<void>;
434
/** Focus in frame */
435
focus(selector: string): Promise<void>;
436
/** Hover in frame */
437
hover(selector: string): Promise<void>;
438
/** Select in frame */
439
select(selector: string, ...values: string[]): Promise<string[]>;
440
/** Tap in frame */
441
tap(selector: string): Promise<void>;
442
/** Type in frame */
443
type(selector: string, text: string, options?: TypeOptions): Promise<void>;
444
}
445
```
446
447
**Usage Examples:**
448
449
```typescript
450
// Working with iframes
451
const frames = page.frames();
452
const iframe = frames.find(frame => frame.name() === "content-frame");
453
454
if (iframe) {
455
// Select elements within iframe
456
const iframeButton = await iframe.$("#iframe-button");
457
if (iframeButton) {
458
await iframeButton.click();
459
}
460
461
// Evaluate within iframe
462
const iframeTitle = await iframe.evaluate(() => document.title);
463
console.log("Iframe title:", iframeTitle);
464
}
465
466
// Handle nested frames
467
const childFrames = iframe?.childFrames() || [];
468
for (const childFrame of childFrames) {
469
const childContent = await childFrame.$eval("body", (body) => body.textContent);
470
console.log("Child frame content:", childContent);
471
}
472
```
473
474
### Error Handling
475
476
Common errors when working with elements:
477
478
```typescript { .api }
479
class TimeoutError extends Error {
480
constructor(message: string);
481
}
482
483
class ElementHandleError extends Error {
484
constructor(message: string);
485
}
486
```
487
488
**Usage Examples:**
489
490
```typescript
491
try {
492
// Element might not exist
493
const element = await page.waitForSelector("#dynamic-element", {
494
timeout: 5000
495
});
496
497
if (element) {
498
await element.click();
499
}
500
} catch (error) {
501
if (error instanceof TimeoutError) {
502
console.log("Element did not appear within timeout");
503
} else {
504
console.log("Unexpected error:", error.message);
505
}
506
}
507
508
// Safe element operations
509
async function safeClick(page: Page, selector: string) {
510
try {
511
const element = await page.$(selector);
512
if (element) {
513
const isVisible = await element.isVisible();
514
if (isVisible) {
515
await element.click();
516
return true;
517
}
518
}
519
} catch (error) {
520
console.log(`Failed to click ${selector}:`, error.message);
521
}
522
return false;
523
}
524
525
// Usage
526
const success = await safeClick(page, "#submit-button");
527
if (!success) {
528
console.log("Could not click submit button");
529
}
530
```