Skip to main content
BAP defines 10 selector types. Each is a JSON object with a type field and type-specific properties. Selectors are used throughout the protocol in action methods, observations, and extraction.

Selector Types

TypeStabilityBest For
testIdHighestElements with data-testid attributes
roleHighButtons, textboxes, links by ARIA role + name
refHighStable references from agent/observe output
labelHighForm inputs with associated labels
textMediumElements with visible text content
placeholderMediumInputs with placeholder text
cssLowDirect CSS selectors
xpathLowXPath expressions
semanticVariableAI-resolved natural language descriptions
coordinatesLowestPixel coordinates (last resort)

JSON Format

testId

Target elements by their data-testid attribute. Most resilient to redesigns.
{ "type": "testId", "value": "submit-button" }

role

Target elements by ARIA role and optional accessible name. The recommended default for interactive elements.
{ "type": "role", "role": "button", "name": "Submit" }
Roles follow the WAI-ARIA specification. Common roles: button, textbox, link, checkbox, combobox, heading, tab, menuitem.

ref

Use stable references returned by agent/observe. Refs persist across observations for the same element.
{ "type": "ref", "value": "@submitBtn" }
Refs are the most efficient selector type for repeat interactions. Call agent/observe once, then use the returned refs for all subsequent actions.

text

Match elements by their visible text content (case-sensitive).
{ "type": "text", "value": "Sign in" }

label

Target form inputs by their associated <label> text.
{ "type": "label", "value": "Email address" }

placeholder

Target inputs by their placeholder text.
{ "type": "placeholder", "value": "Search..." }

testId

Target elements by data-testid attribute.
{ "type": "testId", "value": "login-form" }

css

Direct CSS selector. Use when semantic selectors are insufficient.
{ "type": "css", "value": "#login-btn" }
CSS selectors are brittle — they break when the DOM structure changes. Prefer semantic selectors when possible.

xpath

XPath expression for complex DOM traversals.
{ "type": "xpath", "value": "//button[@type='submit']" }

semantic

Natural language description of the target element. The server resolves this to a concrete selector using accessibility tree analysis.
{ "type": "semantic", "description": "the login button" }

coordinates

Pixel coordinates on the page. Use as a last resort when no other selector type works.
{ "type": "coordinates", "x": 100, "y": 200 }

Alternative Selectors

Each InteractiveElement returned by agent/observe includes an optional alternativeSelectors array — multiple selector options ordered by reliability (most reliable first):
  1. testIddata-testid attribute (most stable, survives redesigns)
  2. role + name — ARIA role with accessible name
  3. css #id — Element ID (escaped for CSS special chars)
  4. text — Visible text content (if under 50 characters)
  5. css path — Full CSS path (least stable, but always unique)
Agents can choose the most appropriate selector based on their reliability needs. The primary selector field contains the best available option.

Selector Resolution Priority

When the server receives a selector, it resolves it in this order:
  1. Cached CSS selector — If the element was previously observed, the cached CSS path is used first (fastest)
  2. Direct resolution — The selector is resolved against the current DOM
  3. Self-healing fallback — If the primary selector fails, the server tries fallback identity signals: testId then ariaLabel+role then id then name

SDK Helpers

Both the TypeScript and Python SDKs provide factory functions for building selectors:
import { role, text, label, testId, css, xpath, ref } from "@browseragentprotocol/client";

await client.click(role("button", "Submit"));
await client.fill(label("Email"), "user@example.com");
await client.click(text("Sign in"));
await client.click(testId("submit-btn"));
await client.click(ref("@e1"));