stagehand-automation

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Stagehand Automation

Stagehand自动化

Overview

概述

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 language
  • extract()
    - Extract structured data from pages
  • observe()
    - Identify elements and page state

Stagehand v3是一款顶尖的AI浏览器自动化框架,它将脆弱的传统自动化与智能自修复能力相结合。基于Chrome DevTools Protocol (CDP)构建,相比v2版本速度提升44%,并可与Claude无缝集成。
核心创新:当DOM发生变化时,AI会自动适配,而非导致测试失败。
核心API:
  • act()
    - 使用自然语言执行操作
  • extract()
    - 从页面提取结构化数据
  • observe()
    - 识别元素与页面状态

Quick Start (10 Minutes)

快速上手(10分钟)

1. Install Stagehand

1. 安装Stagehand

bash
npm install @browserbase/stagehand zod
bash
npm install @browserbase/stagehand zod

2. Configure Claude API

2. 配置Claude API

bash
undefined
bash
undefined

Add to .env

添加到.env文件

ANTHROPIC_API_KEY=your_api_key_here
undefined
ANTHROPIC_API_KEY=your_api_key_here
undefined

3. Write First Automation

3. 编写首个自动化脚本

typescript
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();
typescript
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驱动操作 - 无惧UI变更!
  await stagehand.act({ action: "click on the first story link" });

  // 提取结构化数据
  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();

4. Run

4. 运行脚本

bash
npx ts-node your-script.ts

bash
npx ts-node your-script.ts

Core APIs

核心API

act() - Perform Actions

act() - 执行操作

Execute actions using natural language:
typescript
// Click elements
await stagehand.act({ action: "click the login button" });

// Fill forms
await stagehand.act({ action: "fill in the email field with 'test@example.com'" });
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.
使用自然语言执行各类操作:
typescript
// 点击元素
await stagehand.act({ action: "click the login button" });

// 填写表单
await stagehand.act({ action: "fill in the email field with 'test@example.com'" });
await stagehand.act({ action: "enter password 'securepass123'" });

// 页面导航
await stagehand.act({ action: "scroll down to the pricing section" });
await stagehand.act({ action: "click the 'Sign Up' button in the header" });

// 复杂操作
await stagehand.act({
  action: "select 'Premium' from the plan dropdown and click Continue"
});
自修复特性:如果按钮ID从
#login-btn
变更为
#auth-signin
,Stagehand会自动适配。

extract() - Get Structured Data

extract() - 获取结构化数据

Extract data with schema validation:
typescript
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(),
  }),
});
通过Schema验证提取数据:
typescript
import { z } from "zod";

// 简单提取
const title = await stagehand.extract({
  instruction: "get the main page title",
  schema: z.object({
    title: z.string(),
  }),
});

// 复杂提取
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(),
    })),
  }),
});

// 从指定区域提取
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(),
  }),
});

observe() - Analyze Page State

observe() - 分析页面状态

Understand page elements and state:
typescript
// 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"
});

识别页面元素与状态:
typescript
// 查找元素
const elements = await stagehand.observe({
  instruction: "find all clickable buttons on this page"
});

// 检查状态
const loginState = await stagehand.observe({
  instruction: "is the user logged in? Look for profile icons or logout buttons"
});

// 识别表单字段
const formFields = await stagehand.observe({
  instruction: "identify all form input fields and their labels"
});

Self-Healing Patterns

自修复模式

Traditional vs Stagehand

传统方案 vs Stagehand

typescript
// 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
typescript
// 传统方案(Playwright)- DOM变更时失效
await page.click('#submit-btn-v2');  // ID变更时失败
await page.click('.btn-primary:nth-child(2)');  // 顺序变更时失败

// STAGEHAND - 自修复
await stagehand.act({ action: "click the submit button" });  // 始终可用
await stagehand.act({ action: "click the primary action button" });  // 自动适配

When Self-Healing Activates

自修复触发场景

  1. ID/Class Changes: Button ID changes from
    #old-id
    to
    #new-id
  2. Structure Changes: Element moves in DOM tree
  3. Text Changes: Button text changes from "Submit" to "Send"
  4. Style Changes: CSS classes reorganized
  1. ID/类名变更:按钮ID从
    #old-id
    变为
    #new-id
  2. 结构变更:元素在DOM树中的位置移动
  3. 文本变更:按钮文本从“Submit”变为“Send”
  4. 样式变更:CSS类重新组织

Caching (Performance Optimization)

缓存(性能优化)

Stagehand v3 caches discovered elements:
typescript
// 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

Stagehand v3会缓存已发现的元素:
typescript
// 首次调用:AI分析页面,查找元素(速度较慢)
await stagehand.act({ action: "click login" });

// 二次调用:使用缓存的选择器(速度快)
await stagehand.act({ action: "click login" });

// 当页面发生显著变更时,缓存会失效

Hybrid Approach: Playwright + Stagehand

混合方案:Playwright + Stagehand

Combine traditional speed with AI resilience:
typescript
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"]', 'test@example.com');

  // 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);
});

结合传统方案的速度与AI的韧性:
typescript
import { Stagehand } from "@browserbase/stagehand";
import { test, expect } from "@playwright/test";

test('hybrid test', async () => {
  const stagehand = new Stagehand({ env: "LOCAL" });
  await stagehand.init();

  // 使用Playwright执行稳定、快速的操作
  await stagehand.page.goto('https://app.example.com');
  await stagehand.page.fill('[data-testid="email"]', 'test@example.com');

  // 使用Stagehand处理动态/脆弱元素
  await stagehand.act({ action: "click the login button" });

  // 使用Playwright执行断言
  await expect(stagehand.page).toHaveURL(/dashboard/);

  // 使用Stagehand执行复杂提取
  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 Integration

Claude集成

Model Selection

模型选择

typescript
// 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",
});
typescript
// Claude Sonnet 4(推荐 - 平衡速度与性能)
const stagehand = new Stagehand({
  modelName: "claude-sonnet-4-20250514",
  modelClientOptions: {
    apiKey: process.env.ANTHROPIC_API_KEY,
  },
});

// Claude Opus(最高性能,速度较慢)
const stagehand = new Stagehand({
  modelName: "claude-opus-4-20250514",
});

// Claude Haiku(最快,适用于简单任务)
const stagehand = new Stagehand({
  modelName: "claude-3-5-haiku-20241022",
});

Cost Optimization

成本优化

typescript
// 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,
});
typescript
// 使用Haiku执行简单操作(成本更低)
const simpleStagehand = new Stagehand({
  modelName: "claude-3-5-haiku-20241022",
});
await simpleStagehand.act({ action: "click login" });

// 使用Sonnet执行复杂提取
const complexStagehand = new Stagehand({
  modelName: "claude-sonnet-4-20250514",
});
const data = await complexStagehand.extract({
  instruction: "extract all product details with nested specifications",
  schema: complexSchema,
});

Estimated Costs

预估成本

OperationModelEst. Cost
Simple act()Haiku~$0.001
Complex act()Sonnet~$0.005
Simple extract()Haiku~$0.002
Complex extract()Sonnet~$0.01

操作类型模型预估成本
简单act()Haiku~$0.001
复杂act()Sonnet~$0.005
简单extract()Haiku~$0.002
复杂extract()Sonnet~$0.01

MCP Integration

MCP集成

Use Stagehand with Claude Desktop via Model Context Protocol:
typescript
// 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: "..." })

通过Model Context Protocol将Stagehand与Claude Desktop结合使用:
typescript
// Stagehand MCP服务器允许Claude控制浏览器
// 支持Claude Desktop或任何兼容MCP的客户端

import { StagehandMCPServer } from "@browserbase/stagehand/mcp";

const server = new StagehandMCPServer();
server.start();

// 现在Claude可以调用:
// - stagehand.act({ action: "..." })
// - stagehand.extract({ instruction: "..." })
// - stagehand.observe({ instruction: "..." })

Error Handling

错误处理

typescript
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));
    }
  }
}

typescript
try {
  await stagehand.act({
    action: "click the non-existent button",
    timeout: 10000,  // 10秒超时
  });
} catch (error) {
  if (error.message.includes('timeout')) {
    console.log('超时未找到元素');
  } else if (error.message.includes('multiple')) {
    console.log('找到多个匹配元素 - 请更明确');
  } else {
    throw error;
  }
}

// 重试模式
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));
    }
  }
}

Best Practices

最佳实践

1. Be Specific in Instructions

1. 指令需明确

typescript
// 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" });
typescript
// 差 - 模糊
await stagehand.act({ action: "click button" });

// 好 - 明确
await stagehand.act({ action: "click the blue 'Add to Cart' button below the product image" });

2. Use Context

2. 提供上下文

typescript
// 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'"
});
typescript
// 提供上下文以提升准确性
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'"
});

3. Combine with Playwright for Speed

3. 结合Playwright提升速度

typescript
// 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" });
typescript
// 快速:使用Playwright处理带data-testid的元素
await stagehand.page.click('[data-testid="submit"]');

// 韧性:使用Stagehand处理动态元素
await stagehand.act({ action: "dismiss the cookie banner" });

4. Schema Validation

4. Schema验证

typescript
// 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!

typescript
// 始终使用Zod Schema确保类型安全
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类型完全安全!

Use Cases

适用场景

  1. Self-Healing E2E Tests: Tests that survive UI redesigns
  2. Web Scraping: Extract data from any website
  3. Form Automation: Fill complex forms automatically
  4. Testing AI Chatbots: Interact with conversational UIs
  5. Cross-Site Workflows: Automate multi-site processes

  1. 自修复端到端测试:可适应UI重设计的测试
  2. 网页抓取:从任意网站提取数据
  3. 表单自动化:自动填写复杂表单
  4. AI聊天机器人测试:与对话式UI交互
  5. 跨站点工作流:自动化多站点流程

References

参考资料

  • references/stagehand-v3-guide.md
    - Complete API reference
  • references/claude-integration.md
    - API setup and model selection
  • references/self-healing-patterns.md
    - Advanced patterns

Stagehand v3 brings AI-powered self-healing to browser automation - tests that adapt instead of break.
  • references/stagehand-v3-guide.md
    - 完整API参考
  • references/claude-integration.md
    - API设置与模型选择
  • references/self-healing-patterns.md
    - 高级模式

Stagehand v3为浏览器自动化带来AI驱动的自修复能力——测试将自动适配而非失效。