Stagehand: AI-Powered Browser Automation That Combines Code and Natural Language (2026)
Stagehand is BrowserBase's open-source framework that extends Playwright with LLM-powered natural language commands. You can page.act("click the login button") or page.extract({ instruction: "...", schema: {...} }) instead of writing brittle selectors. Stagehand shines on complex, dynamic UIs; plain Playwright remains better for high-volume scraping where LLM latency and cost matter. Use Apify for scalable browser automation.
What Stagehand Is
Stagehand wraps Playwright with methods that use an LLM to interpret your intent:
page.act(instruction)— Performs an action (click, type, scroll) based on natural languagepage.extract({ instruction, schema })— Extracts structured data using an LLM to find and parse contentpage.observe()— Captures page structure for the LLM to reason about
Under the hood, Playwright handles browser control; the LLM interprets ambiguous or dynamic UI when selectors would break. You need an Anthropic or OpenAI API key. Stagehand is free and open-source; you pay for LLM calls.
Key Methods
| Method | Purpose | When to Use |
|---|---|---|
act(instruction) | Perform an action from natural language | Buttons, links, forms with changing IDs |
extract({ instruction, schema }) | Extract structured data | Tables, lists, cards with variable layout |
observe() | Get page context for LLM | Debugging, multi-step reasoning |
extractOne(selector, schema) | Extract from a specific element | When you have a stable selector |
extractMany(selector, schema) | Extract list from matching elements | Product grids, search results |
For stable sites with consistent selectors, use Playwright's page.locator() and evaluate(). For sites that change often or have opaque class names, Stagehand's natural language layer reduces maintenance.
How It Works
- You call
page.act("click the accept cookies button")orpage.extract({ instruction: "Get product name and price", schema: { name: "string", price: "string" } }). - Stagehand captures a snapshot of the page (DOM, screenshot, or both) and sends it to the LLM.
- LLM determines which element to click or how to map content to your schema.
- Stagehand translates that into Playwright calls (
page.click(selector),page.fill(), etc.) and executes them.
The LLM adds latency (often 1–5 seconds per call) and cost (tokens per request). For high-throughput scraping, that adds up quickly.
When Stagehand Beats Plain Playwright
- Complex dynamic UIs — React/Vue apps with generated class names, A/B-tested layouts
- Sites that change frequently — Selectors break; natural language is more resilient
- Rapid prototyping — Get something working before investing in robust selectors
- Ad-hoc extraction — One-off scripts where LLM cost is acceptable
- Accessibility-driven actions — "Click the submit button" works even if the DOM changes
When Plain Playwright Is Better
- High-volume scraping — Thousands of pages; LLM cost and latency dominate
- Stable selectors — Site structure is predictable; locators are reliable
- CI/test automation — Determinism matters; no LLM variance
- Budget-sensitive — Minimize API calls; use HTTP + proxy for simple HTML
Use Stagehand for the 10% of targets that resist traditional automation. Use Playwright (and Crawlee) for the rest. See Playwright vs Puppeteer vs Selenium for stack choices.
Code Example: Scraping a Complex SPA
const { Stagehand } = require('@browserbasehq/stagehand');
async function scrapeProductPage(url) {
const stagehand = new Stagehand({
env: "BROWSERBASE",
apiKey: process.env.BROWSERBASE_API_KEY,
enableCaching: true,
});
await stagehand.init();
const page = stagehand.page;
await page.goto(url);
// Natural language action — works even if button ID changes
await page.act("Close the cookie banner if it appears");
// Extract structured data with LLM
const products = await page.extract({
instruction: "Extract all product cards: name, price, and image URL",
schema: {
type: "object",
properties: {
items: {
type: "array",
items: {
type: "object",
properties: {
name: { type: "string" },
price: { type: "string" },
imageUrl: { type: "string" },
},
},
},
},
required: ["items"],
},
});
await stagehand.close();
return products;
}
Stagehand can use BrowserBase's cloud browsers or local Playwright. Set env: "LOCAL" for local execution; env: "BROWSERBASE" for cloud. BrowserBase provides persistent sessions and screenshot-based debugging, useful when debugging LLM-driven flows across page transitions. For cost-sensitive development, start with LOCAL and switch to BrowserBase only when you need cloud scale or session persistence.
Setup
npm install @browserbasehq/stagehand playwright
Configure one of:
ANTHROPIC_API_KEY— For Claude (default)OPENAI_API_KEY— For GPT-4
Optional: BROWSERBASE_API_KEY for BrowserBase cloud. Without it, Stagehand uses local browsers.
Comparison: Stagehand vs Alternatives
| Attribute | Stagehand | Playwright + AI Extension | Manual Playwright + LLM Fallback |
|---|---|---|---|
| Natural language | ✓ Built-in | Varies | Manual prompt engineering |
| Extraction | extract() with schema | Depends | Custom LLM + parser |
| Actions | act() | Varies | Manual selector or LLM |
| Cost | Per act/extract | Per call | Per call |
| Determinism | Lower (LLM variance) | Lower | Higher with selectors |
| Best for | Complex SPAs, rapid protos | Similar | Full control |
Stagehand gives you a ready-made integration. Manual Playwright + LLM gives more control but more code. Choose based on how much you value speed of development vs. cost and determinism.
Integration with Apify
You can use Stagehand inside an Apify Actor:
- Add
@browserbasehq/stagehandtopackage.json - Set
ANTHROPIC_API_KEYorOPENAI_API_KEYas a secret in Apify - Use Stagehand in your Actor's main function instead of (or alongside) raw Playwright
- Store results in the default dataset
Stagehand fits when an Actor targets a few complex pages (e.g., login flows, dynamic dashboards). For bulk crawling, prefer plain Playwright with Crawlee. A common pattern: use Stagehand for the login or cookie-consent step, then switch to standard Playwright selectors for the main extraction loop. See building an Apify Actor with TypeScript for the Actor structure. For anti-bot sites, combine with Bright Data Scraping Browser.
Use Stagehand for the hard parts (login, dynamic extraction), Playwright for the rest. Deploy to Apify for scheduling and scaling.
Stagehand is BrowserBase's open-source framework that adds LLM-powered natural language to Playwright. You use act() and extract() instead of writing selectors.
Use Stagehand for complex dynamic UIs, sites that change frequently, or rapid prototyping. Use plain Playwright for high-volume scraping and stable sites.
Stagehand itself is free. You pay for LLM API calls (Anthropic or OpenAI). Each act() and extract() costs tokens. For thousands of pages, costs add up.
Yes. Add Stagehand to your Apify Actor's dependencies. Use it for complex pages; use Crawlee/Playwright for bulk crawling. Set LLM API keys as Apify secrets.
Yes. Set env to LOCAL and Stagehand uses local Playwright. You still need ANTHROPIC_API_KEY or OPENAI_API_KEY for act() and extract().
Less so than plain Playwright. LLM output can vary. For critical paths, combine Stagehand with fallback selectors or validation.




