# Repository: browserbase/stagehand # Stars: 22115 ## .cursorrules # Stagehand Project This is a project that uses Stagehand V3, a browser automation framework with AI-powered `act`, `extract`, `observe`, and `agent` methods. The main class can be imported as `Stagehand` from `@browserbasehq/stagehand`. **Key Classes:** - `Stagehand`: Main orchestrator class providing `act`, `extract`, `observe`, and `agent` methods - `context`: A `V3Context` object that manages browser contexts and pages - `page`: Individual page objects accessed via `stagehand.context.pages()[i]` or created with `stagehand.context.newPage()` ## Initialize ```typescript import { Stagehand } from "@browserbasehq/stagehand"; const stagehand = new Stagehand({ env: "LOCAL", // or "BROWSERBASE" verbose: 2, // 0, 1, or 2 model: "openai/gpt-4.1-mini", // or any supported model }); await stagehand.init(); // Access the browser context and pages const page = stagehand.context.pages()[0]; const context = stagehand.context; // Create new pages if needed const page2 = await stagehand.context.newPage(); ``` ## Act Actions are called on the `stagehand` instance (not the page). Use atomic, specific instructions: ```typescript // Act on the current active page await stagehand.act("click the sign in button"); // Act on a specific page (when you need to target a page that isn't currently active) await stagehand.act("click the sign in button", { page: page2 }); ``` **Important:** Act instructions should be atomic and specific: - ✅ Good: "Click the sign in button" or "Type 'hello' into the search input" - ❌ Bad: "Order me pizza" or "Type in the search bar and hit enter" (multi-step) ### Observe + Act Pattern (Recommended) Cache the results of `observe` to avoid unexpected DOM changes: ```typescript const instruction = "Click the sign in button"; // Get candidate actions const actions = await stagehand.observe(instruction); // Execute the first action await stagehand.act(actions[0]); ``` To target a specific page: ```typescript const actions = await stagehand.observe("select blue as the favorite color", { page: page2, }); await stagehand.act(actions[0], { page: page2 }); ``` ## Extract Extract data from pages using natural language instructions. The `extract` method is called on the `stagehand` instance. ### Basic Extraction (with schema) ```typescript import { z } from "zod"; // Extract with explicit schema const data = await stagehand.extract( "extract all apartment listings with prices and addresses", z.object({ listings: z.array( z.object({ price: z.string(), address: z.string(), }), ), }), ); console.log(data.listings); ``` ### Simple Extraction (without schema) ```typescript // Extract returns a default object with 'extraction' field const result = await stagehand.extract("extract the sign in button text"); console.log(result); // Output: { extraction: "Sign in" } // Or destructure directly const { extraction } = await stagehand.extract( "extract the sign in button text", ); console.log(extraction); // "Sign in" ``` ### Targeted Extraction Extract data from a specific element using a selector: ```typescript const reason = await stagehand.extract( "extract the reason why script injection fails", z.string(), { selector: "/html/body/div[2]/div[3]/iframe/html/body/p[2]" }, ); ``` ### URL Extraction When extracting links or URLs, use `z.string().url()`: ```typescript const { links } = await stagehand.extract( "extract all navigation links", z.object({ links: z.array(z.string().url()), }), ); ``` ### Extracting from a Specific Page ```typescript // Extract from a specific page (when you need to target a page that isn't currently active) const data = await stagehand.extract( "extract the placeholder text on the name field", { page: page2 }, ); ``` ## Observe Plan actions before executing them. Returns an array of candidate actions: ```typescript // Get candidate actions on the current active page const [action] = await stagehand.observe("Click the sign in button"); // Execute the action await stagehand.act(action); ``` Observing on a specific page: ```typescript // Target a specific page (when you need to target a page that isn't currently active) const actions = await stagehand.observe("find the next page button", { page: page2, }); await stagehand.act(actions[0], { page: page2 }); ``` ## Agent Use the `agent` method to autonomously execute complex, multi-step tasks. ### Basic Agent Usage ```typescript const page = stagehand.context.pages()[0]; await page.goto("https://www.google.com"); const agent = stagehand.agent({ model: "google/gemini-2.0-flash", executionModel: "google/gemini-2.0-flash", }); const result = await agent.execute({ instruction: "Search for the stock price of NVDA", maxSteps: 20, }); console.log(result.message); ``` ### Computer Use Agent (CUA) For more advanced scenarios using computer-use models: ```typescript const agent = stagehand.agent({ mode: "cua", // Enable Computer Use Agent mode model: "anthropic/claude-sonnet-4-20250514", // or "google/gemini-2.5-computer-use-preview-10-2025" systemPrompt: `You are a helpful assistant that can use a web browser. Do not ask follow up questions, the user will trust your judgement.`, }); await agent.execute({ instruction: "Apply for a library card at the San Francisco Public Library", maxSteps: 30, }); ``` ### Agent with Custom Model Configuration ```typescript const agent = stagehand.agent({ model: { modelName: "google/gemini-2.5-computer-use-preview-10-2025", apiKey: process.env.GEMINI_API_KEY, }, systemPrompt: `You are a helpful assistant.`, }); ``` ### Agent with Integrations (MCP/External Tools) ```typescript const agent = stagehand.agent({ integrations: [`https://mcp.exa.ai/mcp?exaApiKey=${process.env.EXA_API_KEY}`], systemPrompt: `You have access to the Exa search tool.`, }); ``` ## Advanced Features ### DeepLocator (XPath Targeting) Target specific elements across shadow DOM and iframes: ```typescript await page .deepLocator("/html/body/div[2]/div[3]/iframe/html/body/p") .highlight({ durationMs: 5000, contentColor: { r: 255, g: 0, b: 0 }, }); ``` ### Multi-Page Workflows ```typescript const page1 = stagehand.context.pages()[0]; await page1.goto("https://example.com"); const page2 = await stagehand.context.newPage(); await page2.goto("https://example2.com"); // Act/extract/observe operate on the current active page by default // Pass { page } option to target a specific page await stagehand.act("click button", { page: page1 }); await stagehand.extract("get title", { page: page2 }); ``` ## README.md
The AI Browser Automation Framework
Read the Docs
If you're looking for the Python implementation, you can find it here
## What is Stagehand? Stagehand is a browser automation framework used to control web browsers with natural language and code. By combining the power of AI with the precision of code, Stagehand makes web automation flexible, maintainable, and actually reliable. ## Why Stagehand? Most existing browser automation tools either require you to write low-level code in a framework like Selenium, Playwright, or Puppeteer, or use high-level agents that can be unpredictable in production. By letting developers choose what to write in code vs. natural language (and bridging the gap between the two) Stagehand is the natural choice for browser automations in production. 1. **Choose when to write code vs. natural language**: use AI when you want to navigate unfamiliar pages, and use code when you know exactly what you want to do. 2. **Go from AI-driven to repeatable workflows**: Stagehand lets you preview AI actions before running them, and also helps you easily cache repeatable actions to save time and tokens. 3. **Write once, run forever**: Stagehand's auto-caching combined with self-healing remembers previous actions, runs without LLM inference, and knows when to involve AI whenever the website changes and your automation breaks. ## Getting Started Start with Stagehand with one line of code, or check out our [Quickstart Guide](https://docs.stagehand.dev/v3/first-steps/quickstart) for more information: ```bash npx create-browser-app ``` ## Example Here's how to build a sample browser automation with Stagehand: ```typescript // Stagehand's CDP engine provides an optimized, low level interface to the browser built for automation const page = stagehand.context.pages()[0]; await page.goto("https://github.com/browserbase"); // Use act() to execute individual actions await stagehand.act("click on the stagehand repo"); // Use agent() for multi-step tasks const agent = stagehand.agent(); await agent.execute("Get to the latest PR"); // Use extract() to get structured data from the page const { author, title } = await stagehand.extract( "extract the author and title of the PR", z.object({ author: z.string().describe("The username of the PR author"), title: z.string().describe("The title of the PR"), }), ); ``` ## Documentation Visit [docs.stagehand.dev](https://docs.stagehand.dev) to view the full documentation. ### Build and Run from Source ```bash git clone https://github.com/browserbase/stagehand.git cd stagehand pnpm install pnpm run build pnpm run example # run the blank script at ./examples/example.ts ``` Stagehand is best when you have an API key for an LLM provider and Browserbase credentials. To add these to your project, run: ```bash cp .env.example .env nano .env # Edit the .env file to add API keys ``` ### Installing from a branch You can install and build Stagehand directly from a github branch using [gitpkg](https://github.com/EqualMa/gitpkg) In your project's `package.json` set: ```json "@browserbasehq/stagehand": "https://gitpkg.now.sh/browserbase/stagehand/packages/core?