stagehand

browserbaseMIT活跃维护

用 TypeScript 写的浏览器 Agent SDK,让 AI 能操作网页、抓取任意站点数据,支持 Playwright、CDP 和云端浏览器。

The SDK to extract data and interact with any site on the web. Get started with Claude Code, Codex, Eve, Mastra, and more.

stagehand-server-v3/v3.7.7发布于 2026-10-23 18:09 UTC25,993star +14 / 7 天1,812fork同步于 2026-11-10 05:21 UTC

怎么上手

由 README 提炼,执行前请确认
pnpm add @browserbasehq/stagehand 'zod@~4.4.3'
硬件要求按 README 说明

本地运行需安装 Chrome 浏览器;README 未说明显存或 GPU 要求。

下载:源码 zip·GitHub Releases(安装包)本站不镜像安装包

项目说明

由 README 自动翻译提炼

面向浏览器智能体的 SDK,用自然语言操作网页并抽取结构化数据

用 TypeScript 写的浏览器 Agent SDK,让 AI 能操作网页、抓取任意站点数据,支持 Playwright、CDP 和云端浏览器。

核心能力

  • 用 observe 返回真实选择器,凭据不进入模型
  • act 在页面改版时自动修复操作方式
  • extract 按 Zod/Pydantic schema 校验抽取结果
  • 混合可访问性树裁剪,减少 token 消耗
  • 以浏览器扩展方式运行,降低每次动作延迟

容易踩的坑

本地运行必须预先安装 Chrome;使用 SDK 需自备模型 API Key(如 OPENAI_API_KEY);Zod 需锁定 ~4.4.3 版本

内容由模型根据 README 生成,可能不完整或不准确,以官方文档为准。看原文 README

最近发版

5 个版本stagehand-server-v3/v3.7.7
  1. stagehand-server-v3/v3.7.7stagehand/server-v3 v3.7.7最新正式版2026-10-23 · 2026-10-23 18:09 UTC

    What's Changed

    Full Changelog: https://github.com/browserbase/stagehand/compare/@browserbasehq/[email protected]/v3.7.7

  2. @browserbasehq/[email protected]2026-08-28 · 2026-08-28 14:46 UTC
    查看更新说明

    Patch Changes

  3. stagehand-server-v3/v3.7.6stagehand/server-v3 v3.7.62026-08-28 · 2026-08-28 14:22 UTC
    查看更新说明

    What's Changed

    Full Changelog: https://github.com/browserbase/stagehand/compare/stagehand-server-v3/v3.7.5...stagehand-server-v3/v3.7.6

  4. stagehand-server-v3/v3.7.5stagehand/server-v3 v3.7.52026-08-20 · 2026-08-20 00:44 UTC
    查看更新说明

    What's Changed

    Full Changelog: https://github.com/browserbase/stagehand/compare/[email protected]/v3.7.5

  5. [email protected]2026-08-03 · 2026-08-03 18:13 UTC
    查看更新说明

    Patch Changes

    • #2356 04c8ee4 Thanks @Kylejeong2! - Replace raw daemon socket connection errors with a human-readable message that includes the exact browse open command needed to start the session.

    • #2361 2a6e20b Thanks @shrey150! - Warn when auto-loading variables from .env and add BROWSE_LOAD_DOTENV to opt out ahead of a future release where this will be off by default.

用户点评

登录用户的真实使用记录,可按版本和硬件筛选
共 0 条

    还没有人点评。第一个说出真实体验的人最有价值。

    README 原文

    未翻译

    AI that uses the browser like humans.

    Sign in once, keep the session, and pull structured data out the other side.

    import { localBrowser, Stagehand } from "@browserbasehq/stagehand";
    import { z } from "zod/v4";
    
    // Cookies persist in ./browser-data, so the next run starts already signed in
    const browser = await localBrowser.launch({ userDataDir: "./browser-data" });
    const stagehand = await Stagehand.create({
      browser,
      model: { modelName: "openai/gpt-5.4-mini", apiKey: process.env.OPENAI_API_KEY },
    });
    
    const [page] = await browser.context.pages();
    await page.goto("https://app.example.com/login");
    
    // observe() returns real selectors, so credentials never reach the model
    const { data: email } = await stagehand.observe("find the email input");
    const { data: password } = await stagehand.observe("find the password input");
    await page.locator(email[0].selector).fill(process.env.APP_EMAIL!);
    await page.locator(password[0].selector).fill(process.env.APP_PASSWORD!);
    
    // act() self-heals when the site redesigns its form
    await stagehand.act("click the sign in button");
    await stagehand.act("open the billing page");
    
    // extract() returns schema-validated data
    const { data } = await stagehand.extract(
      "extract every invoice in the table",
      z.object({
        invoices: z.array(z.object({ number: z.string(), amount: z.number(), paid: z.boolean() })),
      }),
    );
    
    console.log(data.invoices);
    
    await stagehand.close();
    await browser.close();
    
    import asyncio
    import os
    
    from pydantic import BaseModel
    from stagehand import Stagehand, local_browser
    
    
    class Invoice(BaseModel):
        number: str
        amount: float
        paid: bool
    
    
    class Invoices(BaseModel):
        invoices: list[Invoice]
    
    
    async def main() -> None:
        # Cookies persist in ./browser-data, so the next run starts already signed in
        browser = await local_browser.launch(user_data_dir="./browser-data")
        try:
            stagehand = await Stagehand.create(
                browser=browser,
                model="openai/gpt-5.4-mini",
                model_api_key=os.environ["OPENAI_API_KEY"],
            )
            try:
                page = (await browser.context.pages())[0]
                await page.goto("https://app.example.com/login")
    
                # observe() returns real selectors, so credentials never reach the model
                email = await stagehand.observe("find the email input")
                password = await stagehand.observe("find the password input")
                await page.locator(email.data[0].selector).fill(os.environ["APP_EMAIL"])
                await page.locator(password.data[0].selector).fill(os.environ["APP_PASSWORD"])
    
                # act() self-heals when the site redesigns its form
                await stagehand.act("click the sign in button")
                await stagehand.act("open the billing page")
    
                # extract() returns schema-validated data
                result = await stagehand.extract(
                    "extract every invoice in the table",
                    Invoices,
                )
                print(result.data.invoices)
            finally:
                await stagehand.close()
        finally:
            await browser.close()
    
    
    asyncio.run(main())
    
    package main
    
    import (
    	"context"
    	"errors"
    	"fmt"
    	"log"
    	"os"
    
    	stagehand "github.com/browserbase/stagehand/packages/sdk-go/v4"
    )
    
    type invoice struct {
    	Number string  `json:"number"`
    	Amount float64 `json:"amount"`
    	Paid   bool    `json:"paid"`
    }
    
    type invoices struct {
    	Invoices []invoice `json:"invoices"`
    }
    
    func main() {
    	if err := run(context.Background()); err != nil {
    		log.Fatal(err)
    	}
    }
    
    func run(ctx context.Context) (err error) {
    	// Cookies persist in ./browser-data, so the next run starts already signed in
    	browser, err := stagehand.LaunchLocalBrowser(ctx, &stagehand.LocalBrowserLaunchOptions{
    		UserDataDir: "./browser-data",
    	})
    	if err != nil {
    		return err
    	}
    	defer func() { err = errors.Join(err, browser.Close(ctx)) }()
    
    	modelAPIKey := os.Getenv("OPENAI_API_KEY")
    	client, err := stagehand.Create(ctx, stagehand.CreateOptions{
    		Browser: browser,
    		Model: &stagehand.ModelConfig{
    			ModelName: "openai/gpt-5.4-mini",
    			APIKey:    &modelAPIKey,
    		},
    	})
    	if err != nil {
    		return err
    	}
    	defer func() { err = errors.Join(err, client.Close(ctx)) }()
    
    	browserContext, err := browser.Context()
    	if err != nil {
    		return err
    	}
    	pages, err := browserContext.Pages(ctx)
    	if err != nil {
    		return err
    	}
    	page := pages[0]
    	if _, err := page.Goto(ctx, "https://app.example.com/login", nil); err != nil {
    		return err
    	}
    
    	// Observe returns real selectors, so credentials never reach the model
    	emailInstruction := "find the email input"
    	email, err := client.Observe(ctx, &emailInstruction, nil)
    	if err != nil {
    		return err
    	}
    	if err := page.Locator(email.Data[0].Selector).Fill(ctx, os.Getenv("APP_EMAIL")); err != nil {
    		return err
    	}
    
    	passwordInstruction := "find the password input"
    	password, err := client.Observe(ctx, &passwordInstruction, nil)
    	if err != nil {
    		return err
    	}
    	if err := page.Locator(password.Data[0].Selector).Fill(ctx, os.Getenv("APP_PASSWORD")); err != nil {
    		return err
    	}
    
    	// Act self-heals when the site redesigns its form
    	if _, err := client.Act(ctx, stagehand.ActInstruction("click the sign in button"), nil); err != nil {
    		return err
    	}
    	if _, err := client.Act(ctx, stagehand.ActInstruction("open the billing page"), nil); err != nil {
    		return err
    	}
    
    	// Extract returns data decoded into a Go type
    	extracted, err := stagehand.Extract[invoices](
    		ctx,
    		client,
    		"extract every invoice in the table",
    		nil,
    	)
    	if err != nil {
    		return err
    	}
    	fmt.Println(extracted.Data.Invoices)
    
    	return nil
    }
    

    Install

    pnpm add @browserbasehq/stagehand 'zod@~4.4.3'
    
    pip install stagehand
    
    go get github.com/browserbase/stagehand/packages/sdk-go/[email protected]
    

    Local runs need Chrome installed. Full setup: Quickstart.

    Install the browse CLI and skill instead of using the SDK directly:

    npm install -g browse
    npx skills add browserbase/stagehand --skill browse
    browse open https://example.com --local
    browse snapshot
    browse get title
    

    No LLM key or Browserbase account needed for local use. See CLI vs SDK vs hosted MCP for when to use each.

    Why Stagehand

    Run it on Browserbase

    Point the same script at Browserbase and get 2x faster execution than Playwright cloud equivalent browsers. Configure the Model Gateway so you never wire up a provider, and enable server-side caching to cache repeated actions.

    import { browserbase, Stagehand } from "@browserbasehq/stagehand";
    
    const browser = await browserbase.launch({ apiKey: process.env.BROWSERBASE_API_KEY! });
    
    // No model configuration: the Model Gateway picks the cheapest model for each action
    // cache: true: identical calls come back from Browserbase, no tokens spent
    const stagehand = await Stagehand.create({ browser, cache: true });
    
    import os
    
    from stagehand import Stagehand, browserbase
    
    browser = await browserbase.launch(api_key=os.environ["BROWSERBASE_API_KEY"])
    
    # No model configuration: the Model Gateway picks the cheapest model for each action
    # cache=True: identical calls come back from Browserbase, no tokens spent
    stagehand = await Stagehand.create(browser=browser, cache=True)
    
    browser, err := stagehand.LaunchBrowserbase(ctx, stagehand.BrowserbaseLaunchOptions{
    	APIKey: os.Getenv("BROWSERBASE_API_KEY"),
    })
    if err != nil {
    	return err
    }
    
    // No model configuration: the Model Gateway picks the cheapest model for each action
    // CacheEnabled(true): identical calls come back from Browserbase, no tokens spent
    cache := stagehand.CacheEnabled(true)
    client, err := stagehand.Create(ctx, stagehand.CreateOptions{
    	Browser: browser,
    	Cache:   &cache,
    })
    if err != nil {
    	return err
    }
    

    Verified mode, residential proxies, persistent contexts, and session recordings come with it. Get an API key and learn how to configure your browser here.

    Hosted MCP: browser tools without installing anything

    The hosted Browserbase MCP server puts navigate, act, observe, and extract in any MCP client — no install, no local browser. Requires a Browserbase API key.

    claude mcp add --transport http browserbase https://mcp.browserbase.com/mcp \
      --header "Authorization: Bearer $BROWSERBASE_API_KEY"
    
    {
      "mcpServers": {
        "browserbase": {
          "url": "https://mcp.browserbase.com/mcp",
          "headers": { "Authorization": "Bearer YOUR_BROWSERBASE_API_KEY" }
        }
      }
    }
    

    For local browsing without an API key, use the browse CLI instead.

    Search and fetch without a browser

    Fetch lets you grab the content of any URL as markdown. Search provides fast, token-efficient web search results. Both as a lightweight complement to browser sessions.

    import { browserbase } from "@browserbasehq/stagehand";
    
    const { results } = await browserbase.search({
      apiKey: process.env.BROWSERBASE_API_KEY!,
      query: "browser agent frameworks",
      numResults: 5,
    });
    
    const fetched = await browserbase.fetch({
      apiKey: process.env.BROWSERBASE_API_KEY!,
      url: results[0].url,
      format: "markdown",
    });
    
    console.log(fetched.content);
    

    Docs and resources

    Join the community

    Stagehand is built in the open, and the fastest way to shape it is to show up.

    Contributing

    We're focused on improving reliability, extensibility, speed, and cost, in that order. Bug fixes and small improvements are the best way to get started. For anything larger, reach out to Miguel Gonzalez or Paul Klein on Discord first so we can make sure it lands.

    Stagehand is a TypeScript, Python, and Go monorepo driven by just:

    git clone https://github.com/browserbase/stagehand.git
    cd stagehand
    just install
    just generate
    just build
    
    export OPENAI_API_KEY="your-openai-api-key"
    just example act # runs packages/sdk-ts/examples/act.ts
    

    See CONTRIBUTING.md for the full TypeScript, Python, and Go setup.

    Acknowledgements

    We'd like to thank the following people for their major contributions to Stagehand:

    License

    Licensed under the MIT License.

    Copyright 2026 Browserbase, Inc.

    "Stagehand" is a trademark of Browserbase, Inc.