Skip to content

Playwright Locators

Locators are Playwright's primary way to find elements. They are strict, auto-waiting, and designed for user-facing queries rather than brittle CSS paths.

The Locator Model

A locator describes how to find element(s) on the page. Playwright re-evaluates locators before each action, so stale element references are rare compared to older WebDriver patterns.

Prefer user-facing locators (getByRole, getByLabel, getByText) over CSS/XPath. Use getByTestId when roles are ambiguous.

await page.getByRole('button', { name: 'Submit' }).click();
await page.getByLabel('Email').fill('a@b.com');
await page.getByTestId('cart-count').textContent();
await page.locator('.legacy-widget').getByText('Open');

Chain .locator() to scope searches; prefer role/label at the top level.

Core Locator Methods

page.getByRole(role, { name, exact })
page.getByLabel(text)
page.getByPlaceholder(text)
page.getByText(text)
page.getByTestId(id)
page.locator(selector)  // CSS only when necessary
  • getByRole reflects accessibility tree — closest to how users perceive UI.
  • getByLabel targets form controls by associated label.
  • getByTestId uses data-testid configured via testIdAttribute.
  • .first(), .last(), .nth(n) select among matches — use sparingly.

Locator Methods Reference

Choose locators in this priority order.

Method Best For
getByRole Buttons, links, headings, checkboxes
getByLabel Inputs with visible labels
getByPlaceholder Inputs identified by placeholder
getByText Static text not tied to a role
getByTestId Custom stable hooks from devs
getByAltText Images
getByTitle Elements with title attribute
locator('css') Last resort legacy markup

Filtering and Chaining

const row = page.getByRole('row').filter({ hasText: 'Product A' });
await row.getByRole('button', { name: 'Delete' }).click();

await page
  .getByRole('listitem')
  .filter({ has: page.getByRole('checkbox', { checked: true }) })
  .count();

Strict Mode and Single Match

Actions require exactly one matching element by default. If zero or multiple match, Playwright throws with a helpful error listing candidates — fix locators instead of forcing .first() without reason.

Common Mistakes

  • CSS selectors tied to styling classes that change frequently.
  • Using .nth(3) when a role+name or filter would be stable.
  • Creating locators once before navigation and reusing after full page reload without re-querying.
  • XPath copied from DevTools when a role locator exists.

Key Takeaways

  • Locators are lazy and re-resolved before actions.
  • Prefer role, label, and test id over CSS.
  • Strict mode catches ambiguous selectors early.
  • Filter and chain to scope within tables and lists.

Pro Tip

Run npx playwright codegen on problematic pages — it suggests locators in priority order Playwright itself prefers.