# Ego-Browser Element Resolver Selector Forms: Complete Guide to 7 Locator Types

> Master ego-browser's element resolver with our complete guide. Learn all 7 selector forms including CSS, ARIA, href, XPath, text locators, and more to find elements efficiently.

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

---

**Ego-browser's element resolver supports seven distinct selector forms including reference IDs (`@N`), CSS locators (`loc=css:`), ARIA role locators (`loc=role:`), href locators (`loc=href:`), XPath expressions (`xpath=`), raw CSS selectors, and text locators (`loc=text:`).**

The element resolver is the core translation layer in [citrolabs/ego-lite](https://github.com/citrolabs/ego-lite) that converts high-level selector strings into concrete DOM references for browser automation agents. Understanding these **ego-browser element resolver selector forms** is essential for writing reliable automation scripts.

## Reference Selector Form (`@N`)

The **reference form** uses a snapshot reference ID to fetch elements directly from the most recent snapshot map.

This is the fastest resolution method because it bypasses DOM querying entirely. The numeric ID corresponds to the `backendNodeId` captured during page snapshots.

```javascript
// Click element with reference ID 15 from the latest snapshot
await click('@15')

// Reference IDs persist across navigation within the same session
await click('@42')

```

Reference selectors are defined in [`src/element-resolver.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/element-resolver.ts) where the resolver checks for the `@` prefix before delegating to snapshot-based lookup routines.

## CSS Locator Form (`loc=css:`)

The **CSS locator form** executes standard CSS selectors against the page DOM using `querySelectorAll`.

```javascript
// Explicit CSS locator with prefix
await click('loc=css:button.primary')

// Target nested elements
await click('loc=css:nav ul li:first-child')

// Combine with pseudo-selectors
await click('loc=css:input:focus')

```

The resolver strips the `loc=css:` prefix and passes the remaining string to the browser's native CSS selector engine. This form supports the full CSS selector specification.

## Raw CSS Form (No Prefix)

**Bare CSS selectors without any prefix** are treated as CSS locators for backward compatibility.

```javascript
// Implicit CSS selector - identical behavior to loc=css:
await click('.nav-item.active')

// Complex nested selector
await click('div.article > p.intro')

// Attribute selectors work unchanged
await click('[data-testid="submit"]')

```

This legacy form exists in [`src/element-resolver.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/element-resolver.ts) as a fallback when no recognized prefix is detected. The resolver applies the same `querySelectorAll` execution path as explicit CSS locators.

## ARIA Role Locator Form (`loc=role:`)

The **ARIA role locator form** queries the browser's Accessibility Tree to find elements by their semantic role.

```javascript
// Find first button role in accessibility tree
await click('loc=role:button')

// Target navigation landmark
await click('loc=role:navigation')

// Interactive elements
await click('loc=role:link')
await click('loc=role:textbox')

```

This form is particularly valuable for accessibility-first automation and resilient scripts that survive DOM restructuring. The resolver interfaces with Chrome DevTools Protocol accessibility domains in [`src/element-resolver.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/element-resolver.ts).

## Href Locator Form (`loc=href:`)

The **href locator form** targets anchor (`<a>`) elements by matching their `href` attribute values.

```javascript
// Exact URL match
await click('loc=href:https://example.com/login')

// Partial path matching
await click('loc=href:/dashboard')

// Query string inclusion
await click('loc=href:?tab=settings')

```

The resolver performs substring matching against the full `href` attribute, making partial matches practical for dynamic URLs. This form is implemented alongside other prefixed locators in the main resolver logic.

## XPath Locator Form (`xpath=`)

The **XPath form** evaluates full XPath 1.0 expressions against the document.

```javascript
// Element by tag and attribute
await click('xpath=//div[@class="content"]')

// Text-based selection
await click('xpath=//button[text()="Continue"]')

// Complex predicates
await click('xpath=//input[@type="email" and @required]')

```

The resolver passes XPath expressions to the browser's native XPath engine. Error handling distinguishes between malformed expressions (permanent errors) and valid expressions returning no matches (transient errors).

## Text Locator Form (`loc=text:`)

The **text locator form** (available in later versions) finds elements by their visible text content.

```javascript
// Exact text match
await click('loc=text:Sign In')

// Case-sensitive matching
await click('loc=text:Logout')

// Multi-word strings
await click('loc=text:Add to Cart')

```

Text resolution performs exact string matching against rendered text nodes. This form requires the most careful handling of whitespace and capitalization.

## Error Classification in Element Resolution

The resolver throws `ElementResolutionError` instances defined in [`src/errors.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/errors.ts). These errors carry a **transient/permanent classification**:

- **Transient errors**: DOM not ready, element temporarily detached — trigger retry loops
- **Permanent errors**: Invalid selector syntax, unsupported form — fail immediately

This classification enables higher-level wait logic in [`src/helpers.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/helpers.ts) functions like `click()` and `type()` to implement intelligent retry strategies.

## Selector Form Resolution Pipeline

The complete resolution flow in [`src/element-resolver.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/element-resolver.ts) follows this precedence:

1. Check for `@` prefix → reference lookup
2. Check for `loc=css:` prefix → explicit CSS query
3. Check for `loc=role:` prefix → accessibility tree query
4. Check for `loc=href:` prefix → anchor href matching
5. Check for `loc=text:` prefix → visible text search
6. Check for `xpath=` prefix → XPath evaluation
7. No prefix detected → implicit CSS query

Each branch delegates to specialized resolvers or browser protocol methods, then returns normalized element references to [`src/element-ops.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/element-ops.ts) for interaction.

## Summary

- **Reference selectors** (`@N`) offer fastest resolution via snapshot IDs
- **CSS locators** support both explicit (`loc=css:`) and implicit (raw) forms
- **ARIA role locators** query the accessibility tree for semantic matching
- **Href locators** target links by URL pattern matching
- **XPath locators** enable complex document traversal expressions
- **Text locators** find elements by exact visible text content
- Error classification in [`src/errors.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/errors.ts) distinguishes retryable from fatal failures

## Frequently Asked Questions

### How does ego-browser choose which selector form to use?

The resolver examines the selector string for recognized prefixes in fixed precedence order. Prefixes like `@`, `loc=`, and `xpath=` trigger specific resolution branches, while unprefixed strings default to CSS selection. This logic is centralized in [`src/element-resolver.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/element-resolver.ts).

### When should I use reference selectors versus CSS locators?

Use **reference selectors** (`@N`) for maximum speed when element stability is guaranteed. Use **CSS locators** when elements may move in the DOM or when scripting across multiple page states where snapshot IDs become invalid.

### What happens if a selector matches multiple elements?

The resolver returns the first matching element for all selector forms except where explicitly noted. For CSS and XPath forms, this corresponds to `querySelectorAll()[0]` behavior. Use more specific selectors or XPath predicates to target precise elements.

### Are text locators available in all ego-browser versions?

The `loc=text:` form was added in later versions. Check your `package/ego-browser` version against the repository changelog. Earlier versions throw `ElementResolutionError` with permanent classification for unrecognized prefix types.