What is a Locator?
A Locator in Playwright is a lazy, re-queryable handle to an element. Instead of grabbing a DOM node once, Playwright resolves it every time you act on it — which is exactly why auto-waiting and retries work so reliably.
const submit = page.getByRole('button', { name: 'Submit' });
await submit.click();getByRole — the recommended default
Role-based locators mirror how assistive tech sees your page. They're stable and improve accessibility at the same time.
await page.getByRole('link', { name: 'Sign in' }).click();
await page.getByRole('textbox', { name: 'Email' }).fill('a@b.com');
await page.getByRole('checkbox', { name: 'Remember me' }).check();getByText — visible copy
Use getByText for visible strings the user actually reads. Prefer exact matches when the text is short and unique.
await page.getByText('Welcome back').isVisible();
await page.getByText('Delete', { exact: true }).click();getByTestId — when semantics are missing
For custom widgets without roles, add data-testid attributes and use them. This is the escape hatch, not the default.
await page.getByTestId('shopping-cart').click();CSS and XPath (last resort)
CSS is fine for structural queries; XPath is powerful but brittle. Reach for them only when the semantic APIs cannot express what you need.
page.locator('css=nav >> a.active');
page.locator('xpath=//table//tr[td[text()="John"]]');Chaining and Filtering
Compose locators to scope queries — this eliminates flaky global selectors.
const row = page.getByRole('row', { name: /John/ });
await row.getByRole('button', { name: 'Edit' }).click();
page.getByRole('listitem').filter({ hasText: 'Product 2' });Best Practices
- Prefer getByRole > getByLabel > getByPlaceholder > getByText > getByTestId > CSS/XPath.
- Never assert or act on a raw element handle — use Locators.
- Use filter() and chaining instead of long CSS selectors.
- Avoid indexes like nth(3) — they break when the DOM changes.
Get Playwright tutorials in your inbox
Weekly tips, real-world examples, and framework patterns – no spam, unsubscribe anytime.