.claude/skills/stagehand-automation/SKILL.md
AI-powered browser automation using Stagehand v3 and Claude. Use when building self-healing tests, AI agents, dynamic web automation, or when traditional selectors break frequently due to UI changes.
npx skillsauth add adaptationio/skrillz stagehand-automationInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Stagehand v3 is the state-of-the-art AI browser automation framework that bridges brittle traditional automation with intelligent, self-healing capabilities. Built on Chrome DevTools Protocol (CDP), it's 44% faster than v2 and integrates seamlessly with Claude.
Key Innovation: When DOM changes, AI adapts instead of tests breaking.
Core APIs:
act() - Perform actions using natural languageextract() - Extract structured data from pagesobserve() - Identify elements and page statenpm install @browserbase/stagehand zod
# Add to .env
ANTHROPIC_API_KEY=your_api_key_here
import { Stagehand } from "@browserbase/stagehand";
import { z } from "zod";
async function main() {
const stagehand = new Stagehand({
env: "LOCAL",
modelName: "claude-sonnet-4-20250514",
modelClientOptions: {
apiKey: process.env.ANTHROPIC_API_KEY,
},
});
await stagehand.init();
await stagehand.page.goto("https://news.ycombinator.com");
// AI-powered action - survives UI changes!
await stagehand.act({ action: "click on the first story link" });
// Extract structured data
const data = await stagehand.extract({
instruction: "extract the story title and author",
schema: z.object({
title: z.string(),
author: z.string(),
}),
});
console.log(data);
await stagehand.close();
}
main();
npx ts-node your-script.ts
Execute actions using natural language:
// Click elements
await stagehand.act({ action: "click the login button" });
// Fill forms
await stagehand.act({ action: "fill in the email field with '[email protected]'" });
await stagehand.act({ action: "enter password 'securepass123'" });
// Navigate
await stagehand.act({ action: "scroll down to the pricing section" });
await stagehand.act({ action: "click the 'Sign Up' button in the header" });
// Complex actions
await stagehand.act({
action: "select 'Premium' from the plan dropdown and click Continue"
});
Self-Healing: If the button ID changes from #login-btn to #auth-signin, Stagehand adapts automatically.
Extract data with schema validation:
import { z } from "zod";
// Simple extraction
const title = await stagehand.extract({
instruction: "get the main page title",
schema: z.object({
title: z.string(),
}),
});
// Complex extraction
const products = await stagehand.extract({
instruction: "extract all products with name, price, and availability",
schema: z.object({
products: z.array(z.object({
name: z.string(),
price: z.number(),
inStock: z.boolean(),
})),
}),
});
// Extract from specific area
const cartItems = await stagehand.extract({
instruction: "get items in the shopping cart",
schema: z.object({
items: z.array(z.object({
name: z.string(),
quantity: z.number(),
price: z.number(),
})),
total: z.number(),
}),
});
Understand page elements and state:
// Find elements
const elements = await stagehand.observe({
instruction: "find all clickable buttons on this page"
});
// Check state
const loginState = await stagehand.observe({
instruction: "is the user logged in? Look for profile icons or logout buttons"
});
// Identify form fields
const formFields = await stagehand.observe({
instruction: "identify all form input fields and their labels"
});
// TRADITIONAL (Playwright) - Breaks when DOM changes
await page.click('#submit-btn-v2'); // Fails if ID changes
await page.click('.btn-primary:nth-child(2)'); // Fails if order changes
// STAGEHAND - Self-healing
await stagehand.act({ action: "click the submit button" }); // Always works
await stagehand.act({ action: "click the primary action button" }); // Adapts
#old-id to #new-idStagehand v3 caches discovered elements:
// First call: AI analyzes page, finds element (slow)
await stagehand.act({ action: "click login" });
// Second call: Uses cached selector (fast)
await stagehand.act({ action: "click login" });
// Cache invalidated when page changes significantly
Combine traditional speed with AI resilience:
import { Stagehand } from "@browserbase/stagehand";
import { test, expect } from "@playwright/test";
test('hybrid test', async () => {
const stagehand = new Stagehand({ env: "LOCAL" });
await stagehand.init();
// Use Playwright for stable, fast operations
await stagehand.page.goto('https://app.example.com');
await stagehand.page.fill('[data-testid="email"]', '[email protected]');
// Use Stagehand for dynamic/fragile elements
await stagehand.act({ action: "click the login button" });
// Use Playwright for assertions
await expect(stagehand.page).toHaveURL(/dashboard/);
// Use Stagehand for complex extraction
const dashboardData = await stagehand.extract({
instruction: "get user stats from dashboard",
schema: z.object({
totalOrders: z.number(),
accountBalance: z.number(),
}),
});
expect(dashboardData.totalOrders).toBeGreaterThan(0);
});
// Claude Sonnet 4 (recommended - balance of speed/quality)
const stagehand = new Stagehand({
modelName: "claude-sonnet-4-20250514",
modelClientOptions: {
apiKey: process.env.ANTHROPIC_API_KEY,
},
});
// Claude Opus (highest quality, slower)
const stagehand = new Stagehand({
modelName: "claude-opus-4-20250514",
});
// Claude Haiku (fastest, simpler tasks)
const stagehand = new Stagehand({
modelName: "claude-3-5-haiku-20241022",
});
// Use Haiku for simple actions (cheaper)
const simpleStagehand = new Stagehand({
modelName: "claude-3-5-haiku-20241022",
});
await simpleStagehand.act({ action: "click login" });
// Use Sonnet for complex extraction
const complexStagehand = new Stagehand({
modelName: "claude-sonnet-4-20250514",
});
const data = await complexStagehand.extract({
instruction: "extract all product details with nested specifications",
schema: complexSchema,
});
| Operation | Model | Est. Cost | |-----------|-------|-----------| | Simple act() | Haiku | ~$0.001 | | Complex act() | Sonnet | ~$0.005 | | Simple extract() | Haiku | ~$0.002 | | Complex extract() | Sonnet | ~$0.01 |
Use Stagehand with Claude Desktop via Model Context Protocol:
// Stagehand MCP server enables Claude to control browsers
// from Claude Desktop or any MCP-compatible client
import { StagehandMCPServer } from "@browserbase/stagehand/mcp";
const server = new StagehandMCPServer();
server.start();
// Now Claude can call:
// - stagehand.act({ action: "..." })
// - stagehand.extract({ instruction: "..." })
// - stagehand.observe({ instruction: "..." })
try {
await stagehand.act({
action: "click the non-existent button",
timeout: 10000, // 10 second timeout
});
} catch (error) {
if (error.message.includes('timeout')) {
console.log('Element not found within timeout');
} else if (error.message.includes('multiple')) {
console.log('Multiple matching elements found - be more specific');
} else {
throw error;
}
}
// Retry pattern
async function actWithRetry(stagehand, action, maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
try {
return await stagehand.act({ action });
} catch (error) {
if (i === maxRetries - 1) throw error;
await new Promise(r => setTimeout(r, 1000));
}
}
}
// BAD - ambiguous
await stagehand.act({ action: "click button" });
// GOOD - specific
await stagehand.act({ action: "click the blue 'Add to Cart' button below the product image" });
// Provide context for better accuracy
await stagehand.act({
action: "in the navigation menu, click on 'Settings'"
});
await stagehand.act({
action: "in the user dropdown in the top right, click 'Logout'"
});
// Fast: Use Playwright for data-testid elements
await stagehand.page.click('[data-testid="submit"]');
// Resilient: Use Stagehand for dynamic elements
await stagehand.act({ action: "dismiss the cookie banner" });
// Always use Zod schemas for type safety
const schema = z.object({
title: z.string().min(1),
price: z.number().positive(),
inStock: z.boolean(),
});
const data = await stagehand.extract({
instruction: "get product details",
schema,
});
// data is fully typed!
references/stagehand-v3-guide.md - Complete API referencereferences/claude-integration.md - API setup and model selectionreferences/self-healing-patterns.md - Advanced patternsStagehand v3 brings AI-powered self-healing to browser automation - tests that adapt instead of break.
development
Setup secure web-based terminal access to WSL2 from mobile/tablet via ttyd + ngrok/Cloudflare/Tailscale. One-command install, start, stop, status. Use when you need remote terminal access, web terminal, browser-based shell, or mobile access to WSL2 environment.
development
Complete development workflows where Claude writes the code while Gemini and Codex provide research, planning, reviews, and different perspectives. Claude remains the main developer. Use for complex projects requiring expert planning and multi-perspective reviews.
development
Systematic progress tracking for skill development. Manages task states (pending/in_progress/completed), updates in real-time, reports progress, identifies blockers, and maintains momentum. Use when tracking skill development, coordinating work, or reporting progress.
testing
Comprehensive testing workflow orchestrating functional testing, example validation, integration testing, and usability assessment. Sequential workflow for complete skill testing from examples through scenarios to integration validation. Use when conducting thorough testing, pre-deployment validation, ensuring skill functionality, or comprehensive quality checks.