Skip to main content

View on GitHub

View on NPM

Installation

Install the Hyperbrowser SDK via npm or yarn:
npm install @hyperbrowser/sdk dotenv

Quick Start

Initialize the client with your API key:
import { Hyperbrowser } from "@hyperbrowser/sdk";
import { config } from "dotenv";

config();

const client = new Hyperbrowser({
  apiKey: process.env.HYPERBROWSER_API_KEY,
});

Configuration Options

interface HyperbrowserConfig {
  apiKey?: string; // API key (can also use HYPERBROWSER_API_KEY env var)
  baseUrl?: string; // Base API URL (default: "https://api.hyperbrowser.ai")
  timeout?: number; // Request timeout in milliseconds (default: 30000)
  runtimeProxyOverride?: string; // Optional host override for sandbox runtime traffic
}

TypeScript Support

The SDK is fully typed with TypeScript. Import types from @hyperbrowser/sdk/types:
import {
  SessionDetail,
  CreateSessionParams,
  CreateSandboxParams,
  ScrapeJobResponse,
  CrawlJobResponse,
  ExtractJobResponse,
  BrowserUseTaskResponse,
  // ... and many more
} from "@hyperbrowser/sdk/types";

Sandboxes

Sandbox APIs work in two layers. Sandbox control methods use your API key to create, inspect, connect to, and stop sandboxes. When you create or connect to a sandbox, the SDK also retrieves a sandbox-scoped runtime token and returns an authenticated SandboxHandle. Sandbox VM operations run inside that started sandbox and use the runtime token on the handle automatically. The SDK handles runtime token refreshes for you, so once you have a running SandboxHandle, you can call files, processes, terminal, networking, and snapshot methods without managing runtime auth yourself.

Sandbox Control

Use these methods to inspect existing sandboxes and discover reusable sandbox resources.

Details

List Sandboxes

const response = await client.sandboxes.list({
  status: "active", // optional: sandbox status filter
  search: "sdk", // optional: search term
  page: 1, // optional: page number
  limit: 20, // optional: results per page
});

console.log(response.totalCount);
console.log(response.sandboxes.map((entry) => entry.id));

List Images

const { images } = await client.sandboxes.listImages();
console.log(images.map((image) => image.imageName));

List Snapshots

const { snapshots } = await client.sandboxes.listSnapshots({
  imageName: "node", // optional: only snapshots for this image
  status: "created", // optional: snapshot status filter
  limit: 10, // optional: max results
});

console.log(snapshots.map((snapshot) => snapshot.snapshotName));

Get Sandbox Info

const detail = await sandbox.info();
console.log(detail.runtime.baseUrl);

Lifecycle

Use these methods to create, connect to, and stop sandbox instances.

Create Sandbox

Use client.sandboxes.create(...) to start a sandbox from an image.
const sandbox = await client.sandboxes.create({
  imageName: "node", // required unless restoring from a snapshot
  region: "us-west", // optional: sandbox region
  timeoutMinutes: 30, // optional: max sandbox lifetime
  enableRecording: true, // optional: record the sandbox
  exposedPorts: [{ port: 3000, auth: true }], // optional: pre-expose ports
});

Start From A Snapshot

Start a new sandbox from a memory checkpoint.
const sandbox = await client.sandboxes.create({
  snapshotName: "node-after-setup", // required: snapshot name
  snapshotId: "snapshot-id", // optional: pin a specific snapshot version
});

Connect To A Running Sandbox

Use connect(...) to re-authenticate a running sandbox, refresh its runtime token, and return a SandboxHandle for runtime operations. If you already have a handle, call sandbox.connect() to re-authenticate it in place.
const sandbox = await client.sandboxes.connect(
  "sandbox-id" // running sandbox ID
);
await sandbox.connect(); // re-authenticate an existing handle in place

Stop Sandbox

await sandbox.stop(); // stop the sandbox when finished

Sandbox VM Operations

These methods operate on the sandbox VM itself when the sandbox is running.

Networking

Expose Port

const exposure = await sandbox.expose({
  port: 3000, // required: port inside the sandbox
  auth: true, // optional: require the sandbox bearer token
});

console.log(exposure.url);

Unexpose Port

await sandbox.unexpose(
  3000 // exposed port to remove
);

Get Exposed URL

const url = sandbox.getExposedUrl(
  3000 // exposed port
);

console.log(url);

Processes

Run A Command

Use sandbox.exec(...) for one-shot commands. You can also pass a plain string like await sandbox.exec("node -v").
const result = await sandbox.exec({
  command: "bash", // required: command to run
  args: ["-lc", "pwd && echo $FOO"], // optional: command arguments
  cwd: "/tmp", // optional: working directory
  env: { FOO: "bar" }, // optional: environment variables
  timeoutMs: 5_000, // optional: runtime limit in milliseconds
  useShell: false, // optional: run through a shell
});

console.log(result.stdout.trim());

Start A Process

Use sandbox.processes.start(...) for long-running processes.
const process = await sandbox.processes.start({
  command: "bash", // required: command to run
  args: ["-lc", "sleep 30"], // optional: command arguments
  cwd: "/tmp", // optional: working directory
  env: { FOO: "bar" }, // optional: environment variables
});

console.log(process.id);

Get A Process

const process = await sandbox.getProcess(
  "process-id" // process ID
);

List Processes

const response = await sandbox.processes.list({
  status: ["queued", "running"], // optional: one status or multiple statuses
  limit: 20, // optional: max results
  cursor: "next-cursor", // optional: pagination cursor
  createdAfter: Date.now() - 60_000, // optional: lower timestamp bound
  createdBefore: Date.now(), // optional: upper timestamp bound
});

console.log(response.data.map((entry) => entry.id));

Write Process Stdin

await process.writeStdin({
  data: "hello\n", // optional: stdin payload
  encoding: "utf8", // optional: "utf8" or "base64"
  eof: true, // optional: close stdin after this write
});

Files

Read Text File

const text = await sandbox.files.readText(
  "/tmp/hello.txt", // path inside the sandbox
  {
    offset: 0, // optional: byte offset
    length: 128, // optional: max bytes to read
  }
);

console.log(text);

Write Text File

await sandbox.files.writeText(
  "/tmp/hello.txt", // path inside the sandbox
  "hello from sandbox", // file contents
  {
    append: true, // optional: append instead of overwrite
    mode: "0640", // optional: chmod-style mode string
  }
);

List Files

const entries = await sandbox.files.list(
  "/tmp", // directory path
  {
    depth: 2, // optional: traversal depth, minimum 1
  }
);

console.log(entries.map((entry) => entry.path));

Watch A Directory

const handle = await sandbox.files.watchDir(
  "/tmp/watch", // directory to watch
  (event) => {
    console.log(event.type, event.name);
  }, // callback for file events
  {
    recursive: true, // optional: watch nested directories
    timeoutMs: 30_000, // optional: auto-stop after this many ms
  }
);

await handle.stop();

Create Upload URL

const upload = await sandbox.files.uploadUrl(
  "/tmp/upload.txt", // target path inside the sandbox
  {
    oneTime: true, // optional: invalidate the URL after one use
    expiresInSeconds: 60, // optional: URL lifetime
  }
);

console.log(upload.method, upload.url);

Create Download URL

const download = await sandbox.files.downloadUrl(
  "/tmp/hello.txt", // source path inside the sandbox
  {
    oneTime: true, // optional: invalidate the URL after one use
    expiresInSeconds: 60, // optional: URL lifetime
  }
);

console.log(download.method, download.url);

Terminal

Create A Terminal

Use sandbox.terminal.create(...) or the alias sandbox.pty.create(...).
const terminal = await sandbox.terminal.create({
  command: "bash", // required: command to launch
  args: ["-l"], // optional: command arguments
  cwd: "/tmp", // optional: working directory
  env: { FOO: "bar" }, // optional: environment variables
  rows: 24, // optional: terminal rows
  cols: 80, // optional: terminal columns
  timeoutMs: 60_000, // optional: PTY timeout in milliseconds
});

console.log(terminal.id);

Get A Terminal

const terminal = await sandbox.terminal.get(
  "terminal-id", // terminal ID
  true // optional: include buffered output
);

console.log(terminal.current.output?.length ?? 0);

Snapshots

Create A Memory Snapshot

const snapshot = await sandbox.createMemorySnapshot({
  snapshotName: "node-after-setup", // optional: custom snapshot name
});

console.log(snapshot.snapshotId);
Sandbox guides:

Integration Examples

import { chromium } from "playwright-core";
import { Hyperbrowser } from "@hyperbrowser/sdk";
import { config } from "dotenv";

config();

const client = new Hyperbrowser({
  apiKey: process.env.HYPERBROWSER_API_KEY,
});

async function main() {
  const session = await client.sessions.create({
    acceptCookies: true,
  });

  try {
    const browser = await chromium.connectOverCDP(session.wsEndpoint);
    const defaultContext = browser.contexts()[0];
    const page = defaultContext.pages()[0];

    await page.goto("https://example.com");
    console.log(await page.title());
  } catch (err) {
    console.error(`Encountered error: ${err}`);
  } finally {
    await client.sessions.stop(session.id);
  }
}

main().catch(console.error);

Computer Actions

Programmatically control the browser with low-level actions. For the session-id parameter, you can also just pass in the detailed session object itself, and it is actually recommended to do so.

Click

const response = await client.computerAction.click(
  "session-id",  // or session object
  500,  // x coordinate
  300,  // y coordinate
  "left",  // button: "left" | "right" | "middle" | "back" | "forward" | "wheel"
  1,  // number of clicks
  false  // do not return screenshot (default: false)
);

console.log(response.success);
console.log(response.screenshot);  // base64 if requested

Type Text

const response = await client.computerAction.typeText(
  "session-id",
  "Hello, World!",
  false  // do not return screenshot (default: false)
);

Press Keys

Uses the xdotool format for keys: https://github.com/sickcodes/xdotool-gui/blob/master/key_list.csv
const response = await client.computerAction.pressKeys(
  "session-id",
  ["Control_L", "a"],  // Key combination
  false  // do not return screenshot (default: false)
);

Move Mouse

const response = await client.computerAction.moveMouse(
  "session-id",
  500,  // x
  300,  // y
  false  // do not return screenshot (default: false)
);

Drag

const response = await client.computerAction.drag(
  "session-id",
  [
    { x: 100, y: 100 },
    { x: 200, y: 200 },
    { x: 300, y: 300 },
  ],
  false  // do not return screenshot (default: false)
);

Scroll

const response = await client.computerAction.scroll(
  "session-id",
  500,  // x position
  300,  // y position
  0,  // scroll x delta
  100,  // scroll y delta
  false  // do not return screenshot (default: false)
);

Screenshot

const response = await client.computerAction.screenshot("session-id");
console.log(response.screenshot);  // base64

Support