# Page interactions Puppeteer allows you interact with the pages in various ways. ## Locators Locators is a new, experimental API that combines the functionalities of waiting and actions. With additional precondition checks, it enables automatic retries for failed actions, resulting in more reliable and less flaky automation scripts. :::note Locators API is experimental and we will not follow semver for breaking changes in the Locators API. ::: ### Use cases #### Waiting for an element ```ts await page.locator('button').wait(); ``` The following preconditions are automatically checked: - Waits for the element to become [visible](https://pptr.dev/api/puppeteer.elementhandle.isvisible/) or hidden. #### Waiting for a function ```ts await page .locator(() => { let resolve!: (node: HTMLCanvasElement) => void; const promise = new Promise(res => { return (resolve = res); }); const observer = new MutationObserver(records => { for (const record of records) { if (record.target instanceof HTMLCanvasElement) { resolve(record.target); } } }); observer.observe(document); return promise; }) .wait(); ``` #### Clicking an element ```ts await page.locator('button').click(); ``` The following preconditions are automatically checked: - Ensures the element is in the viewport. - Waits for the element to become [visible](https://pptr.dev/api/puppeteer.elementhandle.isvisible/) or hidden. - Waits for the element to become enabled. - Waits for the element to have a stable bounding box over two consecutive animation frames. #### Clicking an element matching a criteria ```ts await page .locator('button') .filter(button => !button.disabled) .click(); ``` The following preconditions are automatically checked: - Ensures the element is in the viewport. - Waits for the element to become [visible](https://pptr.dev/api/puppeteer.elementhandle.isvisible/) or hidden. - Waits for the element to become enabled. - Waits for the element to have a stable bounding box over two consecutive animation frames. #### Filling out an input ```ts await page.locator('input').fill('value'); ``` Automatically detects the input type and choose an appropriate way to fill it out with the provided value. The following preconditions are automatically checked: - Ensures the element is in the viewport. - Waits for the element to become [visible](https://pptr.dev/api/puppeteer.elementhandle.isvisible/) or hidden. - Waits for the element to become enabled. - Waits for the element to have a stable bounding box over two consecutive animation frames. #### Retrieving an element property ```ts const enabled = await page .locator('button') .map(button => !button.disabled) .wait(); ``` #### Hover over an element ```ts await page.locator('div').hover(); ``` The following preconditions are automatically checked: - Ensures the element is in the viewport. - Waits for the element to become [visible](https://pptr.dev/api/puppeteer.elementhandle.isvisible/) or hidden. - Waits for the element to have a stable bounding box over two consecutive animation frames. #### Scroll an element ```ts await page.locator('div').scroll({ scrollLeft: 10, scrollTop: 20, }); ``` The following preconditions are automatically checked: - Ensures the element is in the viewport. - Waits for the element to become [visible](https://pptr.dev/api/puppeteer.elementhandle.isvisible/) or hidden. - Waits for the element to have a stable bounding box over two consecutive animation frames. ### Configuring locators Locators can be configured to tune configure the preconditions and other other options: ```ts await page .locator('button') .setEnsureElementIsInTheViewport(false) .setTimeout(0) .setVisibility(null) .setWaitForEnabled(false) .setWaitForStableBoundingBox(false) .click(); ``` ### Getting locator events Currently, locators support a single event that notifies you when the locator is about to perform the action: ```ts let willClick = false; await page .locator('button') .on(LocatorEvent.Action, () => { willClick = true; }) .click(); ``` This event can be used for logging/debugging or other purposes. The event might fire multiple times if the locator retries the action. ## Query Selectors Queries are the primary mechanism for interacting with the DOM on your site. For example, a typical workflow goes like: ```ts // Import puppeteer import puppeteer from 'puppeteer'; (async () => { // Launch the browser const browser = await puppeteer.launch(); // Create a page const page = await browser.newPage(); // Go to your site await page.goto('YOUR_SITE'); // Query for an element handle. const element = await page.waitForSelector('div > .class-name'); // Do something with element... await element.click(); // Just an example. // Dispose of handle await element.dispose(); // Close browser. await browser.close(); })(); ``` ### `P` Selectors Puppeteer uses a superset of the CSS selector syntax for querying. We call this syntax _P selectors_ and it's supercharged with extra capabilities such as deep combinators and text selection. :::caution Although P selectors look like real CSS selectors (we intentionally designed it this way), they should not be used for actually CSS styling. They are designed only for Puppeteer. ::: :::note P selectors only work on the first "depth" of selectors; for example, `:is(div >>> a)` will not work. ::: #### `>>>` and `>>>>` combinators The `>>>` and `>>>>` are called _deep descendent_ and _deep_ combinators respectively. Both combinators have the effect of going into shadow hosts with `>>>` going into every shadow host under a node and `>>>>` going into the immediate one (if the node is a shadow host; otherwise, it's a no-op). :::note A common question is when should `>>>>` be chosen over `>>>` considering the flexibility of `>>>`. A similar question can be asked about `>` and a space; choose `>` if you do not need to query all elements under a given node and a space otherwise. This answer extends to `>>>>` (`>`) and `>>>` (space) naturally. ::: ##### Example Suppose we have the markup ```html

Light content

``` > Note: `