Overview
Optimizing Stagehand’s performance involves balancing speed, reliability, and cost. This guide covers proven strategies to reduce latency.
Use Caching for Speed
Caching is the single most effective performance optimization.
Enable Cache
const stagehand = new Stagehand({
env: "LOCAL",
cacheDir: "./stagehand-cache",
});
await stagehand.init();
Performance impact:
- Cached operations: 50-100ms (selector replay)
- Uncached operations: 1-5 seconds (LLM inference)
- Speed improvement: 10-50x
Cache Hit Verification
const result = await stagehand.extract("get product title");
if (result.metadata?.cacheHit) {
console.log("Cache hit! Instant response.");
console.log("Cache timestamp:", result.metadata.cacheTimestamp);
}
Optimize DOM Processing
Set DOM Settle Timeout
Reduce wait time for DOM stabilization:
const stagehand = new Stagehand({
env: "LOCAL",
domSettleTimeout: 500, // ms to wait for DOM changes
});
Lower values speed up execution but may miss dynamic content. Default is typically sufficient.
Use Faster Models
Smaller models have lower latency:
// Fast: ~500ms inference time
const stagehand = new Stagehand({
model: "openai/gpt-4.1-mini",
});
// Slower but more accurate: ~1-2s inference time
const stagehand = new Stagehand({
model: "anthropic/claude-sonnet-4",
});
Optimize Timeouts
Set Appropriate Timeouts
// Default timeout (varies by operation)
await stagehand.act("click submit");
// Custom timeout for slow-loading pages
await stagehand.act("click submit", {
timeout: 30_000 // 30 seconds
});
// Fail fast for quick operations
await stagehand.act("click button", {
timeout: 5_000 // 5 seconds
});
Agent Timeouts
const agent = stagehand.agent();
await agent.execute({
instruction: "search for product",
maxSteps: 5, // Limit exploration
// Each step can have its own timeout
});
Set maxSteps to the minimum required for your task to avoid unnecessary LLM calls.
Use Browserbase for Scale
Browserbase provides infrastructure optimizations:
const stagehand = new Stagehand({
env: "BROWSERBASE",
apiKey: process.env.BROWSERBASE_API_KEY,
projectId: process.env.BROWSERBASE_PROJECT_ID,
browserbaseSessionCreateParams: {
browserSettings: {
// Optimize for speed
blockAds: true, // Faster page loads
solveCaptchas: true, // Auto-solve captchas
},
proxies: true, // Use optimized routing
},
});
Benefits:
- Pre-warmed browsers
- Optimized network routing
- Parallel execution support
- No local resource constraints
Reduce Logging Overhead
const stagehand = new Stagehand({
verbose: 0, // Minimal logging
logInferenceToFile: false, // Don't persist logs
});
Performance impact:
verbose: 0 - No console output (fastest)
verbose: 1 - Basic logs (~5-10ms overhead)
verbose: 2 - Detailed logs (~20-50ms overhead)
Parallel Execution
Run independent operations concurrently:
// ❌ Sequential: ~6 seconds
const page1Data = await stagehand.extract("get title", { page: page1 });
const page2Data = await stagehand.extract("get title", { page: page2 });
const page3Data = await stagehand.extract("get title", { page: page3 });
// ✅ Parallel: ~2 seconds
const [page1Data, page2Data, page3Data] = await Promise.all([
stagehand.extract("get title", { page: page1 }),
stagehand.extract("get title", { page: page2 }),
stagehand.extract("get title", { page: page3 }),
]);
Multiple Stagehand Instances
For heavy workloads, use multiple instances:
const instances = await Promise.all(
Array.from({ length: 5 }, () => {
const sh = new Stagehand({ env: "BROWSERBASE" });
return sh.init().then(() => sh);
})
);
// Process 5 tasks in parallel
const results = await Promise.all(
instances.map((sh, i) =>
sh.extract(`task ${i}`)
)
);
// Cleanup
await Promise.all(instances.map(sh => sh.close()));
Stream Agent Responses
Get results as they arrive:
const agent = stagehand.agent({
stream: true, // Enable streaming
});
const run = await agent.execute({
instruction: "search for products",
maxSteps: 10,
});
// Process results incrementally
for await (const chunk of run.textStream) {
console.log(chunk); // Display progress in real-time
}
const finalResult = await run.result;
Benefits:
- Perceived latency reduction
- Real-time progress updates
- Better user experience
Optimize Network Requests
Block Unnecessary Resources
const page = stagehand.context.pages()[0];
// Block images, fonts, and other heavy resources
await page.route("**/*", (route) => {
const resourceType = route.request().resourceType();
if (["image", "font", "stylesheet"].includes(resourceType)) {
route.abort();
} else {
route.continue();
}
});
Blocking resources can break some websites. Test thoroughly.
Reuse Browser Sessions
With Browserbase
// Create a session and keep it alive
const stagehand1 = new Stagehand({
env: "BROWSERBASE",
keepAlive: true,
});
await stagehand1.init();
const sessionId = stagehand1.browserbaseSessionID;
// Reuse the session later (saves ~2-3 seconds)
const stagehand2 = new Stagehand({
env: "BROWSERBASE",
browserbaseSessionID: sessionId,
});
await stagehand2.init(); // Reconnects to existing session
With Local Browsers
const stagehand = new Stagehand({
env: "LOCAL",
localBrowserLaunchOptions: {
headless: true, // Faster than headed mode
},
});
await stagehand.init();
// Keep the instance alive for multiple operations
await stagehand.act("task 1");
await stagehand.act("task 2");
await stagehand.act("task 3");
await stagehand.close();
Performance Benchmarks
Typical operation times:
| Operation | Cached | Uncached | Optimization |
|---|
act() | 50-100ms | 1-3s | Use cache |
extract() | 50-100ms | 1-4s | Use cache |
observe() | 50-100ms | 1-3s | Use cache |
agent.execute() (5 steps) | 200-500ms | 5-15s | Use cache + limit steps |
| Browser launch | N/A | 2-5s | Reuse sessions |
Profiling Performance
const start = Date.now();
await stagehand.act("click button");
const duration = Date.now() - start;
console.log(`Operation took ${duration}ms`);
Performance Checklist
Enable caching
Set cacheDir in Stagehand options
Choose appropriate model
Use mini models for simple tasks
Set reasonable timeouts
Don’t wait longer than necessary
Minimize logging
Use verbose: 0 in production
Parallelize when possible
Use Promise.all() for independent operations
Reuse browser sessions
Avoid re-launching browsers
Related