Skip to main content

Overview

The observe() method identifies elements on the page that match a description. It returns an array of Action objects that can be used with act() or inspected directly.

Syntax

const actions = await stagehand.observe();
const actions = await stagehand.observe(instruction, options?);

Parameters

instruction
string
Natural language description of elements to findIf omitted, returns all interactive elements on the pageExamples:
  • "buttons on the page"
  • "the submit button"
  • "all links in the navigation menu"
  • "form input fields"
options
ObserveOptions

Returns

returns
Promise<Action[]>
Array of Action objects representing found elements

Examples

Find All Interactive Elements

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");

// Get all interactive elements
const actions = await stagehand.observe();

console.log(`Found ${actions.length} interactive elements`);
actions.forEach((action, i) => {
  console.log(`${i + 1}. ${action.description}`);
});

await stagehand.close();

Find Specific Elements

// Find buttons
const buttons = await stagehand.observe("buttons on the page");
console.log(`Found ${buttons.length} buttons`);

// Find specific button
const submitButtons = await stagehand.observe("the submit button");
if (submitButtons.length > 0) {
  console.log("Submit button found:", submitButtons[0].description);
}

// Find form fields
const inputs = await stagehand.observe("input fields in the form");

Use with act()

// Find element first, then act on it
const actions = await stagehand.observe("the login button");

if (actions.length > 0) {
  const result = await stagehand.act(actions[0]);
  console.log("Clicked:", result.message);
}

Inspect Element Details

const actions = await stagehand.observe("all navigation links");

actions.forEach((action) => {
  console.log("Description:", action.description);
  console.log("Selector:", action.selector);
  console.log("Method:", action.method);
  console.log("---");
});

Scoped Observation

// Only look within header
const headerButtons = await stagehand.observe("buttons", {
  selector: "header",
});

// Only look within specific form
const formInputs = await stagehand.observe("input fields", {
  selector: "#login-form",
});

Find Multiple Element Types

// Find all links
const links = await stagehand.observe("links on the page");

// Find all buttons
const buttons = await stagehand.observe("buttons on the page");

// Find all form inputs
const inputs = await stagehand.observe("form input fields");

// Find all dropdowns
const dropdowns = await stagehand.observe("dropdown menus");

With Custom Model

const actions = await stagehand.observe("interactive elements", {
  model: "anthropic/claude-3-5-sonnet-latest",
});

Multi-page Observation

const page1 = await stagehand.context.newPage();
const page2 = await stagehand.context.newPage();

await page1.goto("https://example.com");
await page2.goto("https://another.com");

// Observe on specific pages
const actions1 = await stagehand.observe("buttons", { page: page1 });
const actions2 = await stagehand.observe("buttons", { page: page2 });

console.log(`Page 1 buttons: ${actions1.length}`);
console.log(`Page 2 buttons: ${actions2.length}`);

Real-World Examples

Find and Click Menu Items

const menuItems = await stagehand.observe("menu items in the navigation");

// Find specific menu item
const settingsMenu = menuItems.find((item) =>
  item.description.toLowerCase().includes("settings")
);

if (settingsMenu) {
  await stagehand.act(settingsMenu);
}

Find Form Fields and Fill Them

const formFields = await stagehand.observe(
  "input fields in the registration form"
);

for (const field of formFields) {
  console.log(`Found field: ${field.description}`);
  
  if (field.description.includes("email")) {
    await stagehand.act(`type '[email protected]' in this field`, {
      page: /* current page */,
    });
  }
}

Validate Page Elements

// Check if required elements exist
const requiredButtons = [
  "submit button",
  "cancel button",
  "help button",
];

for (const buttonDesc of requiredButtons) {
  const found = await stagehand.observe(buttonDesc);
  
  if (found.length === 0) {
    console.error(`Missing: ${buttonDesc}`);
  } else {
    console.log(`✓ Found: ${buttonDesc}`);
  }
}
const footerLinks = await stagehand.observe("links in the footer", {
  selector: "footer",
});

const linkDescriptions = footerLinks.map((link) => link.description);
console.log("Footer links:", linkDescriptions);

Find Dynamic Elements

// Wait for page to load
await page.waitForLoadState("networkidle");

// Find elements that may have loaded dynamically
const dynamicButtons = await stagehand.observe(
  "action buttons in the modal dialog"
);

if (dynamicButtons.length > 0) {
  console.log("Modal is open");
  await stagehand.act(dynamicButtons[0]);
}

Compare Pages

const page1Actions = await stagehand.observe("buttons", { page: page1 });
const page2Actions = await stagehand.observe("buttons", { page: page2 });

const diff = {
  onlyInPage1: page1Actions.length - page2Actions.length,
  page1Buttons: page1Actions.map((a) => a.description),
  page2Buttons: page2Actions.map((a) => a.description),
};

console.log("Difference:", diff);

Best Practices

  1. Be specific in descriptions:
    // Good
    observe("the blue submit button in the form")
    
    // Less specific
    observe("button")
    
  2. Check array length before using:
    const actions = await stagehand.observe("login button");
    if (actions.length > 0) {
      await stagehand.act(actions[0]);
    }
    
  3. Use scoped selectors for efficiency:
    // Faster and more accurate
    observe("buttons", { selector: ".toolbar" })
    
  4. Combine with act() for reliable workflows:
    const element = await stagehand.observe("specific button");
    if (element.length > 0) {
      await stagehand.act(element[0]);
    }
    
  5. Inspect element properties:
    const actions = await stagehand.observe("all links");
    actions.forEach((action) => {
      console.log(`Element: ${action.description}`);
      console.log(`Selector: ${action.selector}`);
    });
    
  6. Use for validation and testing:
    // Verify expected elements exist
    const requiredElements = await stagehand.observe("required elements");
    expect(requiredElements.length).toBeGreaterThan(0);
    

Build docs developers (and LLMs) love