QA & Testing Tools

E2E Locator Generator

Paste an HTML snippet or a whole page, pick an element and get resilient locators for Playwright, Cypress and Selenium, ranked from role and test id down to fragile positional selectors, with a uniqueness check for every candidate.

Private by design: anything you enter is processed in your browser only. It is never uploaded to or logged on our servers. Your HTML is parsed into an inert document: scripts and event handlers in it never run. Share links carry the HTML inside the link itself.

Pick an element

Interactive elements are shown in bold. The tree is built from a parsed copy of your HTML, not rendered.

Selected element
Nothing selected.

    About resilient end-to-end locators

    Most flaky UI tests are not caused by the application but by locators that break when the page changes: a CSS class renamed during a redesign, an auto-generated id that differs between builds, or an nth-child path that shifts when a banner is added. A resilient locator describes the element the way a user or the test contract does (its role and accessible name, its label, or a dedicated test id), so it keeps working through refactors and fails only when the behaviour really changed.

    This generator parses your HTML with the browser's DOMParser into an inert document, lists every element in a tree, and for the element you pick computes its implicit ARIA role (a <button> is a button, an <a href> a link, an <input type="email"> a textbox, a <select> a combobox), a simplified accessible name (from aria-labelledby, aria-label, an associated <label>, alt text or text content) and every other usable hook: test id, placeholder, title, id, name, text, classes and position. Each candidate is converted to idiomatic Playwright, Cypress and Selenium code and checked against the whole snippet. Non-unique candidates are flagged and ranked lower, and when an exact match or a scoping container (such as a product card with its own test id) makes a role locator unique, that variant is offered.

    Ids that look generated (long digit runs, React :r1: ids, hash-like strings) and utility or CSS-module classes (px-4, css-1q2w3e, Button_root__x7Yz2) are recognised and demoted with an explanation. Because the document is not rendered, CSS visibility from stylesheets, shadow DOM and iframes are not taken into account; inline style="display:none", hidden and aria-hidden are. Always run the chosen locator against the real page, for example with Playwright's codegen and locator picker or the XPath & CSS selector tester.

    Good locators make good steps: pair them with readable scenarios checked by the Gherkin formatter, clean up minified markup with the HTML beautifier before pasting it here, and match dynamic text in assertions with the regex tester.

    Reference Guide

    Recommended locator order. Playwright's documentation lists its built-in locators as getByRole, getByText, getByLabel, getByPlaceholder, getByAltText, getByTitle and getByTestId, and recommends prioritising role locators and user-facing attributes. Testing Library publishes an explicit priority, which is a good default for any framework:

    PriorityPlaywrightCypress / Selenium equivalentWhen to use
    1getByRole('button', { name: 'Sign in' })cy.contains('button', 'Sign in'); XPath //button[normalize-space()='Sign in']Almost anything interactive or structural: buttons, links, inputs, headings, checkboxes
    2getByLabel('Email address')cy.get('#email') via the label's for; XPath through //labelForm fields with a visible label
    3getByPlaceholder('you@example.com')[placeholder="…"]Inputs without a label (fix the missing label too)
    4getByText('Create an account')cy.contains('p', '…'); XPath normalize-space()Non-interactive text: paragraphs, messages, badges
    5getByAltText('Acme Store')img[alt="…"]Images and image inputs
    6getByTitle('Close')[title="…"]Elements identified only by a tooltip title
    7getByTestId('login-submit')cy.get('[data-cy="…"]'); By.cssSelector("[data-testid='…']")When text and role are ambiguous or change often (translations, dynamic copy). An explicit contract that never breaks on copy edits
    Last resortlocator('css=…'), locator('xpath=…')By.id, By.name, CSS, XPathStable hand-written ids and names are fine; avoid styling classes and positions

    Playwright's getByTestId reads data-testid by default; change it with use: { testIdAttribute: 'data-cy' } in playwright.config or selectors.setTestIdAttribute(). Cypress's best-practice guide uses data-cy, data-test or data-testid. Name, text, label, placeholder, alt and title matching in Playwright is case-insensitive and substring-based unless you pass { exact: true }.

    Implicit ARIA roles of common HTML elements (used by getByRole):

    HTMLImplicit roleAccessible name from
    <button>, <input type="submit|button|reset|image">buttonText content / value / alt
    <a href>, <area href>linkText content (including image alt) / alt
    <a> without hrefnone (generic)Not reachable with getByRole('link')
    <input> text, email, tel, url (or no type), <textarea>textboxLabel, then title, then placeholder
    <input type="search">searchboxLabel
    Text-like input with a list attributecomboboxLabel
    <input type="password">noneUse getByLabel
    <input type="checkbox"> / radiocheckbox / radioLabel
    <input type="number"> / rangespinbutton / sliderLabel
    <select> / with multiple or size > 1combobox / listboxLabel
    <option>optionText content
    <h1>…<h6>heading (level: 1–6)Text content
    <img alt="…"> / <img alt="">img / presentationalt
    <ul>, <ol> / <li>list / listitemnone
    <table>, <tr>, <td>, <th>table, row, cell, columnheadercaption / text content
    <nav>, <main>, <aside>navigation, main, complementaryaria-label
    <header> / <footer> (not inside article, aside, main, nav or section)banner / contentinfoaria-label
    <form> / <section> with an accessible nameform / regionaria-label, aria-labelledby
    <dialog>, <fieldset>, <hr>, <progress>dialog, group, separator, progressbarvaries (<legend> for fieldset)

    An explicit role="…" attribute overrides the implicit role.

    Locator anti-patterns:

    AvoidWhy it breaksInstead
    /html/body/div[2]/div/form/div[3]/buttonAny wrapper or sibling change shifts the pathRole + name, or a test id
    #input-38271, #\:r1\:, #ember412Generated ids change between builds, renders or sessionsLabel or a stable test id
    .btn.btn-primary.px-4, .css-1q2w3e4Styling and CSS-in-JS classes change with design work and buildsRole, label or test id
    li:nth-child(3) button, cy.get('button').eq(2)Order depends on data, sorting and feature flagsScope to a container: getByTestId('product-EB-200').getByRole('button')
    .first() to silence a non-unique matchHides ambiguity; clicks whatever happens to be firstMake the locator unique, or filter with hasText / has
    Long exact text with punctuation or counts, e.g. "Cart (2)"Copy edits, translations and dynamic numbersSubstring or regex, a test id, or a role name without the volatile part
    XPath with contains(@class, 'btn')Also matches btn-secondary, nobtn and so onExact class token, or better a semantic locator

    Example input

    <form id="login-form">
      <label for="email">Email address</label>
      <input type="email" id="email" name="email" placeholder="you@example.com">
      <button type="submit" class="btn btn-primary" data-testid="login-submit">Sign in</button>
    </form>
    
    Selected: input#email
    → page.getByRole('textbox', { name: 'Email address' })
    → page.getByLabel('Email address')
    → driver.findElement(By.id("email"))

    This sample loads automatically when you open the tool. Use Load Sample to bring it back.

    Frequently Asked Questions

    Prefer locators that match what users see: role with accessible name, label, placeholder or text, or a dedicated test id. Avoid long CSS chains and positional selectors, which break when the layout changes.

    The generator writes locators for Playwright, Cypress and Selenium (Java and Python).

    More than one element in the snippet matches it. Add a test id, use a more specific accessible name or scope the locator to a parent element.