Model or dataset
browser-use/browser-use-pi avatar
browser-use/browser-use-pi

browser-use-pi: a TypeScript browser agent that writes its own JavaScript

A tiny TypeScript web agent, hill climbed on real browser evals.

321 stars17 forksJavaScriptMIT

At a glance

What is it?
Browser Use Pi puts a persistent V8 REPL between the model and Chrome DevTools Protocol, so the agent programs the browser instead of clicking through a fixed action list. Here is how it installs, what it costs you, and where it stops being the right tool.
Who is it for?
Adopt browser-use-pi if you are building in TypeScript or JavaScript, you want the agent to compose its own helpers rather than pick from a fixed action menu, and you are willing to run it on an isolated machine because the generated code has filesystem and network access.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 9 days ago.
What is it written in?
Mainly JavaScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 16, 2026, and from our analysis. They are not legal advice.

DEEP OPEN-SOURCE ANALYSIS

The problem: browser agents that can only click what you anticipated

Most browser agents expose a fixed vocabulary. The model picks from click, type, scroll and a handful of others, and the harness translates each choice into a DevTools call. That works until a page needs something the vocabulary does not cover: a scroll container that only responds to wheel events, a canvas widget, a date picker that ignores synthetic clicks, or a table that needs to be read in a loop with a filter applied between passes. The agent then fails in a way that looks like a model failure but is really an interface failure.

Browser Use Pi takes the other route. The model writes JavaScript, and that JavaScript runs inside a persistent V8 REPL that holds a live Chrome connection over raw CDP. The README describes the loop as a task flowing from Pi Mono into the REPL and out to Chrome, with the accessibility tree and screenshots flowing back. The pitch is stated plainly: the programmability of Browser Harness, with sessions, saved logins, streaming and typed results, delivered as one SDK.

The audience is developers embedding a browser agent into an existing TypeScript application rather than running a standalone tool. The package exports a Browser and a BrowserUse class, and the example file list (apply-to-job.ts, extract.ts, form.ts, research.ts, qa.ts) reads like the shapes teams actually ship: fill a form, pull structured data out of a page, run a question-answer pass over a site.

How the persistent V8 REPL and raw CDP fit together

The architecture has four moving parts. Pi Mono supplies the model catalog and transports. The V8 REPL is persistent, which matters more than it sounds: helpers the agent defines in one step are still there in the next step, so the agent can build a small library as it works instead of rewriting the same extraction logic on every turn. Raw CDP is the transport to Chrome, with no Puppeteer or Playwright layer in between. The accessibility tree and screenshots are the observation channel back to the model.

Skipping the automation framework is a deliberate trade. You get direct access to protocol domains that higher-level wrappers expose only partially, and you avoid a second abstraction that can silently retry or normalize events. You also inherit the protocol's rough edges: CDP is versioned by Chrome release, and the repository pins devtools-protocol at 0.0.1692173 as a dependency, which tells you the project tracks the protocol surface explicitly rather than treating it as incidental.

The dependency list is short and worth reading as a design statement. Three packages come from @earendil-works (pi-agent-core, pi-ai, pi-coding-agent, all at 0.85.1), plus devtools-protocol and typebox. Typebox at 1.3.7 is the schema layer, which is how typed results are produced: the agent's output is validated against a schema rather than parsed out of free text. The package is type: module and ships only an ESM export with a types entry, so CommonJS consumers need to plan for that.

Installing browser-use-pi and running a first task

The README gives three package manager options. Node 22.19 or newer is required, and Bun 1.3.14 or newer if you use Bun. The README notes that Bun still needs Node present for the V8 worker, so installing Bun does not remove the Node dependency.

bash
npm install @browser_use/pi
# or: pnpm add @browser_use/pi
# or: bun add @browser_use/pi
export OPENROUTER_API_KEY=...
export BROWSER_USE_API_KEY=...

Two environment variables are needed for the cloud path. OPENROUTER_API_KEY authenticates the model call and BROWSER_USE_API_KEY authenticates Browser Use Cloud. The repository also ships a .env.example with four keys: BROWSER_USE_API_KEY, OPENROUTER_API_KEY, MODEL (prefilled with openrouter/openai/gpt-5.6-luna) and BROWSER (prefilled with local), plus DO_NOT_TRACK=1.

The README's first example creates an agent, runs it, and issues a follow-up on the same session before closing. Save it as agent.ts and run it with node agent.ts or bun agent.ts.

ts
import { Browser, BrowserUse } from '@browser_use/pi';

const agent = await BrowserUse.create({
  model: 'openrouter/openai/gpt-5.6-luna',
  reasoning: 'xhigh',
  browser: Browser.cloud({ apiKey: process.env.BROWSER_USE_API_KEY! }),
  workspace: './work',
});

try {
  const result = await agent.run('Find the top story on Hacker News.');
  console.log(result.status, result.text);
  await agent.followUp('Summarize the comments.');
} finally {
  await agent.close();
}

The reader should see the run status and the extracted text printed to the console, then a second round of output from the follow-up. Two details in that snippet are easy to miss. The workspace option is a directory path, and it is what makes sessions persistent across runs. The browser option is Browser.cloud, which the README says means no local Chrome installation is needed; the .env.example's BROWSER=local value points at the other path, where you supply your own Chrome. The docs directory has separate pages for sessions, models, browser primitives, the API, quickstart and benchmarks, and the README links each one rather than inlining them.

Where the design bites: generated code with filesystem access

The README states it without hedging: JavaScript runs in a killable worker with filesystem and network access, and untrusted tasks should run on an isolated machine. That single sentence determines your deployment. If the agent browses pages you do not control, the page content is an input to a system that can write files and make outbound requests. Killable means the worker can be terminated, which bounds runaway execution but does not make the code trustworthy.

The second limitation is observability. When an agent picks from a fixed action list, a failure produces a short log. When an agent writes JavaScript, a failure produces a stack trace, and the person debugging it needs to read generated code and understand what it was trying to do. The README lists streaming, hooks and compaction under Control, and the examples directory mentions interaction highlights, recordings and GIF exports, so there are tools for watching a run. None of that removes the need for someone on the team who can read the trace.

The third is version risk. The package is at 0.1.0, and its three core dependencies are pinned to exact versions (0.85.1) rather than ranges. Pinning buys reproducibility and costs you the ability to absorb upstream fixes without a deliberate bump. There are no releases listed for this repository, so the published package version is the thing to track.

Finally, telemetry is on by default. The README says anonymous run counters are enabled and can be disabled with telemetry: false or DO_NOT_TRACK=1. The .env.example sets DO_NOT_TRACK=1, which is a reasonable default for a template but easy to carry into production without noticing what it does.

browser-use-pi against Playwright-driven agents

The obvious alternative is an agent built on Playwright or Puppeteer, where the model selects from a defined set of actions and the framework handles the automation. The difference is where the flexibility lives. In a Playwright-based agent, the action space is fixed at design time and the model chooses within it; adding a capability means writing a new action and redeploying. In browser-use-pi, the action space is JavaScript, and the agent extends itself at runtime by defining helpers in the REPL.

That shifts the failure mode. A Playwright agent fails predictably, because the set of things it can attempt is bounded and you can enumerate it. A browser-use-pi agent can attempt anything the protocol allows, which means it can also attempt something wrong in a novel way. The persistent REPL makes this sharper: state accumulates across steps, so a bad helper defined early can poison later turns.

Playwright also gives you a mature ecosystem: trace viewer, codegen, a large body of documentation, and a stable API. browser-use-pi gives you direct CDP access and a much smaller dependency tree, at the cost of being early. If your task is a repeated, well-understood flow such as logging in and downloading a report, a Playwright script is the cheaper answer, and an agent on top of it may be unnecessary altogether. The programmability argument only pays off when the task varies enough that you cannot enumerate the steps in advance.

Maintenance cost, licence and what to check before upgrading

The last push to this repository was on 2026-09-09, eight days before this writing, and the repository is not archived. The commit activity is recent, but there are no releases, so there is no changelog to read before an upgrade. You are tracking the main branch and the published package version, and the package is at 0.1.0.

The upgrade surface is narrow but sharp. Three dependencies are pinned to 0.85.1 and devtools-protocol to 0.0.1692173. A bump to any of them can change agent behaviour without changing the API you call. The test script builds first and then runs node's test runner with concurrency set to 1, which suggests the tests are not safe to run in parallel; the package also defines a separate test:bun script that sets DO_NOT_TRACK=1 and runs a named subset of test files with a 60000 ms timeout. If you vendor this, run npm test and npm run check against your own code before upgrading, and expect the check script (tsc --noEmit) to be the fastest signal.

The licence is MIT, which permits commercial use, modification and redistribution provided the copyright notice and licence text are retained. That is a permissive licence, but it does not address the terms of the model provider or Browser Use Cloud, which are separate agreements you enter when you set OPENROUTER_API_KEY and BROWSER_USE_API_KEY. Nothing in the repository substitutes for reading those.

Editorial conclusion

Adopt browser-use-pi if you are building in TypeScript or JavaScript, you want the agent to compose its own helpers rather than pick from a fixed action menu, and you are willing to run it on an isolated machine because the generated code has filesystem and network access. Do not adopt it if you need a stable 1.x API surface, if your team cannot read JavaScript traces when a run goes wrong, or if Python is a hard requirement, since the package is published at version 0.1.0 and the Python path only appears as a separate directory and test script. Before you commit, verify two things against the docs: whether your model and provider combination is actually reachable through the upstream Pi catalog, and whether the cloud browser path or a local Chrome instance fits your deployment, because the README shows both and they have different setup costs.

Frequently asked questions

What is the Pi Browser used for?

It is the browser control layer for a TypeScript agent: the model writes JavaScript into a persistent V8 REPL that talks to Chrome over raw CDP, and the accessibility tree plus screenshots come back as observations. The README frames the goal as the programmability of Browser Harness with sessions, saved logins, streaming and typed results in one SDK.

Is browseruse safe?

The README states that JavaScript runs in a killable worker with filesystem and network access, and that untrusted tasks should use an isolated machine. It also says anonymous run counters are on by default and can be turned off with telemetry: false or DO_NOT_TRACK=1.

How do I install Browser-Use using pip?

The README installs the TypeScript package with npm, pnpm or bun, not pip. The repository does contain a python/ directory and a test:python script that builds a Python package and runs python/tests with unittest, but the README does not document a pip install command for it.

How to use browser use?

Create an agent with BrowserUse.create, passing a model, a browser (Browser.cloud with an API key, or a local Chrome), and a workspace directory, then call agent.run with a task and agent.close when finished. The README's example runs a task, prints result.status and result.text, then calls agent.followUp for a second turn on the same session.

Official sources

  1. browser-use/browser-use-pi on GitHub
  2. Issues
  3. License: MIT
  4. Project website
  5. README
Community notes

Community notes