What is observe()?

page.observe("Find the login button")
observe allows you to turn any page into a checklist of reliable, executable actions. It discovers key elements, ranks likely next steps, and returns structured actions (selector, method, args) you can run instantly with act or use to precisely target extract so workflows are faster, cheaper, and more resilient.

Why use observe()?

Using observe()

Calling observe supercharges other Stagehand methods. Use it to plan workflows, speed up act, and precisely target extract. Using observe helps you explore what’s possible on a page by giving you a list of suggested actions.
// Plan & validate
const buttons = await page.observe("Find the log in / sign up buttons");
This will return a list of suggestions with the following structure
{
  "selector": "xpath=/html/body/header/div/button[1]",
  "description": "Log in button in the top right corner",
  "method": "click",
  "arguments": []
}

Observe with Act

You can validate the action (method, selector, arguments…) and then pass it to act to avoid extra LLM inference.
Performance Tip: Acting on multiple observe suggestions will minimize the number of LLM calls for multi-step actions and speed up your workflow 2-3x.
await page.act(buttons[0]); // No LLM!

Plan ahead

You can use multiple suggestions from observe to preview a batch of actions. For example, when filling a form you could ask observe to find all the fields and then pass them in to act. Call the LLM once, act multiple times.
const fields = await page.observe("Find all the fields in the form");
for (const field of fields) {
  await page.act(field); // No LLM!
}

Observe and Extract

Using observe to focus extract on a specific section of the page (like a table, a form, a list…) minimizes the context needed for an extraction.
Savings Tip: Pass the selector to extract to reduce LLM token usage by 10x for verbose websites!
// Use observe to validate elements before extraction
const [ table ] = await page.observe("Find the data table");

const { data } = await page.extract({
  instruction: "Extract data from the table",
  schema: z.object({
    data: z.string()
  }),
  selector: table.selector // Reduce context scope needed for extraction
});

Best Practices

Choose the right commands

  • Use observe when a yes/no answer will gate an action (e.g., “Find the Submit button”), then conditionally act.
  • Use extract for information-only questions (e.g., “What’s the page title?”, “How many results are listed?”).
  • Discover and plan with observe: Use observe("Find…") to map actionable elements and preview next steps.
  • Scope extract with selectors from observe: First observe("Find the data table"), then pass selector to extract to reduce tokens and boost accuracy.

Conserve LLM tokens

Optimize performance by directly passing ObserveResult to act (e.g., await page.act(results[0])) to save LLM tokens. Batch operations by using observe once to find elements, then act on each. Cache and reuse stable observe results for familiar pages, using self-healing if layouts change.

Build your own cache

Check out the guide on how to build your own action cache

Improve Accuracy

Be precise with instructions, e.g., “Find the primary CTA in the hero” for better results. For iframes, set iframes: true and wait for networkidle. Use observe selectors in extract to limit context.

Prompting Best Practices

Check out the guide on how to improve the accuracy of your results

Action Validation

Before performing critical actions, validate the suggestion’s method, selector, and arguments to prevent misclicks. If a direct act fails, use observe with the same prompt to verify the method, then proceed with the suggested action.
const prompt = "click the submit button";
const expectedMethod = "click";

try {
  await page.act(prompt);
} catch (error) {
  if (error.message.includes("method not supported")) {
    // Observe the same prompt to get the planned action
    const [action] = await page.observe(prompt);
    
    if (action && action.method === expectedMethod) {
      await page.act(action);
    } else {
      throw new Error(`Unsupported method: expected "${expectedMethod}", got "${action?.method}"`);
    }
  } else {
    throw error;
  }
}

Troubleshooting

Next Steps