Skip to main content
Stagehand performance depends on several factors: DOM processing speed, LLM inference time, browser operations, and network latency. This guide provides proven strategies to maximize automation speed.

Quick Performance Wins

1. Plan Ahead with Observe

Use a single observe() call to plan multiple actions, then execute them efficiently:
// Instead of sequential operations with multiple LLM calls
await page.act("Fill name field");        // LLM call #1
await page.act("Fill email field");       // LLM call #2
await page.act("Select country dropdown"); // LLM call #3

// Use single observe to plan all form fields - one LLM call
const formFields = await page.observe("Find all form fields to fill");

// Execute all actions without LLM inference
for (const field of formFields) {
  await page.act(field); // No LLM calls!
}
Performance Tip: Acting on observe results avoids LLM inference entirely. This approach is 2-3x faster than direct act() calls and is the recommended pattern for multi-step workflows.

Caching Guide

Learn advanced caching patterns and cache invalidation strategies

2. Optimize DOM Processing

Reduce DOM complexity before Stagehand processes the page:
// Remove heavy elements that slow down processing
await page.evaluate(() => {
  // Remove video elements
  document.querySelectorAll('video, iframe').forEach(el => el.remove());
  
  // Hide complex animations
  document.querySelectorAll('[style*="animation"]').forEach(el => {
    (el as HTMLElement).style.animation = 'none';
  });
});

// Then perform Stagehand operations
await page.act("Click the submit button");

3. Set Appropriate Timeouts

Use shorter timeouts for simple operations and longer ones for complex page loads:
// Simple actions - reduce action timeout
await page.act({ 
  instruction: "Click the login button",
  actTimeout: 5000  // Default is 30000ms, reduce for simple clicks
});

// Complex page loads - optimize navigation
await page.goto("https://heavy-spa.com", {
  waitUntil: "domcontentloaded", // Don't wait for all resources
  timeout: 15000 // Shorter than default 30s
});

Advanced Performance Strategies

Smart Model Selection

Use faster models for simple tasks, premium models only when needed:
class SpeedOptimizedStagehand {
  private fastModel: Stagehand;
  private premiumModel: Stagehand;

  async smartAct(page: Page, prompt: string, complexity: 'simple' | 'complex') {
    const model = complexity === 'simple' ? this.fastModel : this.premiumModel;
    return await model.page.act(prompt);
  }
}

// Use fast model for simple clicks/forms
await stagehand.smartAct(page, "Click submit", 'simple');

// Use premium model for complex reasoning
await stagehand.smartAct(page, "Find the cheapest flight option", 'complex');

Model Configuration

Compare model performance and costs

Page Load Optimization

Skip unnecessary resources during page loads:
// Block heavy resources globally
await context.route('**/*', (route) => {
  const resourceType = route.request().resourceType();
  if (['image', 'font', 'media'].includes(resourceType)) {
    route.abort();
  } else {
    route.continue();
  }
});

// Use faster navigation
await page.goto(url, { 
  waitUntil: 'domcontentloaded',  // Don't wait for images/fonts
  timeout: 10000 
});

Cost Optimization

Balance speed with cost considerations

Performance Monitoring and Benchmarking

Track performance metrics and measure optimization impact:

Performance Tracking

class PerformanceTracker {
  private speedMetrics: Map<string, number[]> = new Map();

  async timedAct(page: Page, prompt: string): Promise<ActResult> {
    const start = Date.now();
    const result = await page.act(prompt);
    const duration = Date.now() - start;
    
    if (!this.speedMetrics.has(prompt)) {
      this.speedMetrics.set(prompt, []);
    }
    this.speedMetrics.get(prompt)!.push(duration);
    
    console.log(`Action "${prompt}" took ${duration}ms`);
    return result;
  }

  getAverageTime(prompt: string): number {
    const times = this.speedMetrics.get(prompt) || [];
    return times.reduce((a, b) => a + b, 0) / times.length;
  }
}
Example Output:
Action "Fill form" took 1000ms
Action "Click submit" took 2000ms
Action "Confirm submission" took 5000ms

Before vs After Benchmarking

// Before optimization
console.time("workflow");
await page.act("Fill form");
await page.act("Click submit");
await page.act("Confirm submission");
console.timeEnd("workflow"); // 8000ms

// After optimization with observe planning
console.time("workflow-optimized");
const workflowActions = await page.observe("Find form, submit, and confirm elements");

// Execute actions sequentially to avoid conflicts
for (const action of workflowActions) {
  await page.act(action);
}
console.timeEnd("workflow-optimized"); // 500ms
Example Output:
Workflow took 8000ms
Optimized workflow took 500ms

Observability & Metrics

Set up comprehensive performance monitoring

Caching Strategies

Advanced caching patterns for maximum performance

Cost Optimization

Balance speed improvements with cost considerations

Browser Configuration

Optimize Browserbase settings for speed

Model Selection

Choose the right model for speed vs accuracy