Good prompts make Stagehand reliable. Bad prompts cause failures. Here’s how to write prompts that work consistently.

Act Method

Use act() for single actions on web pages. Each action should be focused and clear.
// Good - Single, specific actions
await page.act("click the 'Add to Cart' button");
await page.act("type 'user@example.com' into the email field");

// Bad - Multiple actions combined
await page.act("fill out the form and submit it");
await page.act("login with credentials and navigate to dashboard");

Use Element Types, Not Colors

Describe elements by their type and function rather than visual attributes like color.
// Good - Element types and descriptive text
await page.act("click the 'Sign In' button");
await page.act("type into the email input field");

// Bad - Color-based descriptions
await page.act("click the blue button");
await page.act("type into the white input");

Use Descriptive Language

// Good - Clear element identification
await page.act("click the 'Next' button at the bottom of the form");
await page.act("type into the search bar at the top of the page");

// Bad - Vague descriptions
await page.act("click next");
await page.act("type into search");

Choose the Right Action Verbs

  • Click for buttons, links, checkboxes
  • Type for text inputs
  • Select for dropdowns
  • Check/uncheck for checkboxes
  • Upload for file inputs
// Good
await page.act("click the submit button");
await page.act("select 'Option 1' from dropdown");

// Bad
await page.act("click submit");
await page.act("choose option 1");

Protect Sensitive Data

Variables keep sensitive information out of prompts and logs.
// Good - Secure approach
await page.act({
  action: "enter %username% in the email field",
  variables: {
    username: "user@example.com"
  }
});

await page.act({
  action: "enter %password% in the password field", 
  variables: {
    password: process.env.USER_PASSWORD
  }
});

// Bad - Insecure approach
await page.act("type 'mySecretPassword123' into the password field");
Set verbose: 0 in your Stagehand config to prevent secrets from appearing in logs.

Extract Method

Use extract() to pull structured data from pages. Define clear schemas and provide context.

Schema Best Practices

Use descriptive field names, correct types, and detailed descriptions. Field descriptions provide context that helps the agent understand exactly what to extract.
// Good - Descriptive names, correct types, and helpful descriptions
const productData = await page.extract({
  instruction: "Extract product information",
  schema: z.object({
    productTitle: z.string().describe("The main product name displayed on the page"),
    priceInDollars: z.number().describe("Current selling price as a number, without currency symbol"),
    isInStock: z.boolean().describe("Whether the product is available for purchase")
  })
});

// Bad - Generic names, wrong types, no descriptions
const data = await page.extract({
  instruction: "Get product details", 
  schema: z.object({
    name: z.string(), // Too generic, no context
    price: z.string(), // Should be number
    stock: z.string() // Should be boolean, no context
  })
});

Handle Arrays Correctly

Always wrap schemas in objects for reliable extraction.
// Good - Array wrapped in object
const listings = await page.extract({
  instruction: "Extract all apartment listings",
  schema: z.object({
    apartments: z.array(z.object({
      address: z.string(),
      rent: z.number()
    }))
  })
});

// Bad - Bare array
const listings = await page.extract({
  instruction: "Extract apartment listings",
  schema: z.array(z.string()) // Don't do this
});

Use Proper URL Types

Specify URL types to tell Stagehand to extract URLs. Without proper URL types, Stagehand won’t extract URLs.
// Good - Tells Stagehand to extract URLs
const links = await page.extract({
  instruction: "Extract navigation links",
  schema: z.object({
    links: z.array(z.object({
      text: z.string(),
      url: z.string().url() // Required for URL extraction
    }))
  })
});

Observe Method

Use observe() to discover actionable elements before acting on them.

Check Elements First

Verify elements exist before taking action to avoid errors.
// Check for elements first
const loginButtons = await page.observe("Find the login button");

if (loginButtons.length > 0) {
  await page.act(loginButtons[0]);
} else {
  console.log("No login button found");
}

Be Specific About Element Types

// Good - Specific element types
const submitButtons = await page.observe("Find submit button in the form");
const dropdowns = await page.observe("Find the state dropdown menu");

// Bad - Too vague
const elements = await page.observe("Find submit stuff");
const things = await page.observe("Find state selection");

Agent Method

Use agent() for complex, multi-step workflows. Provide detailed instructions and set appropriate limits. Don’t include navigation in agent tasks. Handle it separately.
// Good - Navigate first
await page.goto('https://amazon.com');
await agent.execute('Search for wireless headphones under $100 and add the best rated one to cart');

// Bad - Navigation in task
await agent.execute('Go to Amazon, search for headphones, and add one to cart');

Be Highly Specific

Detailed instructions lead to better results.
// Good - Detailed instructions
await agent.execute({
  instruction: "Find Italian restaurants in Brooklyn that are open after 10pm, have outdoor seating, and are rated 4+ stars. Save the top 3 results.",
  maxSteps: 25
});

// Bad - Vague instructions
await agent.execute("Find some good restaurants");

Set Appropriate Step Limits

Match step limits to task complexity.
// Simple task - fewer steps
await agent.execute({
  instruction: "Subscribe to the newsletter with email 'user@example.com'",
  maxSteps: 10
});

// Complex task - more steps  
await agent.execute({
  instruction: "Research and compare 5 project management tools with pricing and features",
  maxSteps: 50
});

Include Success Criteria

Tell the agent how to know when it’s done.
// Good - Clear success criteria
await agent.execute({
  instruction: "Add 3 smartphone cases to cart and confirm the cart shows exactly 3 items with total price",
  maxSteps: 20
});

// Bad - No validation
await agent.execute("Add some items to cart");

Common Mistakes to Avoid

  • Combining multiple actions - Keep each act() call to one action
  • Using vague descriptions - Be specific about which elements to interact with
  • Exposing sensitive data - Always use variables for credentials
  • Skipping validation - Check results before proceeding

Testing Your Prompts

  1. Start simple - Test basic functionality first
  2. Add complexity gradually - Build up to complex workflows
  3. Monitor results - Use logging to understand what’s happening
  4. Iterate based on failures - Refine prompts when they don’t work Remember: Good prompting is iterative. When in doubt, be more specific rather than less.