Get the FREE Ultimate OpenClaw Setup Guide →
p

Browserbase

Scanned

@pkiv

npx machina-cli add skill @pkiv/browse --openclaw
Files (1)
SKILL.md
11.2 KB

Browser Automation & Functions Skill

Complete guide for creating and deploying browser automation functions using the stagehand CLI.

When to Use

  • User wants to automate a website task
  • User needs to scrape data from a site
  • User wants to create a Browserbase Function
  • User wants to deploy automation to run on a schedule or via webhook

Prerequisites

Set Up Credentials

stagehand fn auth status  # Check if configured
stagehand fn auth login   # If needed - get credentials from https://browserbase.com/settings

Complete Workflow

Step 1: Explore the Site Interactively

Start a local browser session to understand the site structure:

stagehand session create --local
stagehand goto https://example.com
stagehand snapshot                    # Get DOM structure with refs
stagehand screenshot -o page.png      # Visual inspection

Test interactions manually:

stagehand click @0-5
stagehand fill @0-6 "value"
stagehand eval "document.querySelector('.price').textContent"
stagehand session end  # When done exploring

Step 2: Initialize Function Project

stagehand fn init my-automation
cd my-automation

Creates:

  • package.json - Dependencies
  • .env - Credentials (from ~/.stagehand/config.json)
  • index.ts - Function template
  • tsconfig.json - TypeScript config

Step 3: ⚠️ FIX package.json IMMEDIATELY

CRITICAL BUG: stagehand fn init generates incomplete package.json that causes deployment to fail with "No functions were built."

REQUIRED FIX - Update package.json before doing anything else:

{
  "name": "my-automation",
  "version": "1.0.0",
  "description": "My automation description",
  "main": "index.js",
  "type": "module",
  "packageManager": "pnpm@10.14.0",
  "scripts": {
    "dev": "pnpm bb dev index.ts",
    "publish": "pnpm bb publish index.ts"
  },
  "dependencies": {
    "@browserbasehq/sdk-functions": "^0.0.5",
    "playwright-core": "^1.58.0"
  },
  "devDependencies": {
    "@types/node": "^25.0.10",
    "typescript": "^5.9.3"
  }
}

Key changes from generated file:

  • ✅ Add description and main fields
  • ✅ Add packageManager field
  • ✅ Change "latest" to pinned versions like "^0.0.5"
  • ✅ Add devDependencies with TypeScript and types

Then install:

pnpm install

Step 4: Write Automation Code

Edit index.ts:

import { defineFn } from "@browserbasehq/sdk-functions";
import { chromium } from "playwright-core";

defineFn("my-automation", async (context) => {
  const { session, params } = context;
  console.log("Connecting to browser session:", session.id);

  const browser = await chromium.connectOverCDP(session.connectUrl);
  const page = browser.contexts()[0]!.pages()[0]!;

  // Your automation here
  await page.goto("https://example.com");
  await page.waitForLoadState("domcontentloaded");

  // Extract data
  const data = await page.evaluate(() => {
    // Complex extraction logic
    return Array.from(document.querySelectorAll('.item')).map(el => ({
      title: el.querySelector('.title')?.textContent,
      value: el.querySelector('.value')?.textContent,
    }));
  });

  // Return results (must be JSON-serializable)
  return {
    success: true,
    count: data.length,
    data,
    timestamp: new Date().toISOString(),
  };
});

Key Concepts:

  • context.session - Browser session info (id, connectUrl)
  • context.params - Input parameters from invocation
  • Return JSON-serializable data
  • 15 minute max execution time

Step 5: Test Locally

Start dev server:

pnpm bb dev index.ts

Server runs at http://127.0.0.1:14113

Invoke with curl:

curl -X POST http://127.0.0.1:14113/v1/functions/my-automation/invoke \
  -H "Content-Type: application/json" \
  -d '{"params": {"url": "https://example.com"}}'

Dev server auto-reloads on file changes. Check terminal for logs.

Step 6: Deploy to Browserbase

pnpm bb publish index.ts
# or: stagehand fn publish index.ts

Expected output:

✓ Build completed successfully
Build ID: xxx-xxx-xxx
Function ID: yyy-yyy-yyy  ← Save this!

If you see "No functions were built" → Your package.json is incomplete (see Step 3).

Step 7: Test Production

stagehand fn invoke <function-id> -p '{"param": "value"}'

Or via API:

curl -X POST https://api.browserbase.com/v1/functions/<function-id>/invoke \
  -H "Content-Type: application/json" \
  -H "x-bb-api-key: $BROWSERBASE_API_KEY" \
  -d '{"params": {}}'

Complete Working Example: Hacker News Scraper

import { defineFn } from "@browserbasehq/sdk-functions";
import { chromium } from "playwright-core";

defineFn("hn-scraper", async (context) => {
  const { session } = context;
  console.log("Connecting to browser session:", session.id);

  const browser = await chromium.connectOverCDP(session.connectUrl);
  const page = browser.contexts()[0]!.pages()[0]!;

  await page.goto("https://news.ycombinator.com");
  await page.waitForLoadState("domcontentloaded");

  // Extract top 10 stories
  const stories = await page.evaluate(() => {
    const storyRows = Array.from(document.querySelectorAll('.athing')).slice(0, 10);

    return storyRows.map((row) => {
      const titleLine = row.querySelector('.titleline a');
      const subtext = row.nextElementSibling?.querySelector('.subtext');
      const commentsLink = Array.from(subtext?.querySelectorAll('a') || []).pop();

      return {
        rank: row.querySelector('.rank')?.textContent?.replace('.', '') || '',
        title: titleLine?.textContent || '',
        url: titleLine?.getAttribute('href') || '',
        points: subtext?.querySelector('.score')?.textContent?.replace(' points', '') || '0',
        author: subtext?.querySelector('.hnuser')?.textContent || '',
        time: subtext?.querySelector('.age')?.textContent || '',
        comments: commentsLink?.textContent?.replace(/\u00a0comments?/, '').trim() || '0',
        id: row.id,
      };
    });
  });

  return {
    success: true,
    count: stories.length,
    stories,
    timestamp: new Date().toISOString(),
  };
});

Common Patterns

Parameterized Scraping

defineFn("scrape", async (context) => {
  const { session, params } = context;
  const { url, selector } = params;  // Accept params from invocation

  const browser = await chromium.connectOverCDP(session.connectUrl);
  const page = browser.contexts()[0]!.pages()[0]!;

  await page.goto(url);
  const data = await page.$$eval(selector, els =>
    els.map(el => el.textContent)
  );

  return { url, data };
});

Authentication

defineFn("auth-action", async (context) => {
  const { session, params } = context;
  const { username, password } = params;

  const browser = await chromium.connectOverCDP(session.connectUrl);
  const page = browser.contexts()[0]!.pages()[0]!;

  await page.goto("https://example.com/login");
  await page.fill('input[name="email"]', username);
  await page.fill('input[name="password"]', password);
  await page.click('button[type="submit"]');
  await page.waitForURL("**/dashboard");

  const data = await page.textContent('.user-data');
  return { success: true, data };
});

Multi-Page Workflow

defineFn("multi-page", async (context) => {
  const { session, params } = context;
  const browser = await chromium.connectOverCDP(session.connectUrl);
  const page = browser.contexts()[0]!.pages()[0]!;

  const results = [];
  for (const url of params.urls) {
    await page.goto(url);
    await page.waitForLoadState("domcontentloaded");

    const title = await page.title();
    results.push({ url, title });
  }

  return { results };
});

Troubleshooting

🔴 "No functions were built. Please check your entrypoint and function exports."

This is the #1 error!

Cause: Generated package.json from stagehand fn init is incomplete.

Fix:

  1. Update package.json (see Step 3 above)
  2. Add all required fields: description, main, packageManager
  3. Change "latest" to pinned versions like "^0.0.5"
  4. Add devDependencies section with TypeScript and types
  5. Run pnpm install
  6. Try deploying again

Quick check: Compare your package.json to bitcoin-functions/package.json in the codebase.

Local dev server won't start

# Check credentials
stagehand fn auth status

# Re-login if needed
stagehand fn auth login

# Install SDK globally
pnpm add -g @browserbasehq/sdk-functions

Function works locally but fails on deploy

Common causes:

  1. Missing devDependencies (TypeScript won't compile)
  2. Using "latest" instead of pinned versions
  3. Missing required fields in package.json

Solution: Fix package.json as described in Step 3.

Cannot extract data from page

  1. Take screenshot: stagehand screenshot -o debug.png
  2. Get snapshot: stagehand snapshot
  3. Use page.evaluate() to log what's in the DOM
  4. Check if selectors match actual HTML structure

"Invocation timed out"

  • Functions have 15 minute max
  • Use specific waits instead of long sleeps
  • Check if page is actually loading

Best Practices

  1. Fix package.json immediately after stagehand fn init
  2. Explore interactively first - Use local browser session to understand site
  3. Test manually - Verify each step works before writing code
  4. Test locally - Use dev server before deploying
  5. Return meaningful data - Include timestamps, counts, URLs
  6. Handle errors gracefully - Try/catch around risky operations
  7. Use specific selectors - Prefer data attributes over CSS classes
  8. Add logging - console.log() helps debug deployed functions
  9. Validate parameters - Check params before using
  10. Set reasonable timeouts - Don't wait forever

Quick Checklist

  • Explore site with stagehand session create --local
  • Test interactions manually
  • Create project: stagehand fn init <name>
  • Fix package.json immediately (Step 3)
  • Run pnpm install
  • Write automation in index.ts
  • Test locally: pnpm bb dev index.ts
  • Verify with curl
  • Deploy: pnpm bb publish index.ts
  • Test production: stagehand fn invoke <function-id>
  • Save function ID

Code Fix Needed (For Maintainers)

File: /src/commands/functions.ts Lines: 146-158 Function: initFunction()

Replace the current packageJson object with:

const packageJson = {
  name,
  version: '1.0.0',
  description: `${name} function`,
  main: 'index.js',
  type: 'module',
  packageManager: 'pnpm@10.14.0',
  scripts: {
    dev: 'pnpm bb dev index.ts',
    publish: 'pnpm bb publish index.ts',
  },
  dependencies: {
    '@browserbasehq/sdk-functions': '^0.0.5',
    'playwright-core': '^1.58.0',
  },
  devDependencies: {
    '@types/node': '^25.0.10',
    'typescript': '^5.9.3',
  },
};

This will eliminate the "No functions were built" error for all new projects.

Source

git clone https://clawhub.ai/pkiv/browseView on GitHub

Overview

Browserbase provides a complete guide to creating and deploying browser automation functions using the Stagehand CLI. It covers interactive site exploration, function project setup, code writing, and local testing to enable reliable automated tasks and data extraction.

How This Skill Works

Use Stagehand to start a local browser session, explore the site structure, and test interactions. Then scaffold a function with stagehand fn init, modify package.json as guided, and implement the automation in TypeScript using the Browserbase SDK and Playwright. Your function runs in a defined environment and returns JSON-serializable data, with a 15-minute execution limit.

When to Use It

  • Automate a website task
  • Scrape data from a site
  • Create a Browserbase Function
  • Deploy automation to run on a schedule or via webhook
  • Prototype and test flows in a local session

Quick Start

  1. Step 1: Start a local browser session and explore the site with Stagehand
  2. Step 2: Run stagehand fn init my-automation and open the project folder
  3. Step 3: Fix package.json per the guide, install dependencies, and implement index.ts

Best Practices

  • Start with interactive site exploration using a local browser session
  • Initialize a function project with stagehand and customize file structure
  • Apply the critical package.json fixes before deployment
  • Ensure the function returns JSON-serializable data and stays under 15 minutes
  • Test locally with pnpm bb dev and validate deployment readiness

Example Use Cases

  • Automate login to a dashboard and scrape KPI metrics
  • Scrape product prices across multiple pages for comparison
  • Run a daily stock status check and push webhook alerts
  • Automate form submissions for routine data entry tasks
  • Render and capture pages for archival and QA checks

Frequently Asked Questions

Add this skill to your agents
Sponsor this space

Reach thousands of developers