Specnote
Back to the blog
playwright locatorsPlaywrightE2E testingconceptSpecnote

What are Playwright locators? Writing tests that survive a redesign

By WonyoungAugust 21, 20266 min
On this page

Before a test can click a button, it has to point at that button. Playwright locators are how it points. Playwright ships seven of them, and which one you pick decides whether your suite keeps running after a redesign or stops all at once. This post covers how to choose among the seven, and the three cases where tests stop anyway.

Key takeaways

Playwright locators are seven built-in ways for a test to find an element on the page. Pointing by what users see — role, text, label — survives changes to markup and styling. What remains is deciding whether a change to the UI was intended. No tool answers that.

What "finding an element" means

Ask a person to click the sign-in button and they just do it. They look for the thing that says Sign in and click it.

A machine cannot work from that sentence. To a machine the page is a nested structure of boxes and text, and something has to say which node is the sign-in button. That is what a locator does.

There is more than one way to point at the same button.

  • The second element inside the third box from the top
  • The element whose class is btn-primary
  • The button labeled Sign in

All three point at the same button right now. But the moment the page changes, they part ways. Add a wrapper element and the first one stops. Rename a class during a redesign and the second one stops. The third keeps working as long as the button still says Sign in.

That is exactly the principle Playwright built its locators around.

Same button pointed at three different ways and what happens after a redesignHow you point at an element decides whether it survives a redesign

The seven Playwright locators

The Playwright documentation lists seven built-in locators and recommends prioritizing the ones based on user-facing attributes.

LocatorFinds byWhere it fits
getByRoleRole and accessible nameButtons, links, headings, inputs — most things
getByTextVisible textParagraphs, notices
getByLabelThe label attached to an inputForm fields
getByPlaceholderPlaceholder textInputs without a visible label
getByAltTextImage alt textImages
getByTitleThe title attributeElements with tooltips
getByTestIdA marker the developer plantedWhen none of the six above can reach it

The first six share something. They are what a person actually perceives when looking at the page — the words on a button, the label beside a field, the description of an image. They key off meaning rather than structure.

The seven Playwright locators arranged in three priority tiersPlaywright locators recommend pointing by what users see first

Pointing at the sign-in button
await page.getByRole('button', { name: 'Sign in' }).click();

That line does not care where the button sits or which container holds it. If the role is button and the name is Sign in, it finds it.

Why getByRole comes first

Of the seven, Playwright recommends getByRole first. It points using two things: a role and a name.

The role is what the element does on the page — button, link, heading, checkbox — a classification the browser already understands. The name is the human-readable text attached to it.

Pointing by role and name
await expect(page.getByRole('heading', { name: 'Sign up' })).toBeVisible();
await page.getByRole('checkbox', { name: 'Subscribe' }).check();
await page.getByRole('button', { name: /submit/i }).click();

There is a side effect worth knowing. Role and name are the same information a screen reader uses to read a page. So an element you cannot reach with getByRole is usually an element assistive technology cannot read either. Writing tests surfaces accessibility problems before anyone files them.

When pointing is hard, look at the markup before reaching for a different locator. Often the thing that looks like a button is not a button, or the clickable area has no accessible name.

Three cases where tests stop anyway

Good locators do not remove every failure. Three cases come up repeatedly.

1. The text changed. Rename "Sign in" to "Get started" and a locator that pointed by name no longer finds it. That is not the test being wrong. The page genuinely changed, and the test told you. It just told you by failing, which means a person has to look every time.

2. Several elements share a name. A list with ten Delete buttons cannot be resolved by name alone. Narrow the scope instead.

Narrowing the scope before pointing
await page.getByRole('listitem')
  .filter({ hasText: 'Order 1024' })
  .getByRole('button', { name: 'Delete' })
  .click();

3. The page is not ready yet. While data loads, the button does not exist. Playwright waits for elements to appear by default, so most of this is handled for you. If your page renders in several stages, you still have to decide what to wait on.

Four rules for tests that last

Put together, it comes to this.

  1. Point by what users see. Text, labels, roles. Markup structure and class names are the last resort.
  2. Make each locator resolve to exactly one element. If several match, narrow the scope.
  3. Plant markers only when needed. getByTestId is for when the other six cannot reach an element. Tagging every element up front weighs down both the markup and the suite.
  4. When a test stops, look at the page first. Confirm the change was intended before touching the test. Reverse that order and you end up with a passing suite and a broken page.

Rule 4 is the one that slips most often in practice. The fastest way to make a failing test pass is to edit the test, and after a few rounds of that the suite only knows how to pass.

This is not a Playwright problem

Read this far and locators can look like the source of maintenance cost. They are not.

Lifting element selection up to what users perceive is something Playwright did particularly well. Compared with the older approach of leaning on markup structure, tests stop far less often. Auto-waiting comes from the same idea.

What remains is not the kind of thing a tool can settle. It is deciding whether a change to the page was intended. That decision needs a standard for what the correct state is, and that standard does not live in the code.

Keep readingWhat Is Playwright MCP? 7 Strengths and 3 Ways to Chooseplaywright mcpplaywright8 min

Teams that keep suites alive for years do not stop at writing good locators. When the UI changes they confirm what changed, agree on the new scope, and then update the tests. In that order the suite never drifts into passing for its own sake. The codegen post landed on the same place from a different direction.

Keep readingWhat Is Playwright Codegen? 2 Ways to Get Test Code Writtenplaywright codegenplaywright7 min

Specnote turns that order into a product

Specnote lets people who cannot read code follow the same order. AI lists what it built, a person reviews that list and approves it, and only the approved scope runs in a real browser. No locators to write.

If you can read and edit code, writing them yourself in Playwright is more precise. Follow the rules above and most of the maintenance goes away. What we aim at is the case where nobody has the time or the person to do that.


Technical details in this post were verified against the Playwright documentation on Locators on August 21, 2026.

Frequently asked questions

  • What are Playwright locators?

    They are how a test finds a specific element on the page. Before clicking a button, something has to say which button. Playwright has seven built-in locators that find elements by role, text, label and similar attributes.

  • Can I use CSS selectors?

    You can, and sometimes you need to. CSS selectors lean on markup structure and class names, so they tend to stop when the design is touched. The official docs recommend user-facing attributes first for the same reason.

  • When should I use getByTestId?

    When none of the role, text or label options can reach the element — an icon-only button is the classic case. The developer plants a marker and the test finds it. Tagging everything up front is not recommended.

  • A test failed. Should I just fix the test?

    Check the page first. If you edit the test without checking, you can end up with a passing test and a page that is actually broken. Once that order sets in, the suite stops being worth maintaining.

  • Can I do e2e testing without reading code?

    Writing locators yourself requires reading code. The alternative is a setup where a person approves what should be checked from a list and a tool runs it. That is how Specnote works. > [!CTA] > Approve a list instead of writing locators > > Approve what should be checked once, and every time the UI changes we run that scope in a real browser again. No code to read. > > Start free

Keep reading

If you enjoyed this post