AI agents

Agents need a browser that behaves like the web actually behaves: JavaScript, logins, redirects, and pages that only render on a real engine. BrowserGen gives each agent task a disposable Chromium it can drive with the tooling you already use, plus a live view for the human in the loop.

Skip the glue code with MCP. If your agent runs in an MCP client (Claude Code, Cursor, Codex, ...), the hosted BrowserGen MCP server exposes these browsers as ready-made tools; this page covers wiring sessions up yourself.

The session-per-task pattern

Treat sessions like processes: create one when a task starts, end it when the task ends. Isolation comes free (fresh browser, no shared cookies between tasks) and a crashed task never poisons the next one.

browser-tool.ts
import { chromium, type Browser } from "playwright";

// One session per agent task: isolated state, isolated failure domain.
export async function withBrowser<T>(run: (browser: Browser) => Promise<T>) {
  const session = await fetch("https://api.browsergen.com/v8/web/sessions", {
    method: "POST",
    headers: {
      Authorization: `Bearer ${process.env.BROWSERGEN_KEY}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({ timeout: 900 }),
  }).then((r) => r.json());

  console.log("Watch this run live:", session.liveViewUrl);

  const browser = await chromium.connectOverCDP(session.connectUrl);
  try {
    return await run(browser);
  } finally {
    await browser.close();
    // Free the slot immediately instead of waiting out the grace period.
    await fetch(`https://api.browsergen.com/v8/web/sessions/${session.id}`, {
      method: "DELETE",
      headers: { Authorization: `Bearer ${process.env.BROWSERGEN_KEY}` },
    });
  }
}
Log the live-view URL. Surfacing liveViewUrl in your agent traces turns every browser step into something a human can open and watch, mid-run or after the fact while the session is alive.

Exposing the browser as a tool

Most agent frameworks share the same shape: a named tool with a schema and an async handler. Wrap your browser actions in tools and keep the session handling inside the helper:

tools.ts
// LangChain-style tool wrapping a BrowserGen-backed browser action.
import { tool } from "@langchain/core/tools";
import { z } from "zod";

const readPage = tool(
  async ({ url }) =>
    withBrowser(async (browser) => {
      const page = browser.contexts()[0].pages()[0];
      await page.goto(url, { waitUntil: "domcontentloaded" });
      return await page.innerText("body");
    }),
  {
    name: "read_page",
    description: "Open a URL in a real browser and return its visible text.",
    schema: z.object({ url: z.string().describe("The page to open") }),
  },
);

The same pattern maps to any framework with function/tool calling: define the action, run it inside withBrowser, and return text the model can reason over.

Practical guidance

  • Set tight timeouts. Agent steps are short; a timeout of 300 to 900 seconds keeps runaway loops from holding concurrency.
  • Use geo targeting for localized tasks. Price checks, availability checks and consent walls often depend on the exit country; pass country at creation.
  • Escalate to a human via the live view. When the agent detects a captcha or an unexpected login, pause and hand the live-view URL to a person: they solve it in the browser, the agent continues in the same session.
  • Watch your quota. GET /web/usage reports used and available slots so a scheduler can queue tasks instead of hitting denials.

Related