--- id: locators title: "Locators" --- [Locator]s are the central piece of Playwright's auto-waiting and retry-ability. In a nutshell, locators represent a way to find element(s) on the page at any moment. ### Quick Guide These are the recommended built in locators. - [`method: Page.getByRole`](#locate-by-role) to locate by explicit and implicit accessibility attributes. - [`method: Page.getByText`](#locate-by-text) to locate by text content. - [`method: Page.getByLabel`](#locate-by-label) to locate a form control by associated label's text. - [`method: Page.getByPlaceholder`](#locate-by-placeholder) to locate an input by placeholder. - [`method: Page.getByAltText`](#locate-by-alt-text) to locate an element, usually image, by its text alternative. - [`method: Page.getByTitle`](#locate-by-title) to locate an element by its title attribute. - [`method: Page.getByTestId`](#locate-by-testid) to locate an element based on its `data-testid` attribute (other attributes can be configured). ```js await page.getByLabel('User Name').fill('John'); await page.getByLabel('Password').fill('secret-password'); await page.getByRole('button', { name: 'Sign in' }).click(); await expect(page.getByText('Welcome, John!')).toBeVisible(); ``` ```java page.getByLabel("User Name").fill("John"); page.getByLabel("Password").fill("secret-password"); page.getByRole(AriaRole.BUTTON, new Page.GetByRoleOptions().setName("Sign in")).click(); assertThat(page.getByText("Welcome, John!")).isVisible(); ``` ```python async await page.get_by_label("User Name").fill("John") await page.get_by_label("Password").fill("secret-password") await page.get_by_role("button", name="Sign in").click() await expect(page.get_by_text("Welcome, John!")).to_be_visible() ``` ```python sync page.get_by_label("User Name").fill("John") page.get_by_label("Password").fill("secret-password") page.get_by_role("button", name="Sign in").click() expect(page.get_by_text("Welcome, John!")).to_be_visible() ``` ```csharp await page.GetByLabel("User Name").FillAsync("John"); await page.GetByLabel("Password").FillAsync("secret-password"); await page.GetByRole("button", new() { NameString = "Sign in" }).ClickAsync(); await Expect(page.GetByText("Welcome, John!")).ToBeVisibleAsync(); ``` ## Locating elements Playwright comes with multiple built-in locators. To make tests resilient, we recommend prioritizing user-facing attributes and explicit contracts such as [`method: Page.getByRole`]. For example, consider the following DOM structure. ```html ``` Locate the element by its role of `button` with name "Sign in". ```js await page.getByRole('button', { name: 'Sign in' }) .click(); ``` ```java page.getByRole(AriaRole.BUTTON, new Page.GetByRoleOptions().setName("Sign in")) .click(); ``` ```python async await page.get_by_role("button", name="Sign in").click() ``` ```python sync page.get_by_role("button", name="Sign in").click() ``` ```csharp await page.GetByRole("button", new() { NameString = "Sign in" }) .ClickAsync(); ``` :::tip Use the [code generator](./codegen.md) to generate a locator, and then edit it as you'd like. ::: Every time a locator is used for an action, an up-to-date DOM element is located in the page. In the snippet below, the underlying DOM element will be located twice, once prior to every action. This means that if the DOM changes in between the calls due to re-render, the new element corresponding to the locator will be used. ```js const locator = page.getByRole('button', { name: 'Sign in' }) await locator.hover(); await locator.click(); ``` ```java Locator locator = page.getByRole(AriaRole.BUTTON, new Page.GetByRoleOptions().setName("Sign in")) locator.hover(); locator.click(); ``` ```python async locator = page.get_by_role("button", name="Sign in") await locator.hover() await locator.click() ``` ```python sync locator = page.get_by_role("button", name="Sign in") locator.hover() locator.click() ``` ```csharp var locator = page.GetByRole("button", new() { NameString = "Sign in" }) await locator.HoverAsync(); await locator.ClickAsync(); ``` Note that all methods that create a locator, such as [`method: Page.getByLabel`], are also available on the [Locator] and [FrameLocator] classes, so you can chain them and iteratively narrow down your locator. ```js const locator = page.frameLocator('#my-frame') .getByRole('button', { name: 'Sign in' }); await locator.click(); ``` ```java Locator locator = page.frameLocator("#my-frame") .getByRole(AriaRole.BUTTON, new Page.GetByRoleOptions().setName("Sign in")); locator.click(); ``` ```python async locator = page.frame_locator("#my-frame") .get_by_role("button", name="Sign in") await locator.click() ``` ```python sync locator = page.frame_locator("my-frame") .get_by_role("button", name="Sign in") locator.click() ``` ```csharp var locator = page.FrameLocator("#my-frame") .GetByRole("button", new() { NameString = "Sign in" }); await locator.ClickAsync(); ``` ### Locate by role The [`method: Page.getByRole`] locator reflects how users and assistive technology perceive the page, for example whether some element is a button or a checkbox. When locating by role, you should usually pass the accessible name as well, so that the locator pinpoints the exact element. For example, consider the following DOM structure. ```html