JavaScript / TypeScript

The browsy-ai npm package provides a TypeScript SDK for the browsy REST API, plus ready-made integrations for LangChain.js, OpenAI, and Vercel AI SDK.

Installation

npm install browsy-ai

The package uses ESM and requires Node.js 22+. Framework dependencies are optional peer dependencies — install only what you need.

Core SDK

The core SDK manages the browsy server process, HTTP communication, and per-agent session isolation.

import { BrowsyClient, BrowsyContext, ServerManager } from "browsy-ai";

BrowsyContext

The simplest way to use browsy. BrowsyContext is a facade that coordinates the client, server manager, and session manager.

import { BrowsyContext } from "browsy-ai";

const ctx = new BrowsyContext({ port: 3847 });

// Execute tool calls — server auto-starts, sessions auto-managed
const page = await ctx.executeToolCall("browse", { url: "https://example.com" });
console.log(page);

const info = await ctx.executeToolCall("pageInfo", {});
console.log(info);

BrowsyClient

Lower-level HTTP client for direct API calls. Use this when you manage the server and sessions yourself.

import { BrowsyClient } from "browsy-ai";

const client = new BrowsyClient(3847);

// Navigate
const res = await client.browse({ url: "https://example.com" });
console.log(res.body);

// Interact using the session from the response
await client.typeText({ id: 5, text: "hello" }, res.session);
await client.click({ id: 12 }, res.session);

// Extract data
const tables = await client.tables(res.session);
const info = await client.pageInfo(res.session);

Configuration

import { BrowsyContext } from "browsy-ai";

const ctx = new BrowsyContext({
  port: 3847,           // REST server port (default: 3847)
  autoStart: true,      // Auto-start browsy serve (default: true)
  allowPrivateNetwork: false,  // Allow private network URLs (default: false)
  serverTimeout: 10_000,      // Startup timeout in ms (default: 10000)
});

When autoStart is true, the SDK finds the browsy binary in your PATH (or via the BROWSY_BIN environment variable) and spawns browsy serve --port <port>.

Session isolation

Each agent gets its own isolated browsing session with independent cookies, history, and form state:

const ctx = new BrowsyContext();

// Different agents get different sessions
const page1 = await ctx.executeToolCall("browse", { url: "https://a.com" }, "agent-1");
const page2 = await ctx.executeToolCall("browse", { url: "https://b.com" }, "agent-2");

LangChain.js

npm install browsy-ai @langchain/core
import { getTools } from "browsy-ai/langchain";

Quick start

import { getTools } from "browsy-ai/langchain";
import { ChatOpenAI } from "@langchain/openai";
import { createReactAgent } from "@langchain/langgraph/prebuilt";

const tools = getTools({ port: 3847 });
const llm = new ChatOpenAI({ model: "gpt-4o" });
const agent = createReactAgent({ llm, tools });

const result = await agent.invoke({
  messages: [{ role: "user", content: "Go to news.ycombinator.com and list the top 5 stories" }],
});

Custom context

Pass a BrowsyContext for full control:

import { BrowsyContext } from "browsy-ai";
import { getTools } from "browsy-ai/langchain";

const ctx = new BrowsyContext({ port: 9000, autoStart: false });
const tools = getTools(ctx);

Available tools

getTools() returns 14 LangChain tool instances:

Tool nameParametersDescription
browsy_browseurl, format?, scope?Navigate to a URL
browsy_clickidClick an element by ID
browsy_type_textid, textType into an input field
browsy_checkidCheck a checkbox/radio
browsy_uncheckidUncheck a checkbox/radio
browsy_selectid, valueSelect a dropdown option
browsy_searchquery, engine?Web search
browsy_loginusername, passwordLog in using detected form
browsy_enter_codecodeEnter 2FA/verification code
browsy_findtext?, role?Find elements by text or role
browsy_get_pageformat?, scope?Get current page with form state
browsy_page_infoPage metadata and suggested actions
browsy_tablesExtract structured table data
browsy_backGo back in history

OpenAI

npm install browsy-ai openai
import { getToolDefinitions, handleToolCall } from "browsy-ai/openai";

Quick start

import OpenAI from "openai";
import { getToolDefinitions, handleToolCall, createToolCallHandler } from "browsy-ai/openai";

const client = new OpenAI();
const tools = getToolDefinitions();

const messages = [
  { role: "user" as const, content: "Go to example.com and tell me what's there." },
];

let response = await client.chat.completions.create({
  model: "gpt-4o",
  messages,
  tools,
});

// Tool call loop
while (response.choices[0].message.tool_calls?.length) {
  const msg = response.choices[0].message;
  messages.push(msg);

  for (const toolCall of msg.tool_calls!) {
    const args = JSON.parse(toolCall.function.arguments);
    const result = await handleToolCall(toolCall.function.name, args);

    messages.push({
      role: "tool" as const,
      tool_call_id: toolCall.id,
      content: result,
    });
  }

  response = await client.chat.completions.create({
    model: "gpt-4o",
    messages,
    tools,
  });
}

console.log(response.choices[0].message.content);

Bound handler

Use createToolCallHandler() to get a pre-bound handler:

import { getToolDefinitions, createToolCallHandler } from "browsy-ai/openai";

const tools = getToolDefinitions();
const handle = createToolCallHandler({ port: 3847 });

// In your tool call loop:
const result = await handle(toolCall.function.name, args);

Vercel AI SDK

npm install browsy-ai ai
import { browsyTools } from "browsy-ai/vercel-ai";

Quick start

import { generateText } from "ai";
import { openai } from "@ai-sdk/openai";
import { browsyTools } from "browsy-ai/vercel-ai";

const result = await generateText({
  model: openai("gpt-4o"),
  tools: browsyTools(),
  prompt: "Go to news.ycombinator.com and list the top 5 stories",
  maxSteps: 10,
});

console.log(result.text);

Custom context

import { BrowsyContext } from "browsy-ai";
import { browsyTools } from "browsy-ai/vercel-ai";

const ctx = new BrowsyContext({ port: 9000 });
const tools = browsyTools(ctx);

Zod schemas

All tool parameter schemas are exported as Zod objects for use in custom integrations:

import {
  BrowseParams,
  ClickParams,
  TypeTextParams,
  SearchParams,
  TOOL_DESCRIPTIONS,
  TOOL_SCHEMAS,
} from "browsy-ai";

// Use in your own tool definitions
const parsed = BrowseParams.parse({ url: "https://example.com" });

// Iterate over all tools
for (const { name, method, schema } of TOOL_SCHEMAS) {
  console.log(name, TOOL_DESCRIPTIONS[name]);
}

Prerequisites

The SDK talks to a browsy REST server. You need the browsy CLI installed:

cargo install browsy

With autoStart: true (the default), the SDK starts the server automatically. With autoStart: false, start it manually:

browsy serve --port 3847