Skip to main content

Overview

Locators provide a flexible way to find and interact with elements on the page. They support CSS selectors, XPath, and cross-iframe traversal.

Creating Locators

Locators are created from Page objects:
const page = await stagehand.context.newPage();

// Standard locator
const locator = page.locator(".submit-button");

// Deep locator (with iframe support)
const deepLocator = page.deepLocator("iframe >> .inner-button");

// Frame locator (target iframes)
const frameLocator = page.frameLocator("#my-iframe");

Locator Methods

Query Methods

first()

Get the first matching element.
const element = await locator.first();

last()

Get the last matching element.
const element = await locator.last();

nth()

Get the nth matching element (0-indexed).
const element = await locator.nth(2); // Third element

count()

Get the number of matching elements.
const count = await locator.count();
console.log(`Found ${count} elements`);

all()

Get all matching elements.
const elements = await locator.all();
for (const el of elements) {
  await el.click();
}

Interaction Methods

click()

Click the element.
await locator.click();
await locator.click({ clickCount: 2 }); // Double click
options
object

fill()

Fill an input element.
await locator.fill("[email protected]");
value
string
required
Text to fill

press()

Press a key.
await locator.press("Enter");
await locator.press("Control+A");
key
string
required
Key name (e.g., “Enter”, “Escape”, “Control+C”)

type()

Type text character by character.
await locator.type("Hello world", { delay: 100 });
text
string
required
Text to type
options.delay
number
Delay between keystrokes in ms

hover()

Hover over the element.
await locator.hover();

focus()

Focus the element.
await locator.focus();

blur()

Remove focus from the element.
await locator.blur();

Content Methods

textContent()

Get the text content.
const text = await locator.textContent();
console.log(text);

innerText()

Get the inner text (visible text only).
const text = await locator.innerText();

innerHTML()

Get the inner HTML.
const html = await locator.innerHTML();

getAttribute()

Get an attribute value.
const href = await locator.getAttribute("href");
const id = await locator.getAttribute("id");

State Methods

isVisible()

Check if the element is visible.
const visible = await locator.isVisible();
if (visible) {
  await locator.click();
}

isHidden()

Check if the element is hidden.
const hidden = await locator.isHidden();

isEnabled()

Check if the element is enabled.
const enabled = await locator.isEnabled();

isDisabled()

Check if the element is disabled.
const disabled = await locator.isDisabled();

isChecked()

Check if a checkbox/radio is checked.
const checked = await locator.isChecked();

Wait Methods

waitFor()

Wait for the element to match a state.
await locator.waitFor({ state: "visible", timeout: 5000 });
options
object

Examples

Basic Element Interaction

import { Stagehand } from "@browserbasehq/stagehand";

const stagehand = new Stagehand({ env: "LOCAL" });
await stagehand.init();

const page = await stagehand.context.newPage();
await page.goto("https://example.com");

// Click a button
const button = page.locator(".submit-button");
await button.click();

// Fill a form
const email = page.locator("#email");
await email.fill("[email protected]");

const password = page.locator("#password");
await password.type("secret123", { delay: 50 });

// Check text content
const heading = page.locator("h1");
const text = await heading.textContent();
console.log("Heading:", text);

await stagehand.close();

Working with Multiple Elements

const page = await stagehand.context.newPage();
await page.goto("https://example.com");

// Count elements
const buttons = page.locator("button");
const count = await buttons.count();
console.log(`Found ${count} buttons`);

// Click first button
await buttons.first().click();

// Click last button
await buttons.last().click();

// Click specific button
await buttons.nth(2).click();

// Iterate all buttons
const allButtons = await buttons.all();
for (const button of allButtons) {
  const text = await button.textContent();
  console.log("Button text:", text);
}

Cross-iframe Locators

// Use >> to traverse into iframes
const deepLocator = page.deepLocator("iframe#checkout >> .payment-form >> input[name='card']");
await deepLocator.fill("4111111111111111");

// Or use frameLocator
const frame = page.frameLocator("#checkout-iframe");
const input = frame.locator(".card-number");
await input.fill("4111111111111111");

Wait for Elements

const page = await stagehand.context.newPage();
await page.goto("https://example.com");

// Wait for element to be visible
const modal = page.locator(".modal");
await modal.waitFor({ state: "visible", timeout: 5000 });

// Wait for element to disappear
const spinner = page.locator(".loading-spinner");
await spinner.waitFor({ state: "hidden" });

// Check visibility before interacting
const button = page.locator(".submit");
if (await button.isVisible()) {
  await button.click();
}

Form Handling

const page = await stagehand.context.newPage();
await page.goto("https://example.com/form");

// Fill text inputs
const name = page.locator("#name");
await name.fill("John Doe");

const email = page.locator("#email");
await email.fill("[email protected]");

// Select dropdown
const country = page.locator("#country");
await country.click();
await page.locator("option[value='US']").click();

// Check checkbox
const terms = page.locator("#terms");
if (!await terms.isChecked()) {
  await terms.click();
}

// Submit
const submit = page.locator("button[type='submit']");
await submit.click();

Get Element Attributes

const links = page.locator("a");
const allLinks = await links.all();

for (const link of allLinks) {
  const href = await link.getAttribute("href");
  const text = await link.textContent();
  console.log(`${text}: ${href}`);
}

Chaining Locators

// Find nested elements
const form = page.locator("form#login");
const emailField = form.locator("input[type='email']");
const submitButton = form.locator("button[type='submit']");

await emailField.fill("[email protected]");
await submitButton.click();

Using XPath

// XPath selector
const button = page.locator("xpath=//button[contains(text(), 'Submit')]");
await button.click();

// Mix CSS and XPath
const item = page.locator(".list >> xpath=.//span[@class='price']");
const price = await item.textContent();

Best Practices

  1. Use specific selectors:
    // Good
    page.locator("button#submit-order")
    
    // Less specific
    page.locator("button")
    
  2. Wait for elements before interacting:
    const button = page.locator(".submit");
    await button.waitFor({ state: "visible" });
    await button.click();
    
  3. Check element state:
    if (await button.isEnabled() && await button.isVisible()) {
      await button.click();
    }
    
  4. Use deep locators for iframes:
    // Instead of manual frame switching
    page.deepLocator("iframe >> .button")
    
  5. Iterate elements safely:
    const count = await locator.count();
    for (let i = 0; i < count; i++) {
      const el = locator.nth(i);
      // Process element
    }
    
  6. Handle missing elements:
    try {
      await locator.waitFor({ timeout: 5000 });
      await locator.click();
    } catch (error) {
      console.log("Element not found");
    }
    

Build docs developers (and LLMs) love