browsa
v0.2.0
Published
Official TypeScript SDK for Browsa — anti-detect cloud browsers for AI agents (browsa.io)
Maintainers
Readme
browsa (TypeScript)
Anti-detect browsers for AI agents — official TypeScript/JavaScript SDK for browsa.io.
Install
npm install browsa
# or pnpm add browsa / yarn add browsa / bun add browsaZero deps. Pure Node 18+ fetch. Single ESM+CJS bundle. Audit-friendly.
Five-line hello world
import { Client } from "browsa";
const c = new Client({ apiKey: "agt_live_..." });
const job = await c.runTask({
task: "Go to news.ycombinator.com and return the top story title.",
llm: "claude-opus-4-7",
llmApiKey: "sk-ant-...",
});
console.log(job.finalResult);
console.log("watch live:", job.liveUrl);That runs a real Chromium fork (Phantom — our anti-detect browser) inside an isolated burner session, driven by browser-use + Claude Opus. The agent navigates, extracts, and returns. A live noVNC stream URL is available the moment the burner spawns.
Webhooks
import { verifySignature } from "browsa/webhooks";
import express from "express";
const app = express();
app.post("/webhook",
express.raw({ type: "application/json" }), // raw body!
(req, res) => {
const sig = req.header("X-Agents-Signature") || "";
if (!verifySignature(req.body, sig, process.env.BROWSA_WEBHOOK_SECRET!)) {
return res.status(401).json({ error: "bad signature" });
}
const payload = JSON.parse(req.body.toString("utf-8"));
// trust payload from here
res.sendStatus(200);
});What you get
| Capability | Notes |
|---|---|
| Typed Job + Webhook | Full TypeScript types, with .raw escape hatch |
| Long-poll waits | waitForJob({ timeoutMs }) uses server-side ?wait=30 |
| Webhook signature verify | HMAC-SHA256, constant-time compare, skew check |
| Canonical error envelope | AuthError, InvalidIDError, RateLimitError, etc. |
| X-Request-Id propagation | Every error carries requestId |
| Zero deps | Audit-friendly, no transitive surface |
| ESM + CJS | Works in any Node 18+ runtime, edge runtimes welcome |
Advanced
Progress callbacks for long-running tasks
const job = await c.runTask({
task: "...",
llm: "claude-opus-4-7",
llmApiKey: "sk-ant-...",
maxSteps: 80,
onProgress: (j) => console.log(`step ${j.stepCount}/${j.progressTotal}`),
});Interactive (input_required) tasks
let job = await c.createTask({ task: "...", llm: "...", llmApiKey: "..." });
while (!["completed", "failed", "cancelled"].includes(job.status)) {
job = await c.getJob(job.id, { wait: 30 });
if (job.status === "input_required") {
const answer = await prompt(`Agent asks: ${job.inputQuestion}\n> `);
job = await c.respondToJob(job.id, answer);
}
}JA3-spoofed sessions (TLS fingerprint)
await c.runTask({
task: "Hit a TLS-fingerprinted site",
llm: "claude-opus-4-7", llmApiKey: "sk-...",
ja3Profile: "macos_chrome_137",
});Docs
- API reference: https://browsa.io/docs
- Source: https://github.com/mohasaaid/neout/tree/main/sdks/browsa-ts
- Issues: https://github.com/mohasaaid/neout/issues
License
MIT.
