# Supported Element Target Forms for Resolution in ego-browser: Complete Reference Guide

> Discover supported element target forms in ego-browser including CSS selectors, XPath, text matchers, and more. Find the perfect locator for your automation needs.

- Repository: [CitroLabs/ego-lite](https://github.com/citrolabs/ego-lite)
- Tags: api-reference
- Published: 2026-08-29

---

**The `ego-browser` package supports 13 distinct element target forms including CSS selectors, XPath expressions, text/label/placeholder/alt/title/testid matchers, href locators, ARIA role selectors, and internal scoped/filtered queries.**

The `ego-browser` library provides a powerful element resolution system for browser automation. Understanding the supported **element target forms for resolution** is essential for writing reliable selectors that work across diverse web interfaces. This guide covers every selector type recognized by the `parseLocator` function in [`src/element-resolver.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/element-resolver.ts).

## Internal Query Selectors: Scoped and Filtered Resolution

The most advanced target forms use the `internal:` prefix to create composable, scoped queries.

### Internal Scope Queries

**Internal scope queries** allow you to define a base element and a child selector as a single target. In [`src/element-resolver.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/element-resolver.ts), the parser detects `internal:scope:` and returns `{kind: "query", …}` for downstream resolution.

```typescript
// Scope query: find button inside #parent
await ego.cdp('internal:scope:{"base":"#parent","child":"button"}');

```

### Internal Filter Queries

**Internal filter queries** add visibility and content constraints. The parser recognizes `internal:filter:` at lines 31-33 and constructs complex filter objects.

```typescript
// Filter query: section containing "Welcome" text
await ego.cdp('internal:filter:{"base":"section","hasText":{"text":"Welcome"}}');

```

## Nth Modifiers: Position-Based Selection

The `parseLocator` function in [`src/element-resolver.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/element-resolver.ts) extracts optional **nth modifiers** before primary parsing (lines 17-23). These let you target specific match positions.

| Modifier | Syntax | Purpose |
|----------|--------|---------|
| `nth=N` | `internal:nth=2;css:#btn` | Select the Nth match (1-indexed) |
| `last` | `internal:last;xpath=//div` | Select the final match |

## CSS Selectors: Standard and Shorthand Forms

**CSS selectors** are the default resolution strategy. The parser handles both explicit and implicit forms at lines 36-39.

```typescript
// Explicit CSS with loc= prefix
await ego.cdp('loc=css:.my-class');

// Shorthand (no prefix)
await ego.cdp('.my-class');

```

When no recognized prefix is detected and `nth` is present, the system falls back to CSS selector resolution (lines 112-117).

## XPath Selectors: Precise DOM Navigation

**XPath expressions** provide powerful DOM traversal. Detected by the `xpath=` prefix at lines 40-44.

```typescript
await ego.cdp('xpath=//div[@id="root"]');
await ego.cdp('xpath=//a[contains(@href, "/settings")]');

```

## Href Selectors: Exact Path Matching

**Href selectors** resolve elements by their `href` attribute value. Recognized at lines 45-48 with the `href:` prefix.

```typescript
await ego.cdp('href:/login');
await ego.cdp('href:/dashboard');

```

## Text Selectors: Visible Content Matching

The `parseLocator` function handles **text selectors** through two syntax variants (lines 49-60):

| Variant | Prefix | Behavior |
|---------|--------|----------|
| Non-exact | `text=` | Substring match |
| Exact | `text:` or `text:exact:` | Full string match |

```typescript
// Non-exact (substring) match
await ego.cdp('text=Sign in');

// Exact match
await ego.cdp('text:exact:Confirm');

```

The `parseTextLocator` helper creates appropriate matcher objects for each variant.

## Attribute-Based Selectors: Label, Placeholder, Alt, Title, TestID

`ego-browser` provides dedicated selectors for common element attributes, all parsed similarly to text selectors:

### Label Selectors

Lines 61-66 handle `label:` prefix for form element labels.

```typescript
await ego.cdp('label:Password');

```

### Placeholder Selectors

Lines 67-72 parse `placeholder:` for input hints.

```typescript
await ego.cdp('placeholder:Search…');

```

### Alt Selectors

Lines 73-78 handle `alt:` for image accessibility text.

```typescript
await ego.cdp('alt:Logo');
await ego.cdp('alt:User avatar');

```

### Title Selectors

Lines 79-84 parse `title:` for tooltip text.

```typescript
await ego.cdp('title:Page Title');
await ego.cdp('title:Help');

```

### Test-ID Selectors

Lines 85-90 handle `testid:` for data-testid attributes.

```typescript
await ego.cdp('testid:submitBtn');
await ego.cdp('testid:nav-item');

```

## Role Selectors: ARIA Accessibility Targets

**Role selectors** target elements by ARIA role with optional name filtering. Parsed at lines 101-108 with the `role:` prefix.

```typescript
// Role only
await ego.cdp('role:button');

// Role with name constraint
await ego.cdp('role:button[name="Submit"]');

```

The parser extracts both `role` and optional `name` properties into the locator object.

## Complete Code Reference: All Target Forms

```typescript
// 1. CSS selector
await ego.cdp('.login-button');
await ego.cdp('loc=css:.my-class');

// 2. XPath expression
await ego.cdp('xpath=//a[contains(@href, "/settings")]');

// 3. Href exact match
await ego.cdp('href:/dashboard');

// 4. Text substring
await ego.cdp('text=Sign in');

// 5. Text exact match
await ego.cdp('text:exact:Confirm');

// 6. Label text
await ego.cdp('label:Password');

// 7. Placeholder text
await ego.cdp('placeholder:Search…');

// 8. Alt attribute
await ego.cdp('alt:User avatar');

// 9. Title attribute
await ego.cdp('title:Help');

// 10. Test ID
await ego.cdp('testid:nav-item');

// 11. ARIA role with name
await ego.cdp('role:button[name="Submit"]');

// 12. Internal scope query
await ego.cdp('internal:scope:{"base":"#parent","child":"button"}');

// 13. Internal filter query
await ego.cdp('internal:filter:{"base":"section","hasText":{"text":"Welcome"}}');

// With nth modifiers
await ego.cdp('internal:nth=2;css:#btn');
await ego.cdp('internal:last;xpath=//div');

```

## How Resolution Works: From String to Element

According to the `citrolabs/ego-lite` source code, the resolution pipeline follows this sequence:

1. **`parseLocator`** in [`src/element-resolver.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/element-resolver.ts) parses the selector string into a **locator object** with a `kind` property
2. The resolver functions (`resolveElementCenter`, `resolveElementObjectId`, etc.) dispatch based on `kind`
3. **Evaluation helpers** in [`src/locator-query.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/locator-query.ts) (`queryAllExpression`, `textElementsExpression`, etc.) execute the appropriate DOM query in the browser context

Supported `kind` values: `"query"`, `"css"`, `"xpath"`, `"href"`, `"text"`, `"label"`, `"placeholder"`, `"alt"`, `"title"`, `"testid"`, `"role"`.

## Key Source Files

| File | Purpose |
|------|---------|
| [`src/element-resolver.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/element-resolver.ts) | Contains `parseLocator` function that defines all 13+ target forms |
| [`src/locator-query.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/locator-query.ts) | Provides browser-side evaluation expressions for each locator type |

## Summary

- **`ego-browser`** recognizes **13+ element target forms** for resolution, from simple CSS to complex internal queries
- **Core parser**: `parseLocator` in [`src/element-resolver.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/element-resolver.ts) handles all syntax recognition
- **Two advanced forms**: `internal:scope:` and `internal:filter:` enable composable, conditional element resolution
- **Attribute selectors** (label, placeholder, alt, title, testid) all follow consistent text-matching semantics
- **Role selectors** support ARIA patterns with optional name constraints for accessibility-first automation
- **Nth modifiers** (`nth=N`, `last`) work across all selector types for precise positional targeting

## Frequently Asked Questions

### What is the most reliable target form for flaky UIs?

**Role selectors** with explicit names (`role:button[name="Submit"]`) provide the most stability across DOM changes because they target accessibility semantics rather than implementation details. According to the `ego-browser` source in [`src/element-resolver.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/element-resolver.ts) (lines 101-108), these map directly to ARIA properties that remain consistent even when CSS classes or DOM structure vary.

### Can I combine multiple selector types in one target string?

Not directly—you must use **internal scope or filter queries** for composition. The `internal:scope:` and `internal:filter:` prefixes accept JSON objects that combine base selectors with child selectors or text constraints. See lines 31-33 in [`src/element-resolver.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/element-resolver.ts) for the parser implementation.

### Why does `text=Search` match differently than `text:Search`?

These trigger different parsing paths. `text=` (equals) creates a **non-exact substring matcher**, while `text:` (colon) routes through `parseTextLocator` which defaults to exact matching unless you specify `text:exact:`. This distinction exists at lines 49-60 of [`src/element-resolver.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/element-resolver.ts).