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
button
'left' | 'right' | 'middle'
Mouse button Default: "left"
Number of clicks Default: 1
Delay between clicks in ms
fill()
Fill an input element.
press()
Press a key.
await locator . press ( "Enter" );
await locator . press ( "Control+A" );
Key name (e.g., “Enter”, “Escape”, “Control+C”)
type()
Type text character by character.
await locator . type ( "Hello world" , { delay: 100 });
Delay between keystrokes in ms
hover()
Hover over the element.
focus()
Focus the element.
blur()
Remove focus from the element.
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 });
state
'attached' | 'detached' | 'visible' | 'hidden'
State to wait for Default: "visible"
Timeout in milliseconds Default: 30000
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
Use specific selectors :
// Good
page . locator ( "button#submit-order" )
// Less specific
page . locator ( "button" )
Wait for elements before interacting :
const button = page . locator ( ".submit" );
await button . waitFor ({ state: "visible" });
await button . click ();
Check element state :
if ( await button . isEnabled () && await button . isVisible ()) {
await button . click ();
}
Use deep locators for iframes :
// Instead of manual frame switching
page . deepLocator ( "iframe >> .button" )
Iterate elements safely :
const count = await locator . count ();
for ( let i = 0 ; i < count ; i ++ ) {
const el = locator . nth ( i );
// Process element
}
Handle missing elements :
try {
await locator . waitFor ({ timeout: 5000 });
await locator . click ();
} catch ( error ) {
console . log ( "Element not found" );
}