# What Locator Strategies Does ego-browser Support? A Complete Guide to Element Selection

> Discover the 11 locator strategies ego-browser supports for effortless element selection including CSS XPath ARIA roles text and more Learn effective techniques for web automation

- Repository: [CitroLabs/ego-lite](https://github.com/citrolabs/ego-lite)
- Tags: deep-dive
- Published: 2026-07-27

---

**ego-browser supports 11 distinct locator strategies including raw CSS selectors, XPath, ARIA roles, text matching, and specialized attribute-based locators like test-id, href, and placeholder, all parsed in [`src/locator-query.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/locator-query.ts).**

The ego-browser package from the citrolabs/ego-lite repository provides a flexible locator language that lets automation agents address page elements using multiple resolution strategies. Unlike standard browser automation tools that rely solely on CSS or XPath, ego-browser implements a hybrid resolver in [`src/locator-query.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/locator-query.ts) that supports semantic accessibility attributes, content-based matching, and internal filtering mechanisms.

## CSS and XPath Strategies

The resolver handles standard browser query languages alongside ego-browser's custom prefixes.

### Raw CSS Selectors

Any plain CSS selector (e.g., `#login button`) falls back to `querySelectorAll` on the document or a supplied root element. This provides full compatibility with standard CSS selector syntax without requiring a prefix.

### Explicit CSS

Use the prefix `loc=css:` to explicitly declare a CSS selector. While functionally identical to raw CSS, this format clarifies intent and integrates with ego-browser's uniform locator syntax.

### XPath Expressions

Prefix selectors with `xpath=` to execute `document.evaluate` against the DOM. This strategy returns matching nodes via native XPath evaluation, supporting complex traversal queries that exceed CSS selector capabilities.

## Attribute-Based Locators

ego-browser provides targeted strategies for matching specific HTML attributes commonly used in testing and accessibility.

### Test-ID

The `loc=testid:` prefix matches elements that have a `data-testid` attribute equal to the locator value. This is the preferred strategy for resilient test automation that avoids dependence on CSS structure.

### Href

Use `loc=href:` to find `<a>` elements whose `href` attribute matches the given path or full URL. This enables link resolution without relying on link text or CSS classes.

### Alt and Title

- **`loc=alt:`** matches `<img>` or `<input>` elements by their `alt` attribute.
- **`loc=title:`** resolves any element with a matching `title` attribute.

### Placeholder

The `loc=placeholder:` prefix targets `<input>` or `<textarea>` elements whose `placeholder` attribute matches the supplied string, useful for identifying form fields by their hint text.

## Content and Label Matching

These strategies locate elements based on their visible content or associated labels rather than structural attributes.

### Text Matching

Use `loc:text:` or the shorthand `text=` to find elements whose visible text contains or exactly matches the supplied string. The resolver performs text normalization to ensure reliable matching across different DOM structures.

### Label Association

The `loc=label:` prefix targets form elements associated with a `<label>` whose text matches the locator. This resolves the labeled element rather than the label itself, supporting semantic form interaction.

## ARIA Role Locators

The `role:` prefix enables resolution by accessibility semantics. It matches elements by their explicit `role` attribute or by their implicit DOM role (e.g., `<button>` automatically resolves as `button`).

You can optionally filter by accessible name using bracket syntax:

```javascript
await click('role:button[name=Submit]');

```

This resolves specifically to buttons with the accessible name "Submit", combining role semantics with content filtering.

## Advanced Internal Locators

For complex automation scenarios, ego-browser exposes internal composition mechanisms.

### Scope and Filter

The `internal:scope:` and `internal:filter:` prefixes allow composable queries that restrict searches to specific DOM subtrees or apply "has-text", "has", and "has-not" constraints. These are typically consumed by higher-level helpers rather than end-user scripts. For example:

```javascript
await click('internal:scope:{"base":"#main","child":"button.save"}');

```

This restricts the search for `button.save` to within the `#main` container.

## Resolver Priority and Implementation

The resolution engine in [`src/locator-query.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/locator-query.ts) (lines 47-118) evaluates locator strings through a strict precedence chain:

1. **Internal helpers** (`internal:` prefixes) are checked first.
2. **XPath** selectors (starting with `xpath=`) trigger `document.evaluate`.
3. **Explicit prefixes** (`css:`, `href:`, `text:`, `label:`, `placeholder:`, `alt:`, `title:`, `testid:`) generate specialized expressions after stripping the `loc=` wrapper.
4. **ARIA roles** matching the `role:` grammar trigger role-based resolution.
5. **Fallback** to plain CSS `querySelectorAll` for any unmatched string.

All strategies ultimately produce a JavaScript expression that returns an array of matching DOM elements.

## Practical Code Examples

Agents interact with these locators through helper functions defined in [`src/helpers.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/helpers.ts) (`click`, `type`, `upload`, etc.), which forward selector strings to the underlying resolver:

```javascript
// Click a button using a plain CSS selector
await click('#login button');

// Click a link by its exact href path
await click('loc=href:/settings/account');

// Type into an input identified by its placeholder text
await type('loc=placeholder:Email', 'alice@example.com');

// Click a menu item whose visible text contains "Dashboard"
await click('loc:text:Dashboard');

// Click a button by its ARIA role and name
await click('role:button[name=Submit]');

// Upload a file by selecting an <input type="file> using its data-testid
await upload('loc=testid:profile-photo-upload', './photo.png');

```

## Key Source Files

The locator system spans four primary files in the citrolabs/ego-lite repository:

- **[`src/locator-query.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/locator-query.ts)**: Central parser that converts locator strings into DOM-query expressions (see lines 47-118 for the strategy routing logic).
- **[`src/helpers.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/helpers.ts)**: Public API surface (`click`, `type`, `upload`) that accepts locator strings and delegates to the resolver.
- **[`src/element-resolver.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/element-resolver.ts)**: Calls `queryAllExpression` and translates returned element arrays into usable handles for further actions.
- **[`src/driver/locator.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/driver/locator.ts)**: Low-level driver that receives selectors, validates them, and routes them to the resolver.

## Summary

- **ego-browser supports 11 distinct locator strategies** ranging from standard CSS/XPath to semantic attributes, content matching, and internal composition mechanisms.
- The resolver in [`src/locator-query.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/locator-query.ts) prioritizes internal helpers first, then XPath, explicit prefixes, ARIA roles, and finally raw CSS selectors.
- **ARIA role locators** support both implicit roles (derived from HTML semantics) and explicit `role` attributes, with optional accessible name filtering.
- **Content-based locators** (`text`, `label`, `placeholder`) enable resilient element selection based on user-visible content rather than implementation details.
- **Internal scope/filter** locators provide advanced composability for restricting searches to subtrees and chaining multiple constraints.

## Frequently Asked Questions

### Does ego-browser support Playwright-style selectors?

Yes. The resolver supports Playwright-style "has-text" shortcuts (e.g., `selector:has-text("...")`) which are internally transformed into text filters. Additionally, standard CSS and XPath selectors are fully compatible with the system.

### What is the difference between `loc=text:` and `text=` prefixes?

Both prefixes trigger the same text-matching resolver in [`src/locator-query.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/locator-query.ts). The `loc=text:` format follows the explicit locator prefix convention used by other attribute strategies, while `text=` provides a shorthand syntax. Both locate elements whose normalized visible text contains or exactly matches the supplied string.

### How does the ARIA role locator handle implicit roles?

The `role:` prefix checks both explicit `role` attributes and implicit DOM semantics according to the HTML accessibility mapping specification. For example, an `<input type="checkbox">` without an explicit `role` attribute still resolves when using `role:checkbox` because the resolver recognizes its implicit ARIA semantics.

### Can I combine multiple locator strategies?

Yes, through the `internal:scope:` and `internal:filter:` prefixes. These advanced locators enable composable queries that can restrict a search to a specific DOM subtree (scope) or apply constraints like "has-text", "has", or "has-not". These are primarily used internally by higher-level helpers but are available for complex automation scenarios requiring chained conditions.