getByRole queries the accessibility tree — the same structure screen readers use. It is Playwright's most recommended locator for interactive elements.
Roles and Accessible Names
Every meaningful UI control has an implicit or explicit ARIA role: button, link, textbox, checkbox, heading, etc. The accessible name comes from visible text, aria-label, or associated <label>.
getByRole('button', { name: 'Save' }) finds a button whose accessible name includes 'Save'. Use { exact: true } when partial matches are too loose.
Roles match ARIA semantics — a <div onclick> without role won't appear as button.
Common Roles
button | link | textbox | checkbox | radio
heading | listitem | row | cell | dialog
navigation | main | alert | status
Match role to element semantics, not visual appearance.
name option filters by accessible name (substring by default).
checked, expanded, selected refine form and menu locators.
Headings support { level: 1 } through { level: 6 }.
getByRole Examples
Everyday patterns for typical UI controls.
UI Element
Locator
Submit button
getByRole('button', { name: 'Submit' })
Nav link
getByRole('link', { name: 'Home' })
Email field
getByRole('textbox', { name: 'Email' })
Modal
getByRole('dialog')
Error alert
getByRole('alert')
Data table row
getByRole('row', { name: 'John' })
Menu item
getByRole('menuitem', { name: 'Copy' })
Tab
getByRole('tab', { name: 'Settings' })
Implicit vs Explicit Roles
Native HTML elements get implicit roles: <button> → button, <a href> → link. Custom components need explicit role attributes or you should use getByTestId / getByLabel instead.
If getByRole fails, check Accessibility pane in DevTools.
Ask developers to use semantic HTML before adding test ids.
Radix/shadcn components often expose correct roles when composed properly.
Using the name Option
When multiple elements share a role, pass { name: 'Submit' } matching visible text or aria-label. Without name, strict mode may fail if more than one match exists.
Common Mistakes
Using role button on non-button elements without verifying accessibility tree.
Omitting name and matching dozens of generic buttons.
Confusing textbox with searchbox or spinbutton.
Not using { exact: true } when 'Save' matches 'Save draft'.
Key Takeaways
getByRole aligns tests with accessibility and user perception.
Accessible name comes from text, labels, or aria-label.
Semantic HTML makes role locators easy; fix markup when they fail.
Use role-specific options like checked and level.
Pro Tip
Enable axe in dev — if a control has no accessible name, getByRole will struggle and real users with screen readers will too.
Continue with getByText to build on what you learned here.