Agent Runtime
Status: Connected
Parsing documentation...
Extracted api references
Generating type definitions...
opensteeropensteer
Y Combinator logoBacked by Y Combinator.

The most comprehensive browser automation framework for AI

Enterprise-grade automation at scale.

Custom plans, unlimited concurrent sessions, dedicated proxies, and advanced support for teams that need more.

+ self-service sso
+ unlimited concurrent sessions
+ custom audit logs
+ advanced captcha bypass
+ dedicated support
view pricing

Simple, transparent pricing.

Start for free, upgrade when you need to scale. Everything you need to build robust AI agents.

Getting Started

Quick Start

Install Opensteer, explore a site, extract data, and reverse-engineer an API

Quick Start

Install

npm install -g opensteer

Install the browser binary:

npx playwright install chromium

Add skills to your AI agent (Claude Code, Codex, Cursor):

opensteer skills install

Part 1: Browse and extract data

Open a browser, take a snapshot, interact with elements, and extract structured data.

Open a page

opensteer open https://example.com --workspace demo
import { Opensteer } from "opensteer";

const os = new Opensteer({ workspace: "demo" });
await os.open("https://example.com");

Take a snapshot

Snapshots annotate every element with a counter reference (c="1", c="2", etc).

opensteer snapshot action --workspace demo
const snap = await os.snapshot("action");

Output:

<div c="1">
  <h1 c="2">Example Domain</h1>
  <p c="3">This domain is for use in illustrative examples.</p>
  <a c="4" href="https://www.iana.org/domains/example">More information...</a>
</div>

Interact with elements

Use the counter value to target any element.

opensteer click --workspace demo --element 4
await os.click({ element: 4 });

Extract structured data

Pull data from the page into JSON.

opensteer extract --workspace demo --description "page heading"
const data = await os.extract({
  description: "product details",
  schema: {
    name: { element: 2 },
    price: { element: 5 },
    rating: { element: 8 },
  },
});

Part 2: Reverse-engineer APIs

Capture the network requests a website makes, turn them into reusable request plans, and replay them directly without a browser.

Capture network traffic

Navigate to a page with network capture enabled.

opensteer goto https://example.com/search?q=laptop --workspace demo --capture-network load
await os.goto({ url: "https://example.com/search?q=laptop", captureNetwork: "load" });

Find the API call you want

Query the captured requests to find the one you need.

opensteer network query --workspace demo --capture load
const records = await os.queryNetwork({ capture: "load", includeBodies: true });

Create a request plan

Turn a captured request into a reusable template.

opensteer request-plan infer --workspace demo --record-id rec-123 --key api.search --version v1
await os.inferRequestPlan({
  recordId: "rec-123",
  key: "api.search",
  version: "v1",
});

Replay the API directly

Execute the request plan with new parameters. No browser needed.

opensteer request execute --workspace demo --key api.search --input-json '{"query":{"q":"laptops"}}'
const result = await os.request("api.search", { query: { q: "laptops" } });

Full example: extract + API replay

import { Opensteer } from "opensteer";

const os = new Opensteer({ workspace: "demo" });
await os.open("https://example.com");

// Extract data from the page
const snap = await os.snapshot("action");
const data = await os.extract({
  description: "page content",
  schema: { heading: { element: 2 }, linkText: { element: 4 } },
});
console.log(data);

// Capture and reverse-engineer an API
await os.goto({ url: "https://example.com/search?q=test", captureNetwork: "load" });
const records = await os.queryNetwork({ capture: "load", includeBodies: true });
await os.inferRequestPlan({
  recordId: records.records[0].recordId,
  key: "search",
  version: "v1",
});

// Replay the API without a browser
const result = await os.request("search", { query: { q: "laptops" } });
console.log(result.body);

await os.close();