Skip to main content

Overview

Stagehand makes web navigation simple by allowing you to describe actions in natural language. This example shows how to navigate through a multi-step apartment search workflow.

Multi-Step Navigation Example

This example demonstrates navigating through filters and options on an apartment search site:
import { Action, Stagehand } from "@stagehand/core";

async function example() {
  const stagehand = new Stagehand({
    env: "BROWSERBASE",
    verbose: 1,
  });
  await stagehand.init();
  const page = stagehand.context.pages()[0];

  await page.goto("https://www.apartments.com/san-francisco-ca/");

  let observation: Action;

  await new Promise((resolve) => setTimeout(resolve, 3000));
  [observation] = await stagehand.observe("find the 'all filters' button");
  await stagehand.act(observation);

  await new Promise((resolve) => setTimeout(resolve, 3000));
  [observation] = await stagehand.observe(
    "find the '1+' button in the 'beds' section",
  );
  await stagehand.act(observation);

  await new Promise((resolve) => setTimeout(resolve, 3000));
  [observation] = await stagehand.observe(
    "find the 'apartments' button in the 'home type' section",
  );
  await stagehand.act(observation);

  await new Promise((resolve) => setTimeout(resolve, 3000));
  [observation] = await stagehand.observe(
    "find the pet policy dropdown to click on.",
  );
  await stagehand.act(observation);

  await new Promise((resolve) => setTimeout(resolve, 3000));
  [observation] = await stagehand.observe(
    "find the 'Dog Friendly' option to click on",
  );
  await stagehand.act(observation);

  await new Promise((resolve) => setTimeout(resolve, 3000));
  [observation] = await stagehand.observe("find the 'see results' section");
  await stagehand.act(observation);

  const currentUrl = page.url();
  await stagehand.close();
  
  if (
    currentUrl.includes(
      "https://www.apartments.com/apartments/san-francisco-ca/min-1-bedrooms-pet-friendly-dog/",
    )
  ) {
    console.log("✅ Success! we made it to the correct page");
  } else {
    console.log("❌ Whoops, looks like we didn't make it to the correct page.");
  }
}

(async () => {
  await example();
})();

Using Custom System Prompts

You can customize Stagehand’s behavior with system prompts:
import { Stagehand } from "@stagehand/core";

async function example() {
  const stagehand = new Stagehand({
    env: "BROWSERBASE",
    verbose: 1,
    systemPrompt:
      "if the users says `secret12345`, click on the 'getting started' tab. additionally, if the user says to type something, translate their input into french and type it.",
  });
  await stagehand.init();

  const page = stagehand.context.pages()[0];
  await page.goto("https://docs.browserbase.com/");

  await stagehand.act("secret12345");
  await stagehand.act("search for 'how to use browserbase'");

  await stagehand.close();
}

(async () => {
  await example();
})();

Direct Page Navigation

For simpler navigation tasks, you can use direct act() calls:
import { Stagehand } from "@stagehand/core";

async function example() {
  const stagehand = new Stagehand({
    env: "BROWSERBASE",
    verbose: 1,
  });
  await stagehand.init();
  const page = stagehand.context.pages()[0];
  
  await page.goto("https://google.com");
  await stagehand.act("type in 'Browserbase'");
  await stagehand.act("press enter");
  
  await stagehand.close();
}

(async () => {
  await example();
})();

Working with Multiple Pages

Stagehand supports working with multiple browser pages simultaneously:
import { Stagehand } from "@stagehand/core";

async function example(stagehand: Stagehand) {
  const page = stagehand.context.pages()[0];
  await page.goto("https://example.com");

  // Create a new page
  const page2 = await stagehand.context.newPage();
  await page2.goto("https://another-site.com");
  
  // Perform actions on specific pages
  await stagehand.act("fill the your name field with the text 'John Doe'", {
    page: page2,
  });
  
  const action2 = await stagehand.observe(
    "select blue as the favorite color on the dropdown",
    { page: page2 },
  );
  
  for (const action of action2) {
    await stagehand.act(action, { page: page2, timeout: 30_000 });
  }
}

(async () => {
  const stagehand = new Stagehand({
    env: "BROWSERBASE",
    verbose: 2,
  });
  try {
    await stagehand.init();
    await example(stagehand);
  } finally {
    await stagehand.close();
  }
})();

Key Concepts

observe() and act()

The observe() method lets you preview actions before executing them with act(). This is useful for:
  • Caching element locations
  • Debugging navigation flows
  • Building more robust automation

Waiting for UI Updates

Always add appropriate delays between actions to allow UI elements to load and respond:
await new Promise((resolve) => setTimeout(resolve, 3000));

System Prompts

Customize Stagehand’s behavior with system prompts to:
  • Add special command shortcuts
  • Transform user inputs
  • Implement custom navigation logic

Page Context

When working with multiple pages, specify the target page using the page option in act() and observe().

Best Practices

  1. Wait for navigation - Always ensure pages have loaded before interacting
  2. Use observe() for complex flows - Preview and cache actions for reliability
  3. Verify results - Check URLs or page content to confirm successful navigation
  4. Handle errors gracefully - Navigation can fail due to network issues or UI changes

Next Steps

Build docs developers (and LLMs) love