UNPKG

97.5 kBPlain TextView Raw
1/**
2 * @license
3 * Copyright 2017 Google Inc.
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7import type {Protocol} from 'devtools-protocol';
8
9import {
10 concat,
11 EMPTY,
12 filter,
13 first,
14 firstValueFrom,
15 from,
16 map,
17 merge,
18 mergeMap,
19 mergeScan,
20 of,
21 raceWith,
22 ReplaySubject,
23 startWith,
24 switchMap,
25 take,
26 takeUntil,
27 timer,
28 type Observable,
29} from '../../third_party/rxjs/rxjs.js';
30import type {HTTPRequest} from '../api/HTTPRequest.js';
31import type {HTTPResponse} from '../api/HTTPResponse.js';
32import type {Accessibility} from '../cdp/Accessibility.js';
33import type {Coverage} from '../cdp/Coverage.js';
34import type {DeviceRequestPrompt} from '../cdp/DeviceRequestPrompt.js';
35import type {NetworkConditions} from '../cdp/NetworkManager.js';
36import type {Tracing} from '../cdp/Tracing.js';
37import type {ConsoleMessage} from '../common/ConsoleMessage.js';
38import type {
39 Cookie,
40 CookieParam,
41 DeleteCookiesRequest,
42} from '../common/Cookie.js';
43import type {Device} from '../common/Device.js';
44import {TargetCloseError} from '../common/Errors.js';
45import {
46 EventEmitter,
47 type EventsWithWildcard,
48 type EventType,
49 type Handler,
50} from '../common/EventEmitter.js';
51import type {FileChooser} from '../common/FileChooser.js';
52import type {PDFOptions} from '../common/PDFOptions.js';
53import {TimeoutSettings} from '../common/TimeoutSettings.js';
54import type {
55 Awaitable,
56 AwaitablePredicate,
57 EvaluateFunc,
58 EvaluateFuncWith,
59 HandleFor,
60 NodeFor,
61} from '../common/types.js';
62import {
63 debugError,
64 fromEmitterEvent,
65 filterAsync,
66 isString,
67 NETWORK_IDLE_TIME,
68 timeout,
69 withSourcePuppeteerURLIfNone,
70 fromAbortSignal,
71} from '../common/util.js';
72import type {Viewport} from '../common/Viewport.js';
73import {environment} from '../environment.js';
74import type {ScreenRecorder} from '../node/ScreenRecorder.js';
75import {guarded} from '../util/decorators.js';
76import {
77 AsyncDisposableStack,
78 asyncDisposeSymbol,
79 DisposableStack,
80 disposeSymbol,
81} from '../util/disposable.js';
82import {stringToTypedArray} from '../util/encoding.js';
83
84import type {Browser} from './Browser.js';
85import type {BrowserContext} from './BrowserContext.js';
86import type {CDPSession} from './CDPSession.js';
87import type {Dialog} from './Dialog.js';
88import type {
89 BoundingBox,
90 ClickOptions,
91 ElementHandle,
92} from './ElementHandle.js';
93import type {
94 Frame,
95 FrameAddScriptTagOptions,
96 FrameAddStyleTagOptions,
97 FrameWaitForFunctionOptions,
98 GoToOptions,
99 WaitForOptions,
100} from './Frame.js';
101import type {
102 Keyboard,
103 KeyboardTypeOptions,
104 Mouse,
105 Touchscreen,
106} from './Input.js';
107import type {JSHandle} from './JSHandle.js';
108import {
109 FunctionLocator,
110 Locator,
111 NodeLocator,
112 type AwaitedLocator,
113} from './locators/locators.js';
114import type {Target} from './Target.js';
115import type {WebWorker} from './WebWorker.js';
116
117/**
118 * @public
119 */
120export interface Metrics {
121 Timestamp?: number;
122 Documents?: number;
123 Frames?: number;
124 JSEventListeners?: number;
125 Nodes?: number;
126 LayoutCount?: number;
127 RecalcStyleCount?: number;
128 LayoutDuration?: number;
129 RecalcStyleDuration?: number;
130 ScriptDuration?: number;
131 TaskDuration?: number;
132 JSHeapUsedSize?: number;
133 JSHeapTotalSize?: number;
134}
135
136/**
137 * @public
138 */
139export interface Credentials {
140 username: string;
141 password: string;
142}
143
144/**
145 * @public
146 */
147export interface WaitForNetworkIdleOptions extends WaitTimeoutOptions {
148 /**
149 * Time (in milliseconds) the network should be idle.
150 *
151 * @defaultValue `500`
152 */
153 idleTime?: number;
154 /**
155 * Maximum number concurrent of network connections to be considered inactive.
156 *
157 * @defaultValue `0`
158 */
159 concurrency?: number;
160}
161
162/**
163 * @public
164 */
165export interface WaitTimeoutOptions {
166 /**
167 * Maximum wait time in milliseconds. Pass 0 to disable the timeout.
168 *
169 * The default value can be changed by using the
170 * {@link Page.setDefaultTimeout} method.
171 *
172 * @defaultValue `30_000`
173 */
174 timeout?: number;
175 /**
176 * A signal object that allows you to cancel a waitFor call.
177 */
178 signal?: AbortSignal;
179}
180
181/**
182 * @public
183 */
184export interface WaitForSelectorOptions {
185 /**
186 * Wait for the selected element to be present in DOM and to be visible. See
187 * {@link ElementHandle.isVisible} for the definition of element visibility.
188 *
189 * @defaultValue `false`
190 */
191 visible?: boolean;
192 /**
193 * Wait for the selected element to not be found in the DOM or to be hidden.
194 * See {@link ElementHandle.isHidden} for the definition of element
195 * invisibility.
196 *
197 * @defaultValue `false`
198 */
199 hidden?: boolean;
200 /**
201 * Maximum time to wait in milliseconds. Pass `0` to disable timeout.
202 *
203 * The default value can be changed by using {@link Page.setDefaultTimeout}
204 *
205 * @defaultValue `30_000` (30 seconds)
206 */
207 timeout?: number;
208 /**
209 * A signal object that allows you to cancel a waitForSelector call.
210 */
211 signal?: AbortSignal;
212}
213
214/**
215 * @public
216 */
217export interface GeolocationOptions {
218 /**
219 * Latitude between `-90` and `90`.
220 */
221 longitude: number;
222 /**
223 * Longitude between `-180` and `180`.
224 */
225 latitude: number;
226 /**
227 * Optional non-negative accuracy value.
228 */
229 accuracy?: number;
230}
231
232/**
233 * A media feature to emulate.
234 *
235 * @public
236 */
237export interface MediaFeature {
238 /**
239 * A name of the feature, for example, 'prefers-reduced-motion'.
240 */
241 name: string;
242 /**
243 * A value for the feature, for example, 'reduce'.
244 */
245 value: string;
246}
247
248/**
249 * @public
250 */
251export interface ScreenshotClip extends BoundingBox {
252 /**
253 * @defaultValue `1`
254 */
255 scale?: number;
256}
257
258/**
259 * @public
260 */
261export interface ScreenshotOptions {
262 /**
263 * @defaultValue `false`
264 */
265 optimizeForSpeed?: boolean;
266 /**
267 * @defaultValue `'png'`
268 */
269 type?: 'png' | 'jpeg' | 'webp';
270 /**
271 * Quality of the image, between 0-100. Not applicable to `png` images.
272 */
273 quality?: number;
274 /**
275 * Capture the screenshot from the surface, rather than the view.
276 *
277 * @defaultValue `true`
278 */
279 fromSurface?: boolean;
280 /**
281 * When `true`, takes a screenshot of the full page.
282 *
283 * @defaultValue `false`
284 */
285 fullPage?: boolean;
286 /**
287 * Hides default white background and allows capturing screenshots with transparency.
288 *
289 * @defaultValue `false`
290 */
291 omitBackground?: boolean;
292 /**
293 * The file path to save the image to. The screenshot type will be inferred
294 * from file extension. If path is a relative path, then it is resolved
295 * relative to current working directory. If no path is provided, the image
296 * won't be saved to the disk.
297 */
298 path?: string;
299 /**
300 * Specifies the region of the page/element to clip.
301 */
302 clip?: ScreenshotClip;
303 /**
304 * Encoding of the image.
305 *
306 * @defaultValue `'binary'`
307 */
308 encoding?: 'base64' | 'binary';
309 /**
310 * Capture the screenshot beyond the viewport.
311 *
312 * @defaultValue `false` if there is no `clip`. `true` otherwise.
313 */
314 captureBeyondViewport?: boolean;
315}
316
317/**
318 * @public
319 * @experimental
320 */
321export interface ScreencastOptions {
322 /**
323 * File path to save the screencast to.
324 */
325 path?: `${string}.webm`;
326 /**
327 * Specifies the region of the viewport to crop.
328 */
329 crop?: BoundingBox;
330 /**
331 * Scales the output video.
332 *
333 * For example, `0.5` will shrink the width and height of the output video by
334 * half. `2` will double the width and height of the output video.
335 *
336 * @defaultValue `1`
337 */
338 scale?: number;
339 /**
340 * Specifies the speed to record at.
341 *
342 * For example, `0.5` will slowdown the output video by 50%. `2` will double the
343 * speed of the output video.
344 *
345 * @defaultValue `1`
346 */
347 speed?: number;
348 /**
349 * Path to the {@link https://ffmpeg.org/ | ffmpeg}.
350 *
351 * Required if `ffmpeg` is not in your PATH.
352 */
353 ffmpegPath?: string;
354}
355
356/**
357 * @public
358 */
359export interface QueryOptions {
360 /**
361 * Whether to run the query in isolation. When returning many elements
362 * from {@link Page.$$} or similar methods, it might be useful to turn
363 * off the isolation to improve performance. By default, the querying
364 * code will be executed in a separate sandbox realm.
365 *
366 * @defaultValue `true`
367 */
368 isolate: boolean;
369}
370
371/**
372 * All the events that a page instance may emit.
373 *
374 * @public
375 */
376export const enum PageEvent {
377 /**
378 * Emitted when the page closes.
379 */
380 Close = 'close',
381 /**
382 * Emitted when JavaScript within the page calls one of console API methods,
383 * e.g. `console.log` or `console.dir`. Also emitted if the page throws an
384 * error or a warning.
385 *
386 * @remarks
387 * A `console` event provides a {@link ConsoleMessage} representing the
388 * console message that was logged.
389 *
390 * @example
391 * An example of handling `console` event:
392 *
393 * ```ts
394 * page.on('console', msg => {
395 * for (let i = 0; i < msg.args().length; ++i)
396 * console.log(`${i}: ${msg.args()[i]}`);
397 * });
398 * page.evaluate(() => console.log('hello', 5, {foo: 'bar'}));
399 * ```
400 */
401 Console = 'console',
402 /**
403 * Emitted when a JavaScript dialog appears, such as `alert`, `prompt`,
404 * `confirm` or `beforeunload`. Puppeteer can respond to the dialog via
405 * {@link Dialog.accept} or {@link Dialog.dismiss}.
406 */
407 Dialog = 'dialog',
408 /**
409 * Emitted when the JavaScript
410 * {@link https://developer.mozilla.org/en-US/docs/Web/Events/DOMContentLoaded | DOMContentLoaded }
411 * event is dispatched.
412 */
413 DOMContentLoaded = 'domcontentloaded',
414 /**
415 * Emitted when the page crashes. Will contain an `Error`.
416 */
417 Error = 'error',
418 /** Emitted when a frame is attached. Will contain a {@link Frame}. */
419 FrameAttached = 'frameattached',
420 /** Emitted when a frame is detached. Will contain a {@link Frame}. */
421 FrameDetached = 'framedetached',
422 /**
423 * Emitted when a frame is navigated to a new URL. Will contain a
424 * {@link Frame}.
425 */
426 FrameNavigated = 'framenavigated',
427 /**
428 * Emitted when the JavaScript
429 * {@link https://developer.mozilla.org/en-US/docs/Web/Events/load | load}
430 * event is dispatched.
431 */
432 Load = 'load',
433 /**
434 * Emitted when the JavaScript code makes a call to `console.timeStamp`. For
435 * the list of metrics see {@link Page.metrics | page.metrics}.
436 *
437 * @remarks
438 * Contains an object with two properties:
439 *
440 * - `title`: the title passed to `console.timeStamp`
441 * - `metrics`: object containing metrics as key/value pairs. The values will
442 * be `number`s.
443 */
444 Metrics = 'metrics',
445 /**
446 * Emitted when an uncaught exception happens within the page. Contains an
447 * `Error`.
448 */
449 PageError = 'pageerror',
450 /**
451 * Emitted when the page opens a new tab or window.
452 *
453 * Contains a {@link Page} corresponding to the popup window.
454 *
455 * @example
456 *
457 * ```ts
458 * const [popup] = await Promise.all([
459 * new Promise(resolve => page.once('popup', resolve)),
460 * page.click('a[target=_blank]'),
461 * ]);
462 * ```
463 *
464 * ```ts
465 * const [popup] = await Promise.all([
466 * new Promise(resolve => page.once('popup', resolve)),
467 * page.evaluate(() => window.open('https://example.com')),
468 * ]);
469 * ```
470 */
471 Popup = 'popup',
472 /**
473 * Emitted when a page issues a request and contains a {@link HTTPRequest}.
474 *
475 * @remarks
476 * The object is readonly. See {@link Page.setRequestInterception} for
477 * intercepting and mutating requests.
478 */
479 Request = 'request',
480 /**
481 * Emitted when a request ended up loading from cache. Contains a
482 * {@link HTTPRequest}.
483 *
484 * @remarks
485 * For certain requests, might contain undefined.
486 * {@link https://crbug.com/750469}
487 */
488 RequestServedFromCache = 'requestservedfromcache',
489 /**
490 * Emitted when a request fails, for example by timing out.
491 *
492 * Contains a {@link HTTPRequest}.
493 *
494 * @remarks
495 * HTTP Error responses, such as 404 or 503, are still successful responses
496 * from HTTP standpoint, so request will complete with `requestfinished` event
497 * and not with `requestfailed`.
498 */
499 RequestFailed = 'requestfailed',
500 /**
501 * Emitted when a request finishes successfully. Contains a
502 * {@link HTTPRequest}.
503 */
504 RequestFinished = 'requestfinished',
505 /**
506 * Emitted when a response is received. Contains a {@link HTTPResponse}.
507 */
508 Response = 'response',
509 /**
510 * Emitted when a dedicated
511 * {@link https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API | WebWorker}
512 * is spawned by the page.
513 */
514 WorkerCreated = 'workercreated',
515 /**
516 * Emitted when a dedicated
517 * {@link https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API | WebWorker}
518 * is destroyed by the page.
519 */
520 WorkerDestroyed = 'workerdestroyed',
521}
522
523/**
524 * Denotes the objects received by callback functions for page events.
525 *
526 * See {@link PageEvent} for more detail on the events and when they are
527 * emitted.
528 *
529 * @public
530 */
531export interface PageEvents extends Record<EventType, unknown> {
532 [PageEvent.Close]: undefined;
533 [PageEvent.Console]: ConsoleMessage;
534 [PageEvent.Dialog]: Dialog;
535 [PageEvent.DOMContentLoaded]: undefined;
536 [PageEvent.Error]: Error;
537 [PageEvent.FrameAttached]: Frame;
538 [PageEvent.FrameDetached]: Frame;
539 [PageEvent.FrameNavigated]: Frame;
540 [PageEvent.Load]: undefined;
541 [PageEvent.Metrics]: {title: string; metrics: Metrics};
542 [PageEvent.PageError]: Error;
543 [PageEvent.Popup]: Page | null;
544 [PageEvent.Request]: HTTPRequest;
545 [PageEvent.Response]: HTTPResponse;
546 [PageEvent.RequestFailed]: HTTPRequest;
547 [PageEvent.RequestFinished]: HTTPRequest;
548 [PageEvent.RequestServedFromCache]: HTTPRequest;
549 [PageEvent.WorkerCreated]: WebWorker;
550 [PageEvent.WorkerDestroyed]: WebWorker;
551}
552
553/**
554 * @public
555 */
556export interface NewDocumentScriptEvaluation {
557 identifier: string;
558}
559
560/**
561 * @internal
562 */
563export function setDefaultScreenshotOptions(options: ScreenshotOptions): void {
564 options.optimizeForSpeed ??= false;
565 options.type ??= 'png';
566 options.fromSurface ??= true;
567 options.fullPage ??= false;
568 options.omitBackground ??= false;
569 options.encoding ??= 'binary';
570 options.captureBeyondViewport ??= true;
571}
572
573/**
574 * Page provides methods to interact with a single tab or
575 * {@link https://developer.chrome.com/extensions/background_pages | extension background page}
576 * in the browser.
577 *
578 * :::note
579 *
580 * One Browser instance might have multiple Page instances.
581 *
582 * :::
583 *
584 * @example
585 * This example creates a page, navigates it to a URL, and then saves a screenshot:
586 *
587 * ```ts
588 * import puppeteer from 'puppeteer';
589 *
590 * (async () => {
591 * const browser = await puppeteer.launch();
592 * const page = await browser.newPage();
593 * await page.goto('https://example.com');
594 * await page.screenshot({path: 'screenshot.png'});
595 * await browser.close();
596 * })();
597 * ```
598 *
599 * The Page class extends from Puppeteer's {@link EventEmitter} class and will
600 * emit various events which are documented in the {@link PageEvent} enum.
601 *
602 * @example
603 * This example logs a message for a single page `load` event:
604 *
605 * ```ts
606 * page.once('load', () => console.log('Page loaded!'));
607 * ```
608 *
609 * To unsubscribe from events use the {@link EventEmitter.off} method:
610 *
611 * ```ts
612 * function logRequest(interceptedRequest) {
613 * console.log('A request was made:', interceptedRequest.url());
614 * }
615 * page.on('request', logRequest);
616 * // Sometime later...
617 * page.off('request', logRequest);
618 * ```
619 *
620 * @public
621 */
622export abstract class Page extends EventEmitter<PageEvents> {
623 /**
624 * @internal
625 */
626 _isDragging = false;
627 /**
628 * @internal
629 */
630 _timeoutSettings = new TimeoutSettings();
631
632 #requestHandlers = new WeakMap<Handler<HTTPRequest>, Handler<HTTPRequest>>();
633
634 #inflight$ = new ReplaySubject<number>(1);
635
636 /**
637 * @internal
638 */
639 constructor() {
640 super();
641
642 fromEmitterEvent(this, PageEvent.Request)
643 .pipe(
644 mergeMap(originalRequest => {
645 return concat(
646 of(1),
647 merge(
648 fromEmitterEvent(this, PageEvent.RequestFailed),
649 fromEmitterEvent(this, PageEvent.RequestFinished),
650 fromEmitterEvent(this, PageEvent.Response).pipe(
651 map(response => {
652 return response.request();
653 }),
654 ),
655 ).pipe(
656 filter(request => {
657 return request.id === originalRequest.id;
658 }),
659 take(1),
660 map(() => {
661 return -1;
662 }),
663 ),
664 );
665 }),
666 mergeScan((acc, addend) => {
667 return of(acc + addend);
668 }, 0),
669 takeUntil(fromEmitterEvent(this, PageEvent.Close)),
670 startWith(0),
671 )
672 .subscribe(this.#inflight$);
673 }
674
675 /**
676 * `true` if the service worker are being bypassed, `false` otherwise.
677 */
678 abstract isServiceWorkerBypassed(): boolean;
679
680 /**
681 * `true` if drag events are being intercepted, `false` otherwise.
682 *
683 * @deprecated We no longer support intercepting drag payloads. Use the new
684 * drag APIs found on {@link ElementHandle} to drag (or just use the
685 * {@link Page.mouse}).
686 */
687 abstract isDragInterceptionEnabled(): boolean;
688
689 /**
690 * `true` if the page has JavaScript enabled, `false` otherwise.
691 */
692 abstract isJavaScriptEnabled(): boolean;
693
694 /**
695 * Listen to page events.
696 *
697 * @remarks
698 * This method exists to define event typings and handle proper wireup of
699 * cooperative request interception. Actual event listening and dispatching is
700 * delegated to {@link EventEmitter}.
701 *
702 * @internal
703 */
704 override on<K extends keyof EventsWithWildcard<PageEvents>>(
705 type: K,
706 handler: (event: EventsWithWildcard<PageEvents>[K]) => void,
707 ): this {
708 if (type !== PageEvent.Request) {
709 return super.on(type, handler);
710 }
711 let wrapper = this.#requestHandlers.get(
712 handler as (event: PageEvents[PageEvent.Request]) => void,
713 );
714 if (wrapper === undefined) {
715 wrapper = (event: HTTPRequest) => {
716 event.enqueueInterceptAction(() => {
717 return handler(event as EventsWithWildcard<PageEvents>[K]);
718 });
719 };
720 this.#requestHandlers.set(
721 handler as (event: PageEvents[PageEvent.Request]) => void,
722 wrapper,
723 );
724 }
725 return super.on(
726 type,
727 wrapper as (event: EventsWithWildcard<PageEvents>[K]) => void,
728 );
729 }
730
731 /**
732 * @internal
733 */
734 override off<K extends keyof EventsWithWildcard<PageEvents>>(
735 type: K,
736 handler: (event: EventsWithWildcard<PageEvents>[K]) => void,
737 ): this {
738 if (type === PageEvent.Request) {
739 handler =
740 (this.#requestHandlers.get(
741 handler as (
742 event: EventsWithWildcard<PageEvents>[PageEvent.Request],
743 ) => void,
744 ) as (event: EventsWithWildcard<PageEvents>[K]) => void) || handler;
745 }
746 return super.off(type, handler);
747 }
748
749 /**
750 * This method is typically coupled with an action that triggers file
751 * choosing.
752 *
753 * :::caution
754 *
755 * This must be called before the file chooser is launched. It will not return
756 * a currently active file chooser.
757 *
758 * :::
759 *
760 * :::caution
761 *
762 * Interception of file dialogs triggered via DOM APIs such as
763 * window.showOpenFilePicker is currently not supported.
764 *
765 * :::
766 *
767 * @remarks
768 * In the "headful" browser, this method results in the native file picker
769 * dialog `not showing up` for the user.
770 *
771 * @example
772 * The following example clicks a button that issues a file chooser
773 * and then responds with `/tmp/myfile.pdf` as if a user has selected this file.
774 *
775 * ```ts
776 * const [fileChooser] = await Promise.all([
777 * page.waitForFileChooser(),
778 * page.click('#upload-file-button'),
779 * // some button that triggers file selection
780 * ]);
781 * await fileChooser.accept(['/tmp/myfile.pdf']);
782 * ```
783 */
784 abstract waitForFileChooser(
785 options?: WaitTimeoutOptions,
786 ): Promise<FileChooser>;
787
788 /**
789 * Sets the page's geolocation.
790 *
791 * @remarks
792 * Consider using {@link BrowserContext.overridePermissions} to grant
793 * permissions for the page to read its geolocation.
794 *
795 * @example
796 *
797 * ```ts
798 * await page.setGeolocation({latitude: 59.95, longitude: 30.31667});
799 * ```
800 */
801 abstract setGeolocation(options: GeolocationOptions): Promise<void>;
802
803 /**
804 * A target this page was created from.
805 *
806 * @deprecated Use {@link Page.createCDPSession} directly.
807 */
808 abstract target(): Target;
809
810 /**
811 * Get the browser the page belongs to.
812 */
813 abstract browser(): Browser;
814
815 /**
816 * Get the browser context that the page belongs to.
817 */
818 abstract browserContext(): BrowserContext;
819
820 /**
821 * The page's main frame.
822 */
823 abstract mainFrame(): Frame;
824
825 /**
826 * Creates a Chrome Devtools Protocol session attached to the page.
827 */
828 abstract createCDPSession(): Promise<CDPSession>;
829
830 /**
831 * {@inheritDoc Keyboard}
832 */
833 abstract get keyboard(): Keyboard;
834
835 /**
836 * {@inheritDoc Touchscreen}
837 */
838 abstract get touchscreen(): Touchscreen;
839
840 /**
841 * {@inheritDoc Coverage}
842 */
843 abstract get coverage(): Coverage;
844
845 /**
846 * {@inheritDoc Tracing}
847 */
848 abstract get tracing(): Tracing;
849
850 /**
851 * {@inheritDoc Accessibility}
852 */
853 get accessibility(): Accessibility {
854 return this.mainFrame().accessibility;
855 }
856
857 /**
858 * An array of all frames attached to the page.
859 */
860 abstract frames(): Frame[];
861
862 /**
863 * All of the dedicated {@link
864 * https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API |
865 * WebWorkers} associated with the page.
866 *
867 * @remarks
868 * This does not contain ServiceWorkers
869 */
870 abstract workers(): WebWorker[];
871
872 /**
873 * Activating request interception enables {@link HTTPRequest.abort},
874 * {@link HTTPRequest.continue} and {@link HTTPRequest.respond} methods. This
875 * provides the capability to modify network requests that are made by a page.
876 *
877 * Once request interception is enabled, every request will stall unless it's
878 * continued, responded or aborted; or completed using the browser cache.
879 *
880 * See the
881 * {@link https://pptr.dev/guides/network-interception|Request interception guide}
882 * for more details.
883 *
884 * @example
885 * An example of a naïve request interceptor that aborts all image requests:
886 *
887 * ```ts
888 * import puppeteer from 'puppeteer';
889 * (async () => {
890 * const browser = await puppeteer.launch();
891 * const page = await browser.newPage();
892 * await page.setRequestInterception(true);
893 * page.on('request', interceptedRequest => {
894 * if (
895 * interceptedRequest.url().endsWith('.png') ||
896 * interceptedRequest.url().endsWith('.jpg')
897 * )
898 * interceptedRequest.abort();
899 * else interceptedRequest.continue();
900 * });
901 * await page.goto('https://example.com');
902 * await browser.close();
903 * })();
904 * ```
905 *
906 * @param value - Whether to enable request interception.
907 */
908 abstract setRequestInterception(value: boolean): Promise<void>;
909
910 /**
911 * Toggles ignoring of service worker for each request.
912 *
913 * @param bypass - Whether to bypass service worker and load from network.
914 */
915 abstract setBypassServiceWorker(bypass: boolean): Promise<void>;
916
917 /**
918 * @param enabled - Whether to enable drag interception.
919 *
920 * @deprecated We no longer support intercepting drag payloads. Use the new
921 * drag APIs found on {@link ElementHandle} to drag (or just use the
922 * {@link Page.mouse}).
923 */
924 abstract setDragInterception(enabled: boolean): Promise<void>;
925
926 /**
927 * Sets the network connection to offline.
928 *
929 * It does not change the parameters used in {@link Page.emulateNetworkConditions}
930 *
931 * @param enabled - When `true`, enables offline mode for the page.
932 */
933 abstract setOfflineMode(enabled: boolean): Promise<void>;
934
935 /**
936 * This does not affect WebSockets and WebRTC PeerConnections (see
937 * https://crbug.com/563644). To set the page offline, you can use
938 * {@link Page.setOfflineMode}.
939 *
940 * A list of predefined network conditions can be used by importing
941 * {@link PredefinedNetworkConditions}.
942 *
943 * @example
944 *
945 * ```ts
946 * import {PredefinedNetworkConditions} from 'puppeteer';
947 * const slow3G = PredefinedNetworkConditions['Slow 3G'];
948 *
949 * (async () => {
950 * const browser = await puppeteer.launch();
951 * const page = await browser.newPage();
952 * await page.emulateNetworkConditions(slow3G);
953 * await page.goto('https://www.google.com');
954 * // other actions...
955 * await browser.close();
956 * })();
957 * ```
958 *
959 * @param networkConditions - Passing `null` disables network condition
960 * emulation.
961 */
962 abstract emulateNetworkConditions(
963 networkConditions: NetworkConditions | null,
964 ): Promise<void>;
965
966 /**
967 * This setting will change the default maximum navigation time for the
968 * following methods and related shortcuts:
969 *
970 * - {@link Page.goBack | page.goBack(options)}
971 *
972 * - {@link Page.goForward | page.goForward(options)}
973 *
974 * - {@link Page.goto | page.goto(url,options)}
975 *
976 * - {@link Page.reload | page.reload(options)}
977 *
978 * - {@link Page.setContent | page.setContent(html,options)}
979 *
980 * - {@link Page.waitForNavigation | page.waitForNavigation(options)}
981 * @param timeout - Maximum navigation time in milliseconds.
982 */
983 abstract setDefaultNavigationTimeout(timeout: number): void;
984
985 /**
986 * @param timeout - Maximum time in milliseconds.
987 */
988 abstract setDefaultTimeout(timeout: number): void;
989
990 /**
991 * Maximum time in milliseconds.
992 */
993 abstract getDefaultTimeout(): number;
994
995 /**
996 * Maximum navigation time in milliseconds.
997 */
998 abstract getDefaultNavigationTimeout(): number;
999
1000 /**
1001 * Creates a locator for the provided selector. See {@link Locator} for
1002 * details and supported actions.
1003 *
1004 * @param selector -
1005 * {@link https://pptr.dev/guides/page-interactions#selectors | selector}
1006 * to query the page for.
1007 * {@link https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors | CSS selectors}
1008 * can be passed as-is and a
1009 * {@link https://pptr.dev/guides/page-interactions#non-css-selectors | Puppeteer-specific selector syntax}
1010 * allows quering by
1011 * {@link https://pptr.dev/guides/page-interactions#text-selectors--p-text | text},
1012 * {@link https://pptr.dev/guides/page-interactions#aria-selectors--p-aria | a11y role and name},
1013 * and
1014 * {@link https://pptr.dev/guides/page-interactions#xpath-selectors--p-xpath | xpath}
1015 * and
1016 * {@link https://pptr.dev/guides/page-interactions#querying-elements-in-shadow-dom | combining these queries across shadow roots}.
1017 * Alternatively, you can specify the selector type using a
1018 * {@link https://pptr.dev/guides/page-interactions#prefixed-selector-syntax | prefix}.
1019 */
1020 locator<Selector extends string>(
1021 selector: Selector,
1022 ): Locator<NodeFor<Selector>>;
1023
1024 /**
1025 * Creates a locator for the provided function. See {@link Locator} for
1026 * details and supported actions.
1027 *
1028 * @param selector -
1029 * {@link https://pptr.dev/guides/page-interactions#selectors | selector}
1030 * to query the page for.
1031 * {@link https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors | CSS selectors}
1032 * can be passed as-is and a
1033 * {@link https://pptr.dev/guides/page-interactions#non-css-selectors | Puppeteer-specific selector syntax}
1034 * allows quering by
1035 * {@link https://pptr.dev/guides/page-interactions#text-selectors--p-text | text},
1036 * {@link https://pptr.dev/guides/page-interactions#aria-selectors--p-aria | a11y role and name},
1037 * and
1038 * {@link https://pptr.dev/guides/page-interactions#xpath-selectors--p-xpath | xpath}
1039 * and
1040 * {@link https://pptr.dev/guides/page-interactions#querying-elements-in-shadow-dom | combining these queries across shadow roots}.
1041 * Alternatively, you can specify the selector type using a
1042 * {@link https://pptr.dev/guides/page-interactions#prefixed-selector-syntax | prefix}.
1043 */
1044 locator<Ret>(func: () => Awaitable<Ret>): Locator<Ret>;
1045 locator<Selector extends string, Ret>(
1046 selectorOrFunc: Selector | (() => Awaitable<Ret>),
1047 ): Locator<NodeFor<Selector>> | Locator<Ret> {
1048 if (typeof selectorOrFunc === 'string') {
1049 return NodeLocator.create(this, selectorOrFunc);
1050 } else {
1051 return FunctionLocator.create(this, selectorOrFunc);
1052 }
1053 }
1054
1055 /**
1056 * A shortcut for {@link Locator.race} that does not require static imports.
1057 *
1058 * @internal
1059 */
1060 locatorRace<Locators extends readonly unknown[] | []>(
1061 locators: Locators,
1062 ): Locator<AwaitedLocator<Locators[number]>> {
1063 return Locator.race(locators);
1064 }
1065
1066 /**
1067 * Finds the first element that matches the selector. If no element matches
1068 * the selector, the return value resolves to `null`.
1069 *
1070 * @param selector -
1071 * {@link https://pptr.dev/guides/page-interactions#selectors | selector}
1072 * to query the page for.
1073 * {@link https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors | CSS selectors}
1074 * can be passed as-is and a
1075 * {@link https://pptr.dev/guides/page-interactions#non-css-selectors | Puppeteer-specific selector syntax}
1076 * allows quering by
1077 * {@link https://pptr.dev/guides/page-interactions#text-selectors--p-text | text},
1078 * {@link https://pptr.dev/guides/page-interactions#aria-selectors--p-aria | a11y role and name},
1079 * and
1080 * {@link https://pptr.dev/guides/page-interactions#xpath-selectors--p-xpath | xpath}
1081 * and
1082 * {@link https://pptr.dev/guides/page-interactions#querying-elements-in-shadow-dom | combining these queries across shadow roots}.
1083 * Alternatively, you can specify the selector type using a
1084 * {@link https://pptr.dev/guides/page-interactions#prefixed-selector-syntax | prefix}.
1085 *
1086 * @remarks
1087 *
1088 * Shortcut for {@link Frame.$ | Page.mainFrame().$(selector) }.
1089 */
1090 async $<Selector extends string>(
1091 selector: Selector,
1092 ): Promise<ElementHandle<NodeFor<Selector>> | null> {
1093 return await this.mainFrame().$(selector);
1094 }
1095
1096 /**
1097 * Finds elements on the page that match the selector. If no elements
1098 * match the selector, the return value resolves to `[]`.
1099 *
1100 * @param selector -
1101 * {@link https://pptr.dev/guides/page-interactions#selectors | selector}
1102 * to query the page for.
1103 * {@link https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors | CSS selectors}
1104 * can be passed as-is and a
1105 * {@link https://pptr.dev/guides/page-interactions#non-css-selectors | Puppeteer-specific selector syntax}
1106 * allows quering by
1107 * {@link https://pptr.dev/guides/page-interactions#text-selectors--p-text | text},
1108 * {@link https://pptr.dev/guides/page-interactions#aria-selectors--p-aria | a11y role and name},
1109 * and
1110 * {@link https://pptr.dev/guides/page-interactions#xpath-selectors--p-xpath | xpath}
1111 * and
1112 * {@link https://pptr.dev/guides/page-interactions#querying-elements-in-shadow-dom | combining these queries across shadow roots}.
1113 * Alternatively, you can specify the selector type using a
1114 * {@link https://pptr.dev/guides/page-interactions#prefixed-selector-syntax | prefix}.
1115 *
1116 * @remarks
1117 *
1118 * Shortcut for {@link Frame.$$ | Page.mainFrame().$$(selector) }.
1119 */
1120 async $$<Selector extends string>(
1121 selector: Selector,
1122 options?: QueryOptions,
1123 ): Promise<Array<ElementHandle<NodeFor<Selector>>>> {
1124 return await this.mainFrame().$$(selector, options);
1125 }
1126
1127 /**
1128 * @remarks
1129 *
1130 * The only difference between {@link Page.evaluate | page.evaluate} and
1131 * `page.evaluateHandle` is that `evaluateHandle` will return the value
1132 * wrapped in an in-page object.
1133 *
1134 * If the function passed to `page.evaluateHandle` returns a Promise, the
1135 * function will wait for the promise to resolve and return its value.
1136 *
1137 * You can pass a string instead of a function (although functions are
1138 * recommended as they are easier to debug and use with TypeScript):
1139 *
1140 * @example
1141 *
1142 * ```ts
1143 * const aHandle = await page.evaluateHandle('document');
1144 * ```
1145 *
1146 * @example
1147 * {@link JSHandle} instances can be passed as arguments to the `pageFunction`:
1148 *
1149 * ```ts
1150 * const aHandle = await page.evaluateHandle(() => document.body);
1151 * const resultHandle = await page.evaluateHandle(
1152 * body => body.innerHTML,
1153 * aHandle,
1154 * );
1155 * console.log(await resultHandle.jsonValue());
1156 * await resultHandle.dispose();
1157 * ```
1158 *
1159 * Most of the time this function returns a {@link JSHandle},
1160 * but if `pageFunction` returns a reference to an element,
1161 * you instead get an {@link ElementHandle} back:
1162 *
1163 * @example
1164 *
1165 * ```ts
1166 * const button = await page.evaluateHandle(() =>
1167 * document.querySelector('button'),
1168 * );
1169 * // can call `click` because `button` is an `ElementHandle`
1170 * await button.click();
1171 * ```
1172 *
1173 * The TypeScript definitions assume that `evaluateHandle` returns
1174 * a `JSHandle`, but if you know it's going to return an
1175 * `ElementHandle`, pass it as the generic argument:
1176 *
1177 * ```ts
1178 * const button = await page.evaluateHandle<ElementHandle>(...);
1179 * ```
1180 *
1181 * @param pageFunction - a function that is run within the page
1182 * @param args - arguments to be passed to the pageFunction
1183 */
1184 async evaluateHandle<
1185 Params extends unknown[],
1186 Func extends EvaluateFunc<Params> = EvaluateFunc<Params>,
1187 >(
1188 pageFunction: Func | string,
1189 ...args: Params
1190 ): Promise<HandleFor<Awaited<ReturnType<Func>>>> {
1191 pageFunction = withSourcePuppeteerURLIfNone(
1192 this.evaluateHandle.name,
1193 pageFunction,
1194 );
1195 return await this.mainFrame().evaluateHandle(pageFunction, ...args);
1196 }
1197
1198 /**
1199 * This method iterates the JavaScript heap and finds all objects with the
1200 * given prototype.
1201 *
1202 * @example
1203 *
1204 * ```ts
1205 * // Create a Map object
1206 * await page.evaluate(() => (window.map = new Map()));
1207 * // Get a handle to the Map object prototype
1208 * const mapPrototype = await page.evaluateHandle(() => Map.prototype);
1209 * // Query all map instances into an array
1210 * const mapInstances = await page.queryObjects(mapPrototype);
1211 * // Count amount of map objects in heap
1212 * const count = await page.evaluate(maps => maps.length, mapInstances);
1213 * await mapInstances.dispose();
1214 * await mapPrototype.dispose();
1215 * ```
1216 *
1217 * @param prototypeHandle - a handle to the object prototype.
1218 * @returns Promise which resolves to a handle to an array of objects with
1219 * this prototype.
1220 */
1221 abstract queryObjects<Prototype>(
1222 prototypeHandle: JSHandle<Prototype>,
1223 ): Promise<JSHandle<Prototype[]>>;
1224
1225 /**
1226 * This method finds the first element within the page that matches the selector
1227 * and passes the result as the first argument to the `pageFunction`.
1228 *
1229 * @remarks
1230 *
1231 * If no element is found matching `selector`, the method will throw an error.
1232 *
1233 * If `pageFunction` returns a promise `$eval` will wait for the promise to
1234 * resolve and then return its value.
1235 *
1236 * @example
1237 *
1238 * ```ts
1239 * const searchValue = await page.$eval('#search', el => el.value);
1240 * const preloadHref = await page.$eval('link[rel=preload]', el => el.href);
1241 * const html = await page.$eval('.main-container', el => el.outerHTML);
1242 * ```
1243 *
1244 * If you are using TypeScript, you may have to provide an explicit type to the
1245 * first argument of the `pageFunction`.
1246 * By default it is typed as `Element`, but you may need to provide a more
1247 * specific sub-type:
1248 *
1249 * @example
1250 *
1251 * ```ts
1252 * // if you don't provide HTMLInputElement here, TS will error
1253 * // as `value` is not on `Element`
1254 * const searchValue = await page.$eval(
1255 * '#search',
1256 * (el: HTMLInputElement) => el.value,
1257 * );
1258 * ```
1259 *
1260 * The compiler should be able to infer the return type
1261 * from the `pageFunction` you provide. If it is unable to, you can use the generic
1262 * type to tell the compiler what return type you expect from `$eval`:
1263 *
1264 * @example
1265 *
1266 * ```ts
1267 * // The compiler can infer the return type in this case, but if it can't
1268 * // or if you want to be more explicit, provide it as the generic type.
1269 * const searchValue = await page.$eval<string>(
1270 * '#search',
1271 * (el: HTMLInputElement) => el.value,
1272 * );
1273 * ```
1274 *
1275 * @param selector -
1276 * {@link https://pptr.dev/guides/page-interactions#selectors | selector}
1277 * to query the page for.
1278 * {@link https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors | CSS selectors}
1279 * can be passed as-is and a
1280 * {@link https://pptr.dev/guides/page-interactions#non-css-selectors | Puppeteer-specific selector syntax}
1281 * allows quering by
1282 * {@link https://pptr.dev/guides/page-interactions#text-selectors--p-text | text},
1283 * {@link https://pptr.dev/guides/page-interactions#aria-selectors--p-aria | a11y role and name},
1284 * and
1285 * {@link https://pptr.dev/guides/page-interactions#xpath-selectors--p-xpath | xpath}
1286 * and
1287 * {@link https://pptr.dev/guides/page-interactions#querying-elements-in-shadow-dom | combining these queries across shadow roots}.
1288 * Alternatively, you can specify the selector type using a
1289 * {@link https://pptr.dev/guides/page-interactions#prefixed-selector-syntax | prefix}.
1290 * @param pageFunction - the function to be evaluated in the page context.
1291 * Will be passed the result of the element matching the selector as its
1292 * first argument.
1293 * @param args - any additional arguments to pass through to `pageFunction`.
1294 *
1295 * @returns The result of calling `pageFunction`. If it returns an element it
1296 * is wrapped in an {@link ElementHandle}, else the raw value itself is
1297 * returned.
1298 */
1299 async $eval<
1300 Selector extends string,
1301 Params extends unknown[],
1302 Func extends EvaluateFuncWith<NodeFor<Selector>, Params> = EvaluateFuncWith<
1303 NodeFor<Selector>,
1304 Params
1305 >,
1306 >(
1307 selector: Selector,
1308 pageFunction: Func | string,
1309 ...args: Params
1310 ): Promise<Awaited<ReturnType<Func>>> {
1311 pageFunction = withSourcePuppeteerURLIfNone(this.$eval.name, pageFunction);
1312 return await this.mainFrame().$eval(selector, pageFunction, ...args);
1313 }
1314
1315 /**
1316 * This method returns all elements matching the selector and passes the
1317 * resulting array as the first argument to the `pageFunction`.
1318 *
1319 * @remarks
1320 * If `pageFunction` returns a promise `$$eval` will wait for the promise to
1321 * resolve and then return its value.
1322 *
1323 * @example
1324 *
1325 * ```ts
1326 * // get the amount of divs on the page
1327 * const divCount = await page.$$eval('div', divs => divs.length);
1328 *
1329 * // get the text content of all the `.options` elements:
1330 * const options = await page.$$eval('div > span.options', options => {
1331 * return options.map(option => option.textContent);
1332 * });
1333 * ```
1334 *
1335 * If you are using TypeScript, you may have to provide an explicit type to the
1336 * first argument of the `pageFunction`.
1337 * By default it is typed as `Element[]`, but you may need to provide a more
1338 * specific sub-type:
1339 *
1340 * @example
1341 *
1342 * ```ts
1343 * await page.$$eval('input', elements => {
1344 * return elements.map(e => e.value);
1345 * });
1346 * ```
1347 *
1348 * The compiler should be able to infer the return type
1349 * from the `pageFunction` you provide. If it is unable to, you can use the generic
1350 * type to tell the compiler what return type you expect from `$$eval`:
1351 *
1352 * @example
1353 *
1354 * ```ts
1355 * const allInputValues = await page.$$eval('input', elements =>
1356 * elements.map(e => e.textContent),
1357 * );
1358 * ```
1359 *
1360 * @param selector -
1361 * {@link https://pptr.dev/guides/page-interactions#selectors | selector}
1362 * to query the page for.
1363 * {@link https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors | CSS selectors}
1364 * can be passed as-is and a
1365 * {@link https://pptr.dev/guides/page-interactions#non-css-selectors | Puppeteer-specific selector syntax}
1366 * allows quering by
1367 * {@link https://pptr.dev/guides/page-interactions#text-selectors--p-text | text},
1368 * {@link https://pptr.dev/guides/page-interactions#aria-selectors--p-aria | a11y role and name},
1369 * and
1370 * {@link https://pptr.dev/guides/page-interactions#xpath-selectors--p-xpath | xpath}
1371 * and
1372 * {@link https://pptr.dev/guides/page-interactions#querying-elements-in-shadow-dom | combining these queries across shadow roots}.
1373 * Alternatively, you can specify the selector type using a
1374 * {@link https://pptr.dev/guides/page-interactions#prefixed-selector-syntax | prefix}.
1375 * @param pageFunction - the function to be evaluated in the page context.
1376 * Will be passed an array of matching elements as its first argument.
1377 * @param args - any additional arguments to pass through to `pageFunction`.
1378 *
1379 * @returns The result of calling `pageFunction`. If it returns an element it
1380 * is wrapped in an {@link ElementHandle}, else the raw value itself is
1381 * returned.
1382 */
1383 async $$eval<
1384 Selector extends string,
1385 Params extends unknown[],
1386 Func extends EvaluateFuncWith<
1387 Array<NodeFor<Selector>>,
1388 Params
1389 > = EvaluateFuncWith<Array<NodeFor<Selector>>, Params>,
1390 >(
1391 selector: Selector,
1392 pageFunction: Func | string,
1393 ...args: Params
1394 ): Promise<Awaited<ReturnType<Func>>> {
1395 pageFunction = withSourcePuppeteerURLIfNone(this.$$eval.name, pageFunction);
1396 return await this.mainFrame().$$eval(selector, pageFunction, ...args);
1397 }
1398
1399 /**
1400 * If no URLs are specified, this method returns cookies for the
1401 * current page URL. If URLs are specified, only cookies for those
1402 * URLs are returned.
1403 *
1404 * @deprecated Page-level cookie API is deprecated. Use
1405 * {@link Browser.cookies} or {@link BrowserContext.cookies} instead.
1406 */
1407 abstract cookies(...urls: string[]): Promise<Cookie[]>;
1408
1409 /**
1410 * @deprecated Page-level cookie API is deprecated. Use
1411 * {@link Browser.deleteCookie} or {@link BrowserContext.deleteCookie}
1412 * instead.
1413 */
1414 abstract deleteCookie(...cookies: DeleteCookiesRequest[]): Promise<void>;
1415
1416 /**
1417 * @example
1418 *
1419 *```ts
1420 * await page.setCookie(cookieObject1, cookieObject2);
1421 *```
1422 *
1423 * @deprecated Page-level cookie API is deprecated. Use
1424 * {@link Browser.setCookie} or {@link BrowserContext.setCookie}
1425 * instead.
1426 */
1427 abstract setCookie(...cookies: CookieParam[]): Promise<void>;
1428
1429 /**
1430 * Adds a `<script>` tag into the page with the desired URL or content.
1431 *
1432 * @remarks
1433 * Shortcut for
1434 * {@link Frame.addScriptTag | page.mainFrame().addScriptTag(options)}.
1435 *
1436 * @param options - Options for the script.
1437 * @returns An {@link ElementHandle | element handle} to the injected
1438 * `<script>` element.
1439 */
1440 async addScriptTag(
1441 options: FrameAddScriptTagOptions,
1442 ): Promise<ElementHandle<HTMLScriptElement>> {
1443 return await this.mainFrame().addScriptTag(options);
1444 }
1445
1446 /**
1447 * Adds a `<link rel="stylesheet">` tag into the page with the desired URL or
1448 * a `<style type="text/css">` tag with the content.
1449 *
1450 * Shortcut for
1451 * {@link Frame.(addStyleTag:2) | page.mainFrame().addStyleTag(options)}.
1452 *
1453 * @returns An {@link ElementHandle | element handle} to the injected `<link>`
1454 * or `<style>` element.
1455 */
1456 async addStyleTag(
1457 options: Omit<FrameAddStyleTagOptions, 'url'>,
1458 ): Promise<ElementHandle<HTMLStyleElement>>;
1459 async addStyleTag(
1460 options: FrameAddStyleTagOptions,
1461 ): Promise<ElementHandle<HTMLLinkElement>>;
1462 async addStyleTag(
1463 options: FrameAddStyleTagOptions,
1464 ): Promise<ElementHandle<HTMLStyleElement | HTMLLinkElement>> {
1465 return await this.mainFrame().addStyleTag(options);
1466 }
1467
1468 /**
1469 * The method adds a function called `name` on the page's `window` object.
1470 * When called, the function executes `puppeteerFunction` in node.js and
1471 * returns a `Promise` which resolves to the return value of
1472 * `puppeteerFunction`.
1473 *
1474 * If the puppeteerFunction returns a `Promise`, it will be awaited.
1475 *
1476 * :::note
1477 *
1478 * Functions installed via `page.exposeFunction` survive navigations.
1479 *
1480 * :::
1481 *
1482 * @example
1483 * An example of adding an `md5` function into the page:
1484 *
1485 * ```ts
1486 * import puppeteer from 'puppeteer';
1487 * import crypto from 'crypto';
1488 *
1489 * (async () => {
1490 * const browser = await puppeteer.launch();
1491 * const page = await browser.newPage();
1492 * page.on('console', msg => console.log(msg.text()));
1493 * await page.exposeFunction('md5', text =>
1494 * crypto.createHash('md5').update(text).digest('hex'),
1495 * );
1496 * await page.evaluate(async () => {
1497 * // use window.md5 to compute hashes
1498 * const myString = 'PUPPETEER';
1499 * const myHash = await window.md5(myString);
1500 * console.log(`md5 of ${myString} is ${myHash}`);
1501 * });
1502 * await browser.close();
1503 * })();
1504 * ```
1505 *
1506 * @example
1507 * An example of adding a `window.readfile` function into the page:
1508 *
1509 * ```ts
1510 * import puppeteer from 'puppeteer';
1511 * import fs from 'fs';
1512 *
1513 * (async () => {
1514 * const browser = await puppeteer.launch();
1515 * const page = await browser.newPage();
1516 * page.on('console', msg => console.log(msg.text()));
1517 * await page.exposeFunction('readfile', async filePath => {
1518 * return new Promise((resolve, reject) => {
1519 * fs.readFile(filePath, 'utf8', (err, text) => {
1520 * if (err) reject(err);
1521 * else resolve(text);
1522 * });
1523 * });
1524 * });
1525 * await page.evaluate(async () => {
1526 * // use window.readfile to read contents of a file
1527 * const content = await window.readfile('/etc/hosts');
1528 * console.log(content);
1529 * });
1530 * await browser.close();
1531 * })();
1532 * ```
1533 *
1534 * @param name - Name of the function on the window object
1535 * @param pptrFunction - Callback function which will be called in Puppeteer's
1536 * context.
1537 */
1538 abstract exposeFunction(
1539 name: string,
1540 // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
1541 pptrFunction: Function | {default: Function},
1542 ): Promise<void>;
1543
1544 /**
1545 * The method removes a previously added function via ${@link Page.exposeFunction}
1546 * called `name` from the page's `window` object.
1547 */
1548 abstract removeExposedFunction(name: string): Promise<void>;
1549
1550 /**
1551 * Provide credentials for `HTTP authentication`.
1552 *
1553 * :::note
1554 *
1555 * Request interception will be turned on behind the scenes to
1556 * implement authentication. This might affect performance.
1557 *
1558 * :::
1559 *
1560 * @remarks
1561 * To disable authentication, pass `null`.
1562 */
1563 abstract authenticate(credentials: Credentials | null): Promise<void>;
1564
1565 /**
1566 * The extra HTTP headers will be sent with every request the page initiates.
1567 *
1568 * :::tip
1569 *
1570 * All HTTP header names are lowercased. (HTTP headers are
1571 * case-insensitive, so this shouldn’t impact your server code.)
1572 *
1573 * :::
1574 *
1575 * :::note
1576 *
1577 * page.setExtraHTTPHeaders does not guarantee the order of headers in
1578 * the outgoing requests.
1579 *
1580 * :::
1581 *
1582 * @param headers - An object containing additional HTTP headers to be sent
1583 * with every request. All header values must be strings.
1584 */
1585 abstract setExtraHTTPHeaders(headers: Record<string, string>): Promise<void>;
1586
1587 /**
1588 * @param userAgent - Specific user agent to use in this page
1589 * @param userAgentData - Specific user agent client hint data to use in this
1590 * page
1591 * @returns Promise which resolves when the user agent is set.
1592 */
1593 abstract setUserAgent(
1594 userAgent: string,
1595 userAgentMetadata?: Protocol.Emulation.UserAgentMetadata,
1596 ): Promise<void>;
1597
1598 /**
1599 * Object containing metrics as key/value pairs.
1600 *
1601 * @returns
1602 *
1603 * - `Timestamp` : The timestamp when the metrics sample was taken.
1604 *
1605 * - `Documents` : Number of documents in the page.
1606 *
1607 * - `Frames` : Number of frames in the page.
1608 *
1609 * - `JSEventListeners` : Number of events in the page.
1610 *
1611 * - `Nodes` : Number of DOM nodes in the page.
1612 *
1613 * - `LayoutCount` : Total number of full or partial page layout.
1614 *
1615 * - `RecalcStyleCount` : Total number of page style recalculations.
1616 *
1617 * - `LayoutDuration` : Combined durations of all page layouts.
1618 *
1619 * - `RecalcStyleDuration` : Combined duration of all page style
1620 * recalculations.
1621 *
1622 * - `ScriptDuration` : Combined duration of JavaScript execution.
1623 *
1624 * - `TaskDuration` : Combined duration of all tasks performed by the browser.
1625 *
1626 * - `JSHeapUsedSize` : Used JavaScript heap size.
1627 *
1628 * - `JSHeapTotalSize` : Total JavaScript heap size.
1629 *
1630 * @remarks
1631 * All timestamps are in monotonic time: monotonically increasing time
1632 * in seconds since an arbitrary point in the past.
1633 */
1634 abstract metrics(): Promise<Metrics>;
1635
1636 /**
1637 * The page's URL.
1638 *
1639 * @remarks
1640 *
1641 * Shortcut for {@link Frame.url | page.mainFrame().url()}.
1642 */
1643 url(): string {
1644 return this.mainFrame().url();
1645 }
1646
1647 /**
1648 * The full HTML contents of the page, including the DOCTYPE.
1649 */
1650 async content(): Promise<string> {
1651 return await this.mainFrame().content();
1652 }
1653
1654 /**
1655 * Set the content of the page.
1656 *
1657 * @param html - HTML markup to assign to the page.
1658 * @param options - Parameters that has some properties.
1659 */
1660 async setContent(html: string, options?: WaitForOptions): Promise<void> {
1661 await this.mainFrame().setContent(html, options);
1662 }
1663
1664 /**
1665 * {@inheritDoc Frame.goto}
1666 */
1667 async goto(url: string, options?: GoToOptions): Promise<HTTPResponse | null> {
1668 return await this.mainFrame().goto(url, options);
1669 }
1670
1671 /**
1672 * Reloads the page.
1673 *
1674 * @param options - Options to configure waiting behavior.
1675 * @returns A promise which resolves to the main resource response. In case of
1676 * multiple redirects, the navigation will resolve with the response of the
1677 * last redirect.
1678 */
1679 abstract reload(options?: WaitForOptions): Promise<HTTPResponse | null>;
1680
1681 /**
1682 * Waits for the page to navigate to a new URL or to reload. It is useful when
1683 * you run code that will indirectly cause the page to navigate.
1684 *
1685 * @example
1686 *
1687 * ```ts
1688 * const [response] = await Promise.all([
1689 * page.waitForNavigation(), // The promise resolves after navigation has finished
1690 * page.click('a.my-link'), // Clicking the link will indirectly cause a navigation
1691 * ]);
1692 * ```
1693 *
1694 * @remarks
1695 *
1696 * Usage of the
1697 * {@link https://developer.mozilla.org/en-US/docs/Web/API/History_API | History API}
1698 * to change the URL is considered a navigation.
1699 *
1700 * @param options - Navigation parameters which might have the following
1701 * properties:
1702 * @returns A `Promise` which resolves to the main resource response.
1703 *
1704 * - In case of multiple redirects, the navigation will resolve with the
1705 * response of the last redirect.
1706 * - In case of navigation to a different anchor or navigation due to History
1707 * API usage, the navigation will resolve with `null`.
1708 */
1709 async waitForNavigation(
1710 options: WaitForOptions = {},
1711 ): Promise<HTTPResponse | null> {
1712 return await this.mainFrame().waitForNavigation(options);
1713 }
1714
1715 /**
1716 * @param urlOrPredicate - A URL or predicate to wait for
1717 * @param options - Optional waiting parameters
1718 * @returns Promise which resolves to the matched request
1719 * @example
1720 *
1721 * ```ts
1722 * const firstRequest = await page.waitForRequest(
1723 * 'https://example.com/resource',
1724 * );
1725 * const finalRequest = await page.waitForRequest(
1726 * request => request.url() === 'https://example.com',
1727 * );
1728 * return finalRequest.response()?.ok();
1729 * ```
1730 *
1731 * @remarks
1732 * Optional Waiting Parameters have:
1733 *
1734 * - `timeout`: Maximum wait time in milliseconds, defaults to `30` seconds, pass
1735 * `0` to disable the timeout. The default value can be changed by using the
1736 * {@link Page.setDefaultTimeout} method.
1737 */
1738 waitForRequest(
1739 urlOrPredicate: string | AwaitablePredicate<HTTPRequest>,
1740 options: WaitTimeoutOptions = {},
1741 ): Promise<HTTPRequest> {
1742 const {timeout: ms = this._timeoutSettings.timeout(), signal} = options;
1743 if (typeof urlOrPredicate === 'string') {
1744 const url = urlOrPredicate;
1745 urlOrPredicate = (request: HTTPRequest) => {
1746 return request.url() === url;
1747 };
1748 }
1749 const observable$ = fromEmitterEvent(this, PageEvent.Request).pipe(
1750 filterAsync(urlOrPredicate),
1751 raceWith(
1752 timeout(ms),
1753 fromAbortSignal(signal),
1754 fromEmitterEvent(this, PageEvent.Close).pipe(
1755 map(() => {
1756 throw new TargetCloseError('Page closed!');
1757 }),
1758 ),
1759 ),
1760 );
1761 return firstValueFrom(observable$);
1762 }
1763
1764 /**
1765 * @param urlOrPredicate - A URL or predicate to wait for.
1766 * @param options - Optional waiting parameters
1767 * @returns Promise which resolves to the matched response.
1768 * @example
1769 *
1770 * ```ts
1771 * const firstResponse = await page.waitForResponse(
1772 * 'https://example.com/resource',
1773 * );
1774 * const finalResponse = await page.waitForResponse(
1775 * response =>
1776 * response.url() === 'https://example.com' && response.status() === 200,
1777 * );
1778 * const finalResponse = await page.waitForResponse(async response => {
1779 * return (await response.text()).includes('<html>');
1780 * });
1781 * return finalResponse.ok();
1782 * ```
1783 *
1784 * @remarks
1785 * Optional Parameter have:
1786 *
1787 * - `timeout`: Maximum wait time in milliseconds, defaults to `30` seconds,
1788 * pass `0` to disable the timeout. The default value can be changed by using
1789 * the {@link Page.setDefaultTimeout} method.
1790 */
1791 waitForResponse(
1792 urlOrPredicate: string | AwaitablePredicate<HTTPResponse>,
1793 options: WaitTimeoutOptions = {},
1794 ): Promise<HTTPResponse> {
1795 const {timeout: ms = this._timeoutSettings.timeout(), signal} = options;
1796 if (typeof urlOrPredicate === 'string') {
1797 const url = urlOrPredicate;
1798 urlOrPredicate = (response: HTTPResponse) => {
1799 return response.url() === url;
1800 };
1801 }
1802 const observable$ = fromEmitterEvent(this, PageEvent.Response).pipe(
1803 filterAsync(urlOrPredicate),
1804 raceWith(
1805 timeout(ms),
1806 fromAbortSignal(signal),
1807 fromEmitterEvent(this, PageEvent.Close).pipe(
1808 map(() => {
1809 throw new TargetCloseError('Page closed!');
1810 }),
1811 ),
1812 ),
1813 );
1814 return firstValueFrom(observable$);
1815 }
1816
1817 /**
1818 * Waits for the network to be idle.
1819 *
1820 * @param options - Options to configure waiting behavior.
1821 * @returns A promise which resolves once the network is idle.
1822 */
1823 waitForNetworkIdle(options: WaitForNetworkIdleOptions = {}): Promise<void> {
1824 return firstValueFrom(this.waitForNetworkIdle$(options));
1825 }
1826
1827 /**
1828 * @internal
1829 */
1830 waitForNetworkIdle$(
1831 options: WaitForNetworkIdleOptions = {},
1832 ): Observable<void> {
1833 const {
1834 timeout: ms = this._timeoutSettings.timeout(),
1835 idleTime = NETWORK_IDLE_TIME,
1836 concurrency = 0,
1837 signal,
1838 } = options;
1839
1840 return this.#inflight$.pipe(
1841 switchMap(inflight => {
1842 if (inflight > concurrency) {
1843 return EMPTY;
1844 }
1845 return timer(idleTime);
1846 }),
1847 map(() => {}),
1848 raceWith(
1849 timeout(ms),
1850 fromAbortSignal(signal),
1851 fromEmitterEvent(this, PageEvent.Close).pipe(
1852 map(() => {
1853 throw new TargetCloseError('Page closed!');
1854 }),
1855 ),
1856 ),
1857 );
1858 }
1859
1860 /**
1861 * Waits for a frame matching the given conditions to appear.
1862 *
1863 * @example
1864 *
1865 * ```ts
1866 * const frame = await page.waitForFrame(async frame => {
1867 * return frame.name() === 'Test';
1868 * });
1869 * ```
1870 */
1871 async waitForFrame(
1872 urlOrPredicate: string | ((frame: Frame) => Awaitable<boolean>),
1873 options: WaitTimeoutOptions = {},
1874 ): Promise<Frame> {
1875 const {timeout: ms = this.getDefaultTimeout(), signal} = options;
1876
1877 const predicate = isString(urlOrPredicate)
1878 ? (frame: Frame) => {
1879 return urlOrPredicate === frame.url();
1880 }
1881 : urlOrPredicate;
1882
1883 return await firstValueFrom(
1884 merge(
1885 fromEmitterEvent(this, PageEvent.FrameAttached),
1886 fromEmitterEvent(this, PageEvent.FrameNavigated),
1887 from(this.frames()),
1888 ).pipe(
1889 filterAsync(predicate),
1890 first(),
1891 raceWith(
1892 timeout(ms),
1893 fromAbortSignal(signal),
1894 fromEmitterEvent(this, PageEvent.Close).pipe(
1895 map(() => {
1896 throw new TargetCloseError('Page closed.');
1897 }),
1898 ),
1899 ),
1900 ),
1901 );
1902 }
1903
1904 /**
1905 * This method navigate to the previous page in history.
1906 * @param options - Navigation parameters
1907 * @returns Promise which resolves to the main resource response. In case of
1908 * multiple redirects, the navigation will resolve with the response of the
1909 * last redirect. If can not go back, resolves to `null`.
1910 */
1911 abstract goBack(options?: WaitForOptions): Promise<HTTPResponse | null>;
1912
1913 /**
1914 * This method navigate to the next page in history.
1915 * @param options - Navigation Parameter
1916 * @returns Promise which resolves to the main resource response. In case of
1917 * multiple redirects, the navigation will resolve with the response of the
1918 * last redirect. If can not go forward, resolves to `null`.
1919 */
1920 abstract goForward(options?: WaitForOptions): Promise<HTTPResponse | null>;
1921
1922 /**
1923 * Brings page to front (activates tab).
1924 */
1925 abstract bringToFront(): Promise<void>;
1926
1927 /**
1928 * Emulates a given device's metrics and user agent.
1929 *
1930 * To aid emulation, Puppeteer provides a list of known devices that can be
1931 * via {@link KnownDevices}.
1932 *
1933 * @remarks
1934 * This method is a shortcut for calling two methods:
1935 * {@link Page.setUserAgent} and {@link Page.setViewport}.
1936 *
1937 * This method will resize the page. A lot of websites don't expect phones to
1938 * change size, so you should emulate before navigating to the page.
1939 *
1940 * @example
1941 *
1942 * ```ts
1943 * import {KnownDevices} from 'puppeteer';
1944 * const iPhone = KnownDevices['iPhone 15 Pro'];
1945 *
1946 * (async () => {
1947 * const browser = await puppeteer.launch();
1948 * const page = await browser.newPage();
1949 * await page.emulate(iPhone);
1950 * await page.goto('https://www.google.com');
1951 * // other actions...
1952 * await browser.close();
1953 * })();
1954 * ```
1955 */
1956 async emulate(device: Device): Promise<void> {
1957 await Promise.all([
1958 this.setUserAgent(device.userAgent),
1959 this.setViewport(device.viewport),
1960 ]);
1961 }
1962
1963 /**
1964 * @param enabled - Whether or not to enable JavaScript on the page.
1965 * @remarks
1966 * NOTE: changing this value won't affect scripts that have already been run.
1967 * It will take full effect on the next navigation.
1968 */
1969 abstract setJavaScriptEnabled(enabled: boolean): Promise<void>;
1970
1971 /**
1972 * Toggles bypassing page's Content-Security-Policy.
1973 * @param enabled - sets bypassing of page's Content-Security-Policy.
1974 * @remarks
1975 * NOTE: CSP bypassing happens at the moment of CSP initialization rather than
1976 * evaluation. Usually, this means that `page.setBypassCSP` should be called
1977 * before navigating to the domain.
1978 */
1979 abstract setBypassCSP(enabled: boolean): Promise<void>;
1980
1981 /**
1982 * @param type - Changes the CSS media type of the page. The only allowed
1983 * values are `screen`, `print` and `null`. Passing `null` disables CSS media
1984 * emulation.
1985 * @example
1986 *
1987 * ```ts
1988 * await page.evaluate(() => matchMedia('screen').matches);
1989 * // → true
1990 * await page.evaluate(() => matchMedia('print').matches);
1991 * // → false
1992 *
1993 * await page.emulateMediaType('print');
1994 * await page.evaluate(() => matchMedia('screen').matches);
1995 * // → false
1996 * await page.evaluate(() => matchMedia('print').matches);
1997 * // → true
1998 *
1999 * await page.emulateMediaType(null);
2000 * await page.evaluate(() => matchMedia('screen').matches);
2001 * // → true
2002 * await page.evaluate(() => matchMedia('print').matches);
2003 * // → false
2004 * ```
2005 */
2006 abstract emulateMediaType(type?: string): Promise<void>;
2007
2008 /**
2009 * Enables CPU throttling to emulate slow CPUs.
2010 * @param factor - slowdown factor (1 is no throttle, 2 is 2x slowdown, etc).
2011 */
2012 abstract emulateCPUThrottling(factor: number | null): Promise<void>;
2013
2014 /**
2015 * @param features - `<?Array<Object>>` Given an array of media feature
2016 * objects, emulates CSS media features on the page. Each media feature object
2017 * must have the following properties:
2018 * @example
2019 *
2020 * ```ts
2021 * await page.emulateMediaFeatures([
2022 * {name: 'prefers-color-scheme', value: 'dark'},
2023 * ]);
2024 * await page.evaluate(
2025 * () => matchMedia('(prefers-color-scheme: dark)').matches,
2026 * );
2027 * // → true
2028 * await page.evaluate(
2029 * () => matchMedia('(prefers-color-scheme: light)').matches,
2030 * );
2031 * // → false
2032 *
2033 * await page.emulateMediaFeatures([
2034 * {name: 'prefers-reduced-motion', value: 'reduce'},
2035 * ]);
2036 * await page.evaluate(
2037 * () => matchMedia('(prefers-reduced-motion: reduce)').matches,
2038 * );
2039 * // → true
2040 * await page.evaluate(
2041 * () => matchMedia('(prefers-reduced-motion: no-preference)').matches,
2042 * );
2043 * // → false
2044 *
2045 * await page.emulateMediaFeatures([
2046 * {name: 'prefers-color-scheme', value: 'dark'},
2047 * {name: 'prefers-reduced-motion', value: 'reduce'},
2048 * ]);
2049 * await page.evaluate(
2050 * () => matchMedia('(prefers-color-scheme: dark)').matches,
2051 * );
2052 * // → true
2053 * await page.evaluate(
2054 * () => matchMedia('(prefers-color-scheme: light)').matches,
2055 * );
2056 * // → false
2057 * await page.evaluate(
2058 * () => matchMedia('(prefers-reduced-motion: reduce)').matches,
2059 * );
2060 * // → true
2061 * await page.evaluate(
2062 * () => matchMedia('(prefers-reduced-motion: no-preference)').matches,
2063 * );
2064 * // → false
2065 *
2066 * await page.emulateMediaFeatures([{name: 'color-gamut', value: 'p3'}]);
2067 * await page.evaluate(() => matchMedia('(color-gamut: srgb)').matches);
2068 * // → true
2069 * await page.evaluate(() => matchMedia('(color-gamut: p3)').matches);
2070 * // → true
2071 * await page.evaluate(() => matchMedia('(color-gamut: rec2020)').matches);
2072 * // → false
2073 * ```
2074 */
2075 abstract emulateMediaFeatures(features?: MediaFeature[]): Promise<void>;
2076
2077 /**
2078 * @param timezoneId - Changes the timezone of the page. See
2079 * {@link https://source.chromium.org/chromium/chromium/deps/icu.git/+/faee8bc70570192d82d2978a71e2a615788597d1:source/data/misc/metaZones.txt | ICU’s metaZones.txt}
2080 * for a list of supported timezone IDs. Passing
2081 * `null` disables timezone emulation.
2082 */
2083 abstract emulateTimezone(timezoneId?: string): Promise<void>;
2084
2085 /**
2086 * Emulates the idle state.
2087 * If no arguments set, clears idle state emulation.
2088 *
2089 * @example
2090 *
2091 * ```ts
2092 * // set idle emulation
2093 * await page.emulateIdleState({isUserActive: true, isScreenUnlocked: false});
2094 *
2095 * // do some checks here
2096 * ...
2097 *
2098 * // clear idle emulation
2099 * await page.emulateIdleState();
2100 * ```
2101 *
2102 * @param overrides - Mock idle state. If not set, clears idle overrides
2103 */
2104 abstract emulateIdleState(overrides?: {
2105 isUserActive: boolean;
2106 isScreenUnlocked: boolean;
2107 }): Promise<void>;
2108
2109 /**
2110 * Simulates the given vision deficiency on the page.
2111 *
2112 * @example
2113 *
2114 * ```ts
2115 * import puppeteer from 'puppeteer';
2116 *
2117 * (async () => {
2118 * const browser = await puppeteer.launch();
2119 * const page = await browser.newPage();
2120 * await page.goto('https://v8.dev/blog/10-years');
2121 *
2122 * await page.emulateVisionDeficiency('achromatopsia');
2123 * await page.screenshot({path: 'achromatopsia.png'});
2124 *
2125 * await page.emulateVisionDeficiency('deuteranopia');
2126 * await page.screenshot({path: 'deuteranopia.png'});
2127 *
2128 * await page.emulateVisionDeficiency('blurredVision');
2129 * await page.screenshot({path: 'blurred-vision.png'});
2130 *
2131 * await browser.close();
2132 * })();
2133 * ```
2134 *
2135 * @param type - the type of deficiency to simulate, or `'none'` to reset.
2136 */
2137 abstract emulateVisionDeficiency(
2138 type?: Protocol.Emulation.SetEmulatedVisionDeficiencyRequest['type'],
2139 ): Promise<void>;
2140
2141 /**
2142 * `page.setViewport` will resize the page. A lot of websites don't expect
2143 * phones to change size, so you should set the viewport before navigating to
2144 * the page.
2145 *
2146 * In the case of multiple pages in a single browser, each page can have its
2147 * own viewport size. Setting the viewport to `null` resets the viewport to
2148 * its default value.
2149 *
2150 * @example
2151 *
2152 * ```ts
2153 * const page = await browser.newPage();
2154 * await page.setViewport({
2155 * width: 640,
2156 * height: 480,
2157 * deviceScaleFactor: 1,
2158 * });
2159 * await page.goto('https://example.com');
2160 * ```
2161 *
2162 * @param viewport -
2163 * @remarks
2164 * NOTE: in certain cases, setting viewport will reload the page in order to
2165 * set the isMobile or hasTouch properties.
2166 */
2167 abstract setViewport(viewport: Viewport | null): Promise<void>;
2168
2169 /**
2170 * Returns the current page viewport settings without checking the actual page
2171 * viewport.
2172 *
2173 * This is either the viewport set with the previous {@link Page.setViewport}
2174 * call or the default viewport set via
2175 * {@link ConnectOptions.defaultViewport |
2176 * ConnectOptions.defaultViewport}.
2177 */
2178 abstract viewport(): Viewport | null;
2179
2180 /**
2181 * Evaluates a function in the page's context and returns the result.
2182 *
2183 * If the function passed to `page.evaluate` returns a Promise, the
2184 * function will wait for the promise to resolve and return its value.
2185 *
2186 * @example
2187 *
2188 * ```ts
2189 * const result = await frame.evaluate(() => {
2190 * return Promise.resolve(8 * 7);
2191 * });
2192 * console.log(result); // prints "56"
2193 * ```
2194 *
2195 * You can pass a string instead of a function (although functions are
2196 * recommended as they are easier to debug and use with TypeScript):
2197 *
2198 * @example
2199 *
2200 * ```ts
2201 * const aHandle = await page.evaluate('1 + 2');
2202 * ```
2203 *
2204 * To get the best TypeScript experience, you should pass in as the
2205 * generic the type of `pageFunction`:
2206 *
2207 * ```ts
2208 * const aHandle = await page.evaluate(() => 2);
2209 * ```
2210 *
2211 * @example
2212 *
2213 * {@link ElementHandle} instances (including {@link JSHandle}s) can be passed
2214 * as arguments to the `pageFunction`:
2215 *
2216 * ```ts
2217 * const bodyHandle = await page.$('body');
2218 * const html = await page.evaluate(body => body.innerHTML, bodyHandle);
2219 * await bodyHandle.dispose();
2220 * ```
2221 *
2222 * @param pageFunction - a function that is run within the page
2223 * @param args - arguments to be passed to the pageFunction
2224 *
2225 * @returns the return value of `pageFunction`.
2226 */
2227 async evaluate<
2228 Params extends unknown[],
2229 Func extends EvaluateFunc<Params> = EvaluateFunc<Params>,
2230 >(
2231 pageFunction: Func | string,
2232 ...args: Params
2233 ): Promise<Awaited<ReturnType<Func>>> {
2234 pageFunction = withSourcePuppeteerURLIfNone(
2235 this.evaluate.name,
2236 pageFunction,
2237 );
2238 return await this.mainFrame().evaluate(pageFunction, ...args);
2239 }
2240
2241 /**
2242 * Adds a function which would be invoked in one of the following scenarios:
2243 *
2244 * - whenever the page is navigated
2245 *
2246 * - whenever the child frame is attached or navigated. In this case, the
2247 * function is invoked in the context of the newly attached frame.
2248 *
2249 * The function is invoked after the document was created but before any of
2250 * its scripts were run. This is useful to amend the JavaScript environment,
2251 * e.g. to seed `Math.random`.
2252 * @param pageFunction - Function to be evaluated in browser context
2253 * @param args - Arguments to pass to `pageFunction`
2254 * @example
2255 * An example of overriding the navigator.languages property before the page loads:
2256 *
2257 * ```ts
2258 * // preload.js
2259 *
2260 * // overwrite the `languages` property to use a custom getter
2261 * Object.defineProperty(navigator, 'languages', {
2262 * get: function () {
2263 * return ['en-US', 'en', 'bn'];
2264 * },
2265 * });
2266 *
2267 * // In your puppeteer script, assuming the preload.js file is
2268 * // in same folder of our script.
2269 * const preloadFile = fs.readFileSync('./preload.js', 'utf8');
2270 * await page.evaluateOnNewDocument(preloadFile);
2271 * ```
2272 */
2273 abstract evaluateOnNewDocument<
2274 Params extends unknown[],
2275 Func extends (...args: Params) => unknown = (...args: Params) => unknown,
2276 >(
2277 pageFunction: Func | string,
2278 ...args: Params
2279 ): Promise<NewDocumentScriptEvaluation>;
2280
2281 /**
2282 * Removes script that injected into page by Page.evaluateOnNewDocument.
2283 *
2284 * @param identifier - script identifier
2285 */
2286 abstract removeScriptToEvaluateOnNewDocument(
2287 identifier: string,
2288 ): Promise<void>;
2289
2290 /**
2291 * Toggles ignoring cache for each request based on the enabled state. By
2292 * default, caching is enabled.
2293 * @param enabled - sets the `enabled` state of cache
2294 * @defaultValue `true`
2295 */
2296 abstract setCacheEnabled(enabled?: boolean): Promise<void>;
2297
2298 /**
2299 * @internal
2300 */
2301 async _maybeWriteTypedArrayToFile(
2302 path: string | undefined,
2303 typedArray: Uint8Array,
2304 ): Promise<void> {
2305 if (!path) {
2306 return;
2307 }
2308
2309 await environment.value.fs.promises.writeFile(path, typedArray);
2310 }
2311
2312 /**
2313 * Captures a screencast of this {@link Page | page}.
2314 *
2315 * @example
2316 * Recording a {@link Page | page}:
2317 *
2318 * ```
2319 * import puppeteer from 'puppeteer';
2320 *
2321 * // Launch a browser
2322 * const browser = await puppeteer.launch();
2323 *
2324 * // Create a new page
2325 * const page = await browser.newPage();
2326 *
2327 * // Go to your site.
2328 * await page.goto("https://www.example.com");
2329 *
2330 * // Start recording.
2331 * const recorder = await page.screencast({path: 'recording.webm'});
2332 *
2333 * // Do something.
2334 *
2335 * // Stop recording.
2336 * await recorder.stop();
2337 *
2338 * browser.close();
2339 * ```
2340 *
2341 * @param options - Configures screencast behavior.
2342 *
2343 * @experimental
2344 *
2345 * @remarks
2346 *
2347 * All recordings will be {@link https://www.webmproject.org/ | WebM} format using
2348 * the {@link https://www.webmproject.org/vp9/ | VP9} video codec. The FPS is 30.
2349 *
2350 * You must have {@link https://ffmpeg.org/ | ffmpeg} installed on your system.
2351 */
2352 async screencast(
2353 options: Readonly<ScreencastOptions> = {},
2354 ): Promise<ScreenRecorder> {
2355 const ScreenRecorder = environment.value.ScreenRecorder;
2356 const [width, height, devicePixelRatio] =
2357 await this.#getNativePixelDimensions();
2358 let crop: BoundingBox | undefined;
2359 if (options.crop) {
2360 const {
2361 x,
2362 y,
2363 width: cropWidth,
2364 height: cropHeight,
2365 } = roundRectangle(normalizeRectangle(options.crop));
2366 if (x < 0 || y < 0) {
2367 throw new Error(
2368 `\`crop.x\` and \`crop.y\` must be greater than or equal to 0.`,
2369 );
2370 }
2371 if (cropWidth <= 0 || cropHeight <= 0) {
2372 throw new Error(
2373 `\`crop.height\` and \`crop.width\` must be greater than or equal to 0.`,
2374 );
2375 }
2376
2377 const viewportWidth = width / devicePixelRatio;
2378 const viewportHeight = height / devicePixelRatio;
2379 if (x + cropWidth > viewportWidth) {
2380 throw new Error(
2381 `\`crop.width\` cannot be larger than the viewport width (${viewportWidth}).`,
2382 );
2383 }
2384 if (y + cropHeight > viewportHeight) {
2385 throw new Error(
2386 `\`crop.height\` cannot be larger than the viewport height (${viewportHeight}).`,
2387 );
2388 }
2389
2390 crop = {
2391 x: x * devicePixelRatio,
2392 y: y * devicePixelRatio,
2393 width: cropWidth * devicePixelRatio,
2394 height: cropHeight * devicePixelRatio,
2395 };
2396 }
2397 if (options.speed !== undefined && options.speed <= 0) {
2398 throw new Error(`\`speed\` must be greater than 0.`);
2399 }
2400 if (options.scale !== undefined && options.scale <= 0) {
2401 throw new Error(`\`scale\` must be greater than 0.`);
2402 }
2403
2404 const recorder = new ScreenRecorder(this, width, height, {
2405 ...options,
2406 path: options.ffmpegPath,
2407 crop,
2408 });
2409 try {
2410 await this._startScreencast();
2411 } catch (error) {
2412 void recorder.stop();
2413 throw error;
2414 }
2415 if (options.path) {
2416 const {createWriteStream} = environment.value.fs;
2417 const stream = createWriteStream(options.path, 'binary');
2418 recorder.pipe(stream);
2419 }
2420 return recorder;
2421 }
2422
2423 #screencastSessionCount = 0;
2424 #startScreencastPromise: Promise<void> | undefined;
2425
2426 /**
2427 * @internal
2428 */
2429 async _startScreencast(): Promise<void> {
2430 ++this.#screencastSessionCount;
2431 if (!this.#startScreencastPromise) {
2432 this.#startScreencastPromise = this.mainFrame()
2433 .client.send('Page.startScreencast', {format: 'png'})
2434 .then(() => {
2435 // Wait for the first frame.
2436 return new Promise(resolve => {
2437 return this.mainFrame().client.once('Page.screencastFrame', () => {
2438 return resolve();
2439 });
2440 });
2441 });
2442 }
2443 await this.#startScreencastPromise;
2444 }
2445
2446 /**
2447 * @internal
2448 */
2449 async _stopScreencast(): Promise<void> {
2450 --this.#screencastSessionCount;
2451 if (!this.#startScreencastPromise) {
2452 return;
2453 }
2454 this.#startScreencastPromise = undefined;
2455 if (this.#screencastSessionCount === 0) {
2456 await this.mainFrame().client.send('Page.stopScreencast');
2457 }
2458 }
2459
2460 /**
2461 * Gets the native, non-emulated dimensions of the viewport.
2462 */
2463 async #getNativePixelDimensions(): Promise<
2464 readonly [width: number, height: number, devicePixelRatio: number]
2465 > {
2466 const viewport = this.viewport();
2467 using stack = new DisposableStack();
2468 if (viewport && viewport.deviceScaleFactor !== 0) {
2469 await this.setViewport({...viewport, deviceScaleFactor: 0});
2470 stack.defer(() => {
2471 void this.setViewport(viewport).catch(debugError);
2472 });
2473 }
2474 return await this.mainFrame()
2475 .isolatedRealm()
2476 .evaluate(() => {
2477 return [
2478 window.visualViewport!.width * window.devicePixelRatio,
2479 window.visualViewport!.height * window.devicePixelRatio,
2480 window.devicePixelRatio,
2481 ] as const;
2482 });
2483 }
2484
2485 /**
2486 * Captures a screenshot of this {@link Page | page}.
2487 *
2488 * @param options - Configures screenshot behavior.
2489 *
2490 * @remarks
2491 *
2492 * While a screenshot is being taken in a {@link BrowserContext}, the
2493 * following methods will automatically wait for the screenshot to
2494 * finish to prevent interference with the screenshot process:
2495 * {@link BrowserContext.newPage}, {@link Browser.newPage},
2496 * {@link Page.close}.
2497 *
2498 * Calling {@link Page.bringToFront} will not wait for existing
2499 * screenshot operations.
2500 *
2501 */
2502 async screenshot(
2503 options: Readonly<ScreenshotOptions> & {encoding: 'base64'},
2504 ): Promise<string>;
2505 async screenshot(options?: Readonly<ScreenshotOptions>): Promise<Uint8Array>;
2506 @guarded(function () {
2507 return this.browser();
2508 })
2509 async screenshot(
2510 userOptions: Readonly<ScreenshotOptions> = {},
2511 ): Promise<Uint8Array | string> {
2512 using _guard = await this.browserContext().startScreenshot();
2513
2514 const options = {
2515 ...userOptions,
2516 clip: userOptions.clip
2517 ? {
2518 ...userOptions.clip,
2519 }
2520 : undefined,
2521 };
2522 if (options.type === undefined && options.path !== undefined) {
2523 const filePath = options.path;
2524 // Note we cannot use Node.js here due to browser compatibility.
2525 const extension = filePath
2526 .slice(filePath.lastIndexOf('.') + 1)
2527 .toLowerCase();
2528 switch (extension) {
2529 case 'png':
2530 options.type = 'png';
2531 break;
2532 case 'jpeg':
2533 case 'jpg':
2534 options.type = 'jpeg';
2535 break;
2536 case 'webp':
2537 options.type = 'webp';
2538 break;
2539 }
2540 }
2541 if (options.quality !== undefined) {
2542 if (options.quality < 0 || options.quality > 100) {
2543 throw new Error(
2544 `Expected 'quality' (${options.quality}) to be between 0 and 100, inclusive.`,
2545 );
2546 }
2547 if (
2548 options.type === undefined ||
2549 !['jpeg', 'webp'].includes(options.type)
2550 ) {
2551 throw new Error(
2552 `${options.type ?? 'png'} screenshots do not support 'quality'.`,
2553 );
2554 }
2555 }
2556 if (options.clip) {
2557 if (options.clip.width <= 0) {
2558 throw new Error("'width' in 'clip' must be positive.");
2559 }
2560 if (options.clip.height <= 0) {
2561 throw new Error("'height' in 'clip' must be positive.");
2562 }
2563 }
2564
2565 setDefaultScreenshotOptions(options);
2566
2567 await using stack = new AsyncDisposableStack();
2568 if (options.clip) {
2569 if (options.fullPage) {
2570 throw new Error("'clip' and 'fullPage' are mutually exclusive");
2571 }
2572
2573 options.clip = roundRectangle(normalizeRectangle(options.clip));
2574 } else {
2575 if (options.fullPage) {
2576 // If `captureBeyondViewport` is `false`, then we set the viewport to
2577 // capture the full page. Note this may be affected by on-page CSS and
2578 // JavaScript.
2579 if (!options.captureBeyondViewport) {
2580 const scrollDimensions = await this.mainFrame()
2581 .isolatedRealm()
2582 .evaluate(() => {
2583 const element = document.documentElement;
2584 return {
2585 width: element.scrollWidth,
2586 height: element.scrollHeight,
2587 };
2588 });
2589 const viewport = this.viewport();
2590 await this.setViewport({
2591 ...viewport,
2592 ...scrollDimensions,
2593 });
2594 stack.defer(async () => {
2595 await this.setViewport(viewport).catch(debugError);
2596 });
2597 }
2598 } else {
2599 options.captureBeyondViewport = false;
2600 }
2601 }
2602
2603 const data = await this._screenshot(options);
2604 if (options.encoding === 'base64') {
2605 return data;
2606 }
2607
2608 const typedArray = stringToTypedArray(data, true);
2609 await this._maybeWriteTypedArrayToFile(options.path, typedArray);
2610 return typedArray;
2611 }
2612
2613 /**
2614 * @internal
2615 */
2616 abstract _screenshot(options: Readonly<ScreenshotOptions>): Promise<string>;
2617
2618 /**
2619 * Generates a PDF of the page with the `print` CSS media type.
2620 *
2621 * @param options - options for generating the PDF.
2622 *
2623 * @remarks
2624 *
2625 * To generate a PDF with the `screen` media type, call
2626 * {@link Page.emulateMediaType | `page.emulateMediaType('screen')`} before
2627 * calling `page.pdf()`.
2628 *
2629 * By default, `page.pdf()` generates a pdf with modified colors for printing.
2630 * Use the
2631 * {@link https://developer.mozilla.org/en-US/docs/Web/CSS/-webkit-print-color-adjust | `-webkit-print-color-adjust`}
2632 * property to force rendering of exact colors.
2633 */
2634 abstract createPDFStream(
2635 options?: PDFOptions,
2636 ): Promise<ReadableStream<Uint8Array>>;
2637
2638 /**
2639 * {@inheritDoc Page.createPDFStream}
2640 */
2641 abstract pdf(options?: PDFOptions): Promise<Uint8Array>;
2642
2643 /**
2644 * The page's title
2645 *
2646 * @remarks
2647 *
2648 * Shortcut for {@link Frame.title | page.mainFrame().title()}.
2649 */
2650 async title(): Promise<string> {
2651 return await this.mainFrame().title();
2652 }
2653
2654 abstract close(options?: {runBeforeUnload?: boolean}): Promise<void>;
2655
2656 /**
2657 * Indicates that the page has been closed.
2658 * @returns
2659 */
2660 abstract isClosed(): boolean;
2661
2662 /**
2663 * {@inheritDoc Mouse}
2664 */
2665 abstract get mouse(): Mouse;
2666
2667 /**
2668 * This method fetches an element with `selector`, scrolls it into view if
2669 * needed, and then uses {@link Page.mouse} to click in the center of the
2670 * element. If there's no element matching `selector`, the method throws an
2671 * error.
2672 *
2673 * @remarks
2674 *
2675 * Bear in mind that if `click()` triggers a navigation event and
2676 * there's a separate `page.waitForNavigation()` promise to be resolved, you
2677 * may end up with a race condition that yields unexpected results. The
2678 * correct pattern for click and wait for navigation is the following:
2679 *
2680 * ```ts
2681 * const [response] = await Promise.all([
2682 * page.waitForNavigation(waitOptions),
2683 * page.click(selector, clickOptions),
2684 * ]);
2685 * ```
2686 *
2687 * Shortcut for {@link Frame.click | page.mainFrame().click(selector[, options]) }.
2688 * @param selector -
2689 * {@link https://pptr.dev/guides/page-interactions#selectors | selector}
2690 * to query the page for.
2691 * {@link https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors | CSS selectors}
2692 * can be passed as-is and a
2693 * {@link https://pptr.dev/guides/page-interactions#non-css-selectors | Puppeteer-specific selector syntax}
2694 * allows quering by
2695 * {@link https://pptr.dev/guides/page-interactions#text-selectors--p-text | text},
2696 * {@link https://pptr.dev/guides/page-interactions#aria-selectors--p-aria | a11y role and name},
2697 * and
2698 * {@link https://pptr.dev/guides/page-interactions#xpath-selectors--p-xpath | xpath}
2699 * and
2700 * {@link https://pptr.dev/guides/page-interactions#querying-elements-in-shadow-dom | combining these queries across shadow roots}.
2701 * Alternatively, you can specify the selector type using a
2702 * {@link https://pptr.dev/guides/page-interactions#prefixed-selector-syntax | prefix}. If there are
2703 * multiple elements satisfying the `selector`, the first will be clicked
2704 * @param options - `Object`
2705 * @returns Promise which resolves when the element matching `selector` is
2706 * successfully clicked. The Promise will be rejected if there is no element
2707 * matching `selector`.
2708 */
2709 click(selector: string, options?: Readonly<ClickOptions>): Promise<void> {
2710 return this.mainFrame().click(selector, options);
2711 }
2712
2713 /**
2714 * This method fetches an element with `selector` and focuses it. If
2715 * there's no element matching `selector`, the method throws an error.
2716 * @param selector -
2717 * {@link https://pptr.dev/guides/page-interactions#selectors | selector}
2718 * to query the page for.
2719 * {@link https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors | CSS selectors}
2720 * can be passed as-is and a
2721 * {@link https://pptr.dev/guides/page-interactions#non-css-selectors | Puppeteer-specific selector syntax}
2722 * allows quering by
2723 * {@link https://pptr.dev/guides/page-interactions#text-selectors--p-text | text},
2724 * {@link https://pptr.dev/guides/page-interactions#aria-selectors--p-aria | a11y role and name},
2725 * and
2726 * {@link https://pptr.dev/guides/page-interactions#xpath-selectors--p-xpath | xpath}
2727 * and
2728 * {@link https://pptr.dev/guides/page-interactions#querying-elements-in-shadow-dom | combining these queries across shadow roots}.
2729 * Alternatively, you can specify the selector type using a
2730 * {@link https://pptr.dev/guides/page-interactions#prefixed-selector-syntax | prefix}.
2731 * If there are multiple elements satisfying the selector, the first
2732 * will be focused.
2733 * @returns Promise which resolves when the element matching selector
2734 * is successfully focused. The promise will be rejected if there is
2735 * no element matching selector.
2736 *
2737 * @remarks
2738 *
2739 * Shortcut for
2740 * {@link Frame.focus | page.mainFrame().focus(selector)}.
2741 */
2742 focus(selector: string): Promise<void> {
2743 return this.mainFrame().focus(selector);
2744 }
2745
2746 /**
2747 * This method fetches an element with `selector`, scrolls it into view if
2748 * needed, and then uses {@link Page.mouse}
2749 * to hover over the center of the element.
2750 * If there's no element matching `selector`, the method throws an error.
2751 * @param selector -
2752 * {@link https://pptr.dev/guides/page-interactions#selectors | selector}
2753 * to query the page for.
2754 * {@link https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors | CSS selectors}
2755 * can be passed as-is and a
2756 * {@link https://pptr.dev/guides/page-interactions#non-css-selectors | Puppeteer-specific selector syntax}
2757 * allows quering by
2758 * {@link https://pptr.dev/guides/page-interactions#text-selectors--p-text | text},
2759 * {@link https://pptr.dev/guides/page-interactions#aria-selectors--p-aria | a11y role and name},
2760 * and
2761 * {@link https://pptr.dev/guides/page-interactions#xpath-selectors--p-xpath | xpath}
2762 * and
2763 * {@link https://pptr.dev/guides/page-interactions#querying-elements-in-shadow-dom | combining these queries across shadow roots}.
2764 * Alternatively, you can specify the selector type using a
2765 * {@link https://pptr.dev/guides/page-interactions#prefixed-selector-syntax | prefix}. If there are
2766 * multiple elements satisfying the `selector`, the first will be hovered.
2767 * @returns Promise which resolves when the element matching `selector` is
2768 * successfully hovered. Promise gets rejected if there's no element matching
2769 * `selector`.
2770 *
2771 * @remarks
2772 *
2773 * Shortcut for {@link Page.hover | page.mainFrame().hover(selector)}.
2774 */
2775 hover(selector: string): Promise<void> {
2776 return this.mainFrame().hover(selector);
2777 }
2778
2779 /**
2780 * Triggers a `change` and `input` event once all the provided options have been
2781 * selected. If there's no `<select>` element matching `selector`, the method
2782 * throws an error.
2783 *
2784 * @example
2785 *
2786 * ```ts
2787 * page.select('select#colors', 'blue'); // single selection
2788 * page.select('select#colors', 'red', 'green', 'blue'); // multiple selections
2789 * ```
2790 *
2791 * @param selector -
2792 * {@link https://pptr.dev/guides/page-interactions#selectors | selector}
2793 * to query the page for.
2794 * {@link https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors | CSS selectors}
2795 * can be passed as-is and a
2796 * {@link https://pptr.dev/guides/page-interactions#non-css-selectors | Puppeteer-specific selector syntax}
2797 * allows quering by
2798 * {@link https://pptr.dev/guides/page-interactions#text-selectors--p-text | text},
2799 * {@link https://pptr.dev/guides/page-interactions#aria-selectors--p-aria | a11y role and name},
2800 * and
2801 * {@link https://pptr.dev/guides/page-interactions#xpath-selectors--p-xpath | xpath}
2802 * and
2803 * {@link https://pptr.dev/guides/page-interactions#querying-elements-in-shadow-dom | combining these queries across shadow roots}.
2804 * Alternatively, you can specify the selector type using a
2805 * {@link https://pptr.dev/guides/page-interactions#prefixed-selector-syntax | prefix}.
2806 * @param values - Values of options to select. If the `<select>` has the
2807 * `multiple` attribute, all values are considered, otherwise only the first one
2808 * is taken into account.
2809 * @returns
2810 *
2811 * @remarks
2812 *
2813 * Shortcut for {@link Frame.select | page.mainFrame().select()}
2814 */
2815 select(selector: string, ...values: string[]): Promise<string[]> {
2816 return this.mainFrame().select(selector, ...values);
2817 }
2818
2819 /**
2820 * This method fetches an element with `selector`, scrolls it into view if
2821 * needed, and then uses {@link Page.touchscreen}
2822 * to tap in the center of the element.
2823 * If there's no element matching `selector`, the method throws an error.
2824 * @param selector -
2825 * {@link https://pptr.dev/guides/page-interactions#selectors | selector}
2826 * to query the page for.
2827 * {@link https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors | CSS selectors}
2828 * can be passed as-is and a
2829 * {@link https://pptr.dev/guides/page-interactions#non-css-selectors | Puppeteer-specific selector syntax}
2830 * allows quering by
2831 * {@link https://pptr.dev/guides/page-interactions#text-selectors--p-text | text},
2832 * {@link https://pptr.dev/guides/page-interactions#aria-selectors--p-aria | a11y role and name},
2833 * and
2834 * {@link https://pptr.dev/guides/page-interactions#xpath-selectors--p-xpath | xpath}
2835 * and
2836 * {@link https://pptr.dev/guides/page-interactions#querying-elements-in-shadow-dom | combining these queries across shadow roots}.
2837 * Alternatively, you can specify the selector type using a
2838 * {@link https://pptr.dev/guides/page-interactions#prefixed-selector-syntax | prefix}. If there are multiple elements satisfying the
2839 * selector, the first will be tapped.
2840 *
2841 * @remarks
2842 *
2843 * Shortcut for {@link Frame.tap | page.mainFrame().tap(selector)}.
2844 */
2845 tap(selector: string): Promise<void> {
2846 return this.mainFrame().tap(selector);
2847 }
2848
2849 /**
2850 * Sends a `keydown`, `keypress/input`, and `keyup` event for each character
2851 * in the text.
2852 *
2853 * To press a special key, like `Control` or `ArrowDown`, use {@link Keyboard.press}.
2854 * @example
2855 *
2856 * ```ts
2857 * await page.type('#mytextarea', 'Hello');
2858 * // Types instantly
2859 * await page.type('#mytextarea', 'World', {delay: 100});
2860 * // Types slower, like a user
2861 * ```
2862 *
2863 * @param selector -
2864 * {@link https://pptr.dev/guides/page-interactions#selectors | selector}
2865 * to query the page for.
2866 * {@link https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors | CSS selectors}
2867 * can be passed as-is and a
2868 * {@link https://pptr.dev/guides/page-interactions#non-css-selectors | Puppeteer-specific selector syntax}
2869 * allows quering by
2870 * {@link https://pptr.dev/guides/page-interactions#text-selectors--p-text | text},
2871 * {@link https://pptr.dev/guides/page-interactions#aria-selectors--p-aria | a11y role and name},
2872 * and
2873 * {@link https://pptr.dev/guides/page-interactions#xpath-selectors--p-xpath | xpath}
2874 * and
2875 * {@link https://pptr.dev/guides/page-interactions#querying-elements-in-shadow-dom | combining these queries across shadow roots}.
2876 * Alternatively, you can specify the selector type using a
2877 * {@link https://pptr.dev/guides/page-interactions#prefixed-selector-syntax | prefix}.
2878 * @param text - A text to type into a focused element.
2879 * @param options - have property `delay` which is the Time to wait between
2880 * key presses in milliseconds. Defaults to `0`.
2881 * @returns
2882 */
2883 type(
2884 selector: string,
2885 text: string,
2886 options?: Readonly<KeyboardTypeOptions>,
2887 ): Promise<void> {
2888 return this.mainFrame().type(selector, text, options);
2889 }
2890
2891 /**
2892 * Wait for the `selector` to appear in page. If at the moment of calling the
2893 * method the `selector` already exists, the method will return immediately. If
2894 * the `selector` doesn't appear after the `timeout` milliseconds of waiting, the
2895 * function will throw.
2896 *
2897 * @example
2898 * This method works across navigations:
2899 *
2900 * ```ts
2901 * import puppeteer from 'puppeteer';
2902 * (async () => {
2903 * const browser = await puppeteer.launch();
2904 * const page = await browser.newPage();
2905 * let currentURL;
2906 * page
2907 * .waitForSelector('img')
2908 * .then(() => console.log('First URL with image: ' + currentURL));
2909 * for (currentURL of [
2910 * 'https://example.com',
2911 * 'https://google.com',
2912 * 'https://bbc.com',
2913 * ]) {
2914 * await page.goto(currentURL);
2915 * }
2916 * await browser.close();
2917 * })();
2918 * ```
2919 *
2920 * @param selector -
2921 * {@link https://pptr.dev/guides/page-interactions#selectors | selector}
2922 * to query the page for.
2923 * {@link https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors | CSS selectors}
2924 * can be passed as-is and a
2925 * {@link https://pptr.dev/guides/page-interactions#non-css-selectors | Puppeteer-specific selector syntax}
2926 * allows quering by
2927 * {@link https://pptr.dev/guides/page-interactions#text-selectors--p-text | text},
2928 * {@link https://pptr.dev/guides/page-interactions#aria-selectors--p-aria | a11y role and name},
2929 * and
2930 * {@link https://pptr.dev/guides/page-interactions#xpath-selectors--p-xpath | xpath}
2931 * and
2932 * {@link https://pptr.dev/guides/page-interactions#querying-elements-in-shadow-dom | combining these queries across shadow roots}.
2933 * Alternatively, you can specify the selector type using a
2934 * {@link https://pptr.dev/guides/page-interactions#prefixed-selector-syntax | prefix}.
2935 * @param options - Optional waiting parameters
2936 * @returns Promise which resolves when element specified by selector string
2937 * is added to DOM. Resolves to `null` if waiting for hidden: `true` and
2938 * selector is not found in DOM.
2939 *
2940 * @remarks
2941 * The optional Parameter in Arguments `options` are:
2942 *
2943 * - `visible`: A boolean wait for element to be present in DOM and to be
2944 * visible, i.e. to not have `display: none` or `visibility: hidden` CSS
2945 * properties. Defaults to `false`.
2946 *
2947 * - `hidden`: Wait for element to not be found in the DOM or to be hidden,
2948 * i.e. have `display: none` or `visibility: hidden` CSS properties. Defaults to
2949 * `false`.
2950 *
2951 * - `timeout`: maximum time to wait for in milliseconds. Defaults to `30000`
2952 * (30 seconds). Pass `0` to disable timeout. The default value can be changed
2953 * by using the {@link Page.setDefaultTimeout} method.
2954 */
2955 async waitForSelector<Selector extends string>(
2956 selector: Selector,
2957 options: WaitForSelectorOptions = {},
2958 ): Promise<ElementHandle<NodeFor<Selector>> | null> {
2959 return await this.mainFrame().waitForSelector(selector, options);
2960 }
2961
2962 /**
2963 * Waits for the provided function, `pageFunction`, to return a truthy value when
2964 * evaluated in the page's context.
2965 *
2966 * @example
2967 * {@link Page.waitForFunction} can be used to observe a viewport size change:
2968 *
2969 * ```ts
2970 * import puppeteer from 'puppeteer';
2971 * (async () => {
2972 * const browser = await puppeteer.launch();
2973 * const page = await browser.newPage();
2974 * const watchDog = page.waitForFunction('window.innerWidth < 100');
2975 * await page.setViewport({width: 50, height: 50});
2976 * await watchDog;
2977 * await browser.close();
2978 * })();
2979 * ```
2980 *
2981 * @example
2982 * Arguments can be passed from Node.js to `pageFunction`:
2983 *
2984 * ```ts
2985 * const selector = '.foo';
2986 * await page.waitForFunction(
2987 * selector => !!document.querySelector(selector),
2988 * {},
2989 * selector,
2990 * );
2991 * ```
2992 *
2993 * @example
2994 * The provided `pageFunction` can be asynchronous:
2995 *
2996 * ```ts
2997 * const username = 'github-username';
2998 * await page.waitForFunction(
2999 * async username => {
3000 * const githubResponse = await fetch(
3001 * `https://api.github.com/users/${username}`,
3002 * );
3003 * const githubUser = await githubResponse.json();
3004 * // show the avatar
3005 * const img = document.createElement('img');
3006 * img.src = githubUser.avatar_url;
3007 * // wait 3 seconds
3008 * await new Promise((resolve, reject) => setTimeout(resolve, 3000));
3009 * img.remove();
3010 * },
3011 * {},
3012 * username,
3013 * );
3014 * ```
3015 *
3016 * @param pageFunction - Function to be evaluated in browser context until it returns a
3017 * truthy value.
3018 * @param options - Options for configuring waiting behavior.
3019 */
3020 waitForFunction<
3021 Params extends unknown[],
3022 Func extends EvaluateFunc<Params> = EvaluateFunc<Params>,
3023 >(
3024 pageFunction: Func | string,
3025 options?: FrameWaitForFunctionOptions,
3026 ...args: Params
3027 ): Promise<HandleFor<Awaited<ReturnType<Func>>>> {
3028 return this.mainFrame().waitForFunction(pageFunction, options, ...args);
3029 }
3030
3031 /**
3032 * This method is typically coupled with an action that triggers a device
3033 * request from an api such as WebBluetooth.
3034 *
3035 * :::caution
3036 *
3037 * This must be called before the device request is made. It will not return a
3038 * currently active device prompt.
3039 *
3040 * :::
3041 *
3042 * @example
3043 *
3044 * ```ts
3045 * const [devicePrompt] = Promise.all([
3046 * page.waitForDevicePrompt(),
3047 * page.click('#connect-bluetooth'),
3048 * ]);
3049 * await devicePrompt.select(
3050 * await devicePrompt.waitForDevice(({name}) => name.includes('My Device')),
3051 * );
3052 * ```
3053 */
3054 abstract waitForDevicePrompt(
3055 options?: WaitTimeoutOptions,
3056 ): Promise<DeviceRequestPrompt>;
3057
3058 /** @internal */
3059 override [disposeSymbol](): void {
3060 return void this.close().catch(debugError);
3061 }
3062
3063 /** @internal */
3064 [asyncDisposeSymbol](): Promise<void> {
3065 return this.close();
3066 }
3067}
3068
3069/**
3070 * @internal
3071 */
3072export const supportedMetrics = new Set<string>([
3073 'Timestamp',
3074 'Documents',
3075 'Frames',
3076 'JSEventListeners',
3077 'Nodes',
3078 'LayoutCount',
3079 'RecalcStyleCount',
3080 'LayoutDuration',
3081 'RecalcStyleDuration',
3082 'ScriptDuration',
3083 'TaskDuration',
3084 'JSHeapUsedSize',
3085 'JSHeapTotalSize',
3086]);
3087
3088/** @see https://w3c.github.io/webdriver-bidi/#normalize-rect */
3089function normalizeRectangle<BoundingBoxType extends BoundingBox>(
3090 clip: Readonly<BoundingBoxType>,
3091): BoundingBoxType {
3092 return {
3093 ...clip,
3094 ...(clip.width < 0
3095 ? {
3096 x: clip.x + clip.width,
3097 width: -clip.width,
3098 }
3099 : {
3100 x: clip.x,
3101 width: clip.width,
3102 }),
3103 ...(clip.height < 0
3104 ? {
3105 y: clip.y + clip.height,
3106 height: -clip.height,
3107 }
3108 : {
3109 y: clip.y,
3110 height: clip.height,
3111 }),
3112 };
3113}
3114
3115function roundRectangle<BoundingBoxType extends BoundingBox>(
3116 clip: Readonly<BoundingBoxType>,
3117): BoundingBoxType {
3118 const x = Math.round(clip.x);
3119 const y = Math.round(clip.y);
3120 const width = Math.round(clip.width + clip.x - x);
3121 const height = Math.round(clip.height + clip.y - y);
3122 return {...clip, x, y, width, height};
3123}