Skip to main content
Stagehand provides four core AI methods for browser automation: act(), extract(), observe(), and agent().

Access

Available on all sessions except Selenium:
import { playwright } from '@bctrl/sdk';

const session = await playwright.connect({ apiKey: '...' });

// Use Stagehand methods
await session.stagehand.act('...');
await session.stagehand.extract('...', schema);
await session.stagehand.observe();
const agent = session.stagehand.agent();

act()

Execute a single action using natural language.
await session.stagehand.act('Click the login button');

Examples

// Clicks
await session.stagehand.act('Click the Sign In button');
await session.stagehand.act('Click the first search result');

// Typing
await session.stagehand.act('Type "hello world" in the search box');
await session.stagehand.act('Fill the email field with [email protected]');

// Selection
await session.stagehand.act('Select "California" from the state dropdown');
await session.stagehand.act('Check the "Remember me" checkbox');

// Navigation
await session.stagehand.act('Scroll down to the pricing section');
await session.stagehand.act('Click the Next Page button');

// Complex
await session.stagehand.act('Close the cookie consent banner');
await session.stagehand.act('Expand the "Advanced Options" section');

Options

const result = await session.stagehand.act('Click submit', {
  modelName: 'gpt-4o',        // LLM to use
  timeout: 30000,             // Timeout in ms
});

Return Value

interface ActResult {
  success: boolean;
  action: {
    type: 'click' | 'type' | 'scroll' | 'wait' | 'goto';
    description: string;
    selector?: string;
    value?: string;
  };
}

extract()

Extract structured data from the page.
import { z } from 'zod';

const data = await session.stagehand.extract(
  'Get the product details',
  z.object({
    name: z.string(),
    price: z.number()
  })
);

Schema Types

// String
const title = await session.stagehand.extract(
  'Get the page title',
  z.string()
);

// Number
const price = await session.stagehand.extract(
  'Get the product price',
  z.number()
);

// Boolean
const inStock = await session.stagehand.extract(
  'Is the product in stock?',
  z.boolean()
);

// Object
const product = await session.stagehand.extract(
  'Get product details',
  z.object({
    name: z.string(),
    price: z.number(),
    description: z.string(),
    rating: z.number().optional()
  })
);

// Array
const items = await session.stagehand.extract(
  'Get all menu items with prices',
  z.array(z.object({
    name: z.string(),
    price: z.number()
  }))
);

// Enum
const status = await session.stagehand.extract(
  'What is the order status?',
  z.enum(['pending', 'processing', 'shipped', 'delivered'])
);

Tips for Better Extraction

// Bad - vague
await session.stagehand.extract('Get the data', schema);

// Good - specific
await session.stagehand.extract(
  'Get all product names and prices from the search results table',
  schema
);
// Bad - string for numbers
z.object({ price: z.string() })

// Good - proper types
z.object({ price: z.number() })
z.object({
  name: z.string(),
  rating: z.number().optional(),  // May not exist
  reviews: z.array(z.string()).default([])
})

observe()

Identify available actions on the current page.
const actions = await session.stagehand.observe();

Examples

// Get all available actions
const actions = await session.stagehand.observe();
// Returns: StagehandAction[]

// With specific instruction
const buttons = await session.stagehand.observe('Find all clickable buttons');
const forms = await session.stagehand.observe('Find all form inputs');

Use Cases

// Discover page structure
const actions = await session.stagehand.observe();
console.log('Available actions:', actions);

// Then act on what you found
if (actions.some(a => a.description.includes('login'))) {
  await session.stagehand.act('Click the login button');
}

agent()

Create an autonomous agent for multi-step tasks.
const agent = session.stagehand.agent({
  maxSteps: 10
});

const result = await agent.execute('Book a flight from NYC to LA');

Configuration

const agent = session.stagehand.agent({
  modelName: 'gpt-4o',      // LLM to use
  maxSteps: 10,             // Maximum actions
  maxRetries: 3,            // Retries per step
  temperature: 0.1          // LLM temperature
});

Execution

const result = await agent.execute(
  'Search for laptops under $500 and add the best-rated one to cart'
);

console.log(result.success);    // boolean
console.log(result.message);    // Summary
console.log(result.actions);    // All actions taken

Example

import { playwright } from '@bctrl/sdk';

const session = await playwright.connect({ apiKey: '...' });
await session.page.goto('https://amazon.com');

const agent = session.stagehand.agent({
  modelName: 'gpt-4o',
  maxSteps: 15
});

const result = await agent.execute(`
  1. Search for "wireless headphones"
  2. Filter by 4+ star rating
  3. Sort by price low to high
  4. Click on the first result
  5. Add it to cart
`);

if (result.success) {
  console.log('Added to cart!');
  console.log('Actions taken:', result.actions.length);
}

await session.close();

Metrics & History

Track AI usage:
// Get usage metrics
const metrics = await session.stagehand.getMetrics();
console.log('Total tokens:', metrics.totalInputTokens + metrics.totalOutputTokens);
console.log('Total actions:', metrics.totalActions);

// Get operation history
const history = await session.stagehand.getHistory();
for (const entry of history) {
  console.log(entry.action, entry.success);
}

Full Example

import { playwright } from '@bctrl/sdk';
import { z } from 'zod';

async function scrapeAndAnalyze() {
  const session = await playwright.connect({
    apiKey: process.env.BCTRL_API_KEY
  });

  const page = session.page;
  await page.goto('https://news.ycombinator.com');

  // Extract top stories
  const stories = await session.stagehand.extract(
    'Get the top 10 stories with title, URL, points, and comment count',
    z.array(z.object({
      title: z.string(),
      url: z.string(),
      points: z.number(),
      comments: z.number()
    }))
  );

  console.log('Top stories:', stories);

  // Navigate and extract more
  await session.stagehand.act('Click on the top story');

  // Let agent summarize
  const agent = session.stagehand.agent({ maxSteps: 5 });
  const summary = await agent.execute(
    'Read the article and provide a 2-sentence summary'
  );

  console.log('Summary:', summary.message);

  // Check metrics
  const metrics = await session.stagehand.getMetrics();
  console.log('Tokens used:', metrics.totalInputTokens + metrics.totalOutputTokens);

  await session.close();
}

scrapeAndAnalyze();