NewThe browserless browser

The universal MCP for everything.

Permissionless connectors to any application — even the ones without an API.

01 · The page

Websites are built for eyes.

Buttons, layout, pixels. Agents today drive them in a browser: launch Chromium, click, wait, read eight thousand tokens of HTML — then do it again tomorrow.

02 · The network

Underneath, every page already calls an API.

Unbrowse watches the site's own first-party requests — the JSON the page fetches for itself — and keeps the ones that answer the task.

03 · The compile

Compiled into one tool.

Typed inputs, a verified answer, replayed over plain HTTP in 50–200 ms. No browser window. Your agent calls it like any other tool.

04 · The registry

Every site. One MCP.

3,292 tools already compiled from the top 10,000 websites, re-verified in the background. Anything missing is learned the first time your agent asks.

Get started freeConnect your agent

Give this to your agent

One line. Every site.

npx skills add unbrowse-ai/unbrowse && npx unbrowse login

Adds the Unbrowse skill to your agent and signs in the CLI. Then npx unbrowse run 'top stories on hacker news' runs any site from your terminal, with the site requests sent from your own IP; add --from-unbrowse to send them from Unbrowse instead.

The wedge

Agents should not browse websites. They should call the APIs already behind them.

Unbrowse is an authenticated action surface. Agents ask for an outcome. We hit the site's own first-party APIs when they exist, keep a cloud browser when they don't, and compile the route into a versioned harness your next call can reuse.

Humans

A page

Buttons, type, layout. Beautiful for people. Slow to operate by hand, and not a contract.

Agents today

A DOM

Launch Chromium, wait, click, dump eight thousand tokens of HTML, hope the layout did not ship overnight.

Unbrowse

A route

The first-party JSON the page was already calling. Typed. Cached. Permission-aware. Verified.

a warmed first-party call
5–30s → 50–200msa warmed first-party call
tokens, DOM vs JSON
~8,000 → ~200tokens, DOM vs JSON
mean / median vs Playwright, 94 domains
3.6× / 5.4×mean / median vs Playwright, 94 domains
on a compiled route
0 windowson a compiled route

Speedups from the 94-domain benchmark in “Internal APIs Are All You Need” (arXiv:2604.00694).

3,292 tools in the public registry, from a crawl of the top 10,000 websites: 337 site searches and flows, and page reading for 2,955 sites. Anything missing is learned on first use.

  • github.com
  • amazon.com
  • youtube.com
  • zillow.com
  • arxiv.org
  • bbc.com
  • docs.rs
  • mongodb.com
  • dev.to
  • primevideo.com
  • curl.se
  • bleepingcomputer.com
  • lidl.de
  • esquire.com
  • justdial.com
  • mercadolibre.com.co
  • depositphotos.com
  • kpmg.com
  • att.com
  • bluehost.com

Browse the registry (JSON) →

Runtime

Search. Resolve. Execute. Learn in the background.

  1. 01 · discover

    Find the route

    Your agent says what it wants, in plain words or by capability id. Unbrowse ranks what can answer it: its built-in routes, your own compiled tools, then the public registry.

    discover
    tools/list({ query: "top stories on Hacker News" })
    → hn.top_stories   first_party_http
      GET hn.algolia.com/api/v1/search
  2. 02 · run

    Call the site's own API

    The same request the website makes for itself, replayed over HTTP — no browser window — and the answer is verified before it counts.

    run
    unbrowse.run({ task: "singapore to korea tomorrow" })
    → skyscanner.flights · succeeded
      { itineraries: [ { price, legs, carrier } … ] }
  3. 03 · browse → finish

    Learn anything missing

    No route yet? Your agent does the task once in a cloud browser. Unbrowse watches the site's own traffic and compiles it into a tool that replays without a browser from then on.

    browse → finish
    browse.open({ url: "eatigo.com/sg" }) … browse.finish()
    → learned.eatigo_com.get_7_b2_7_d_search
      parameters: start, sortby, filter_regionid

Metered

Pay for answers, not attempts.

A call counts only when it returns verified data. Failed, blocked and refused calls are free.

verified calls a month, free
500verified calls a month, free
free now · book a call to extend your calls
Betafree now · book a call to extend your calls
for failed, blocked and refused calls
$0for failed, blocked and refused calls
tools in the public registry
3,292tools in the public registry
usage — only verified answers count
# a verified answer
POST /api/v1/runs { capability, input }
200 { status: "succeeded", result }
billed: 1 credit ($0.001)

# a blocked one
POST /api/v1/runs { capability, input }
200 { status: "failed" }
billed: nothing

Start free — 500 calls a monthSee pricing

Identity

Your agent signs in. It never sees the password.

Passwords live in the Unbrowse vault, never in tool arguments or harnesses. Save a login once, or import your browser's CSV. Unbrowse types it into the site's own form, keeps the signed-in session sealed, and signs in again only when the site asks. The model only ever sees a masked hint.

password manager · example

  • github.comoc•••at2FA
  • mail.example.comad•••@ex•••.com
  • bank.examplead•••ce2FA
what the agent sees
browse.act({ action: "autofill" })
→ filled: ["username", "password", "totp"]
  snapshot: { role: "textbox", value: "[from vault]" }

credentials.list()
→ { origin: "https://github.com", hints: { username: "oc•••at" } }

Output

Every site becomes an MCP server and an OpenAPI document.

What Unbrowse compiles is yours to wire anywhere: typed tools with input and output schemas, a per-site MCP server, and an OpenAPI 3.1 document. These are live responses from unbrowse.ai.

POST /api/v1/sites/docs.rs/mcp tools/list
tools: [
  { name: "docs_rs__get_search",
    inputSchema: { query: string } },
  { name: "docs_rs__read_page",
    inputSchema: { path: string } },
  run_task, browse_open, browse_snapshot, …
]
GET /api/v1/sites/docs.rs/openapi.json
openapi: 3.1.0
paths:
  /api/v1/sites/docs.rs/call/docs_rs__get_search:
    post:
      requestBody: { query: string }   # required
      responses:
        200: { runId, status, capabilityId,
               result: { title, text, links[] } }

arXiv:2604.00694

Internal APIs are all you need.

Why the first-party routes already powering modern websites are the machine-native interface for agents, and how a shared route graph turns repeated browser rediscovery into collective memory.

Read the paper
production domains in the benchmark
94production domains in the benchmark
cost reduction on warmed-cache execution
90–96%cost reduction on warmed-cache execution
local cache, shared graph, browser fallback
3 pathslocal cache, shared graph, browser fallback

Limits, stated

Explicit, not magic.

Is this a headless browser?

No. Unbrowse is the browserless browser: an authenticated action surface. It prefers the site's own first-party APIs. A cloud browser is kept only for discovery and for sessions that still need a page.

Do I need an API key for each website?

No. Unbrowse calls each site the way the site calls itself, so there is nothing to sign up for per site. One Unbrowse connection — MCP, the Skill or REST — reaches all of them. Official integrations are used when configured; their absence doesn't block a task.

Where do passwords live?

In the Unbrowse vault, never in tool arguments or harnesses. Agents get opaque references and masked hints; the value is typed into the site's own form, and the signed-in session is kept sealed.

When is a task succeeded?

Only when the declared outcome is independently verified. An HTTP 200, a compiled file, or a model's confidence is not enough — and only verified answers are billed.

How is it priced?

Unbrowse is in beta and free: 500 verified calls a month, and if you need more, book a call and we'll extend it. After the beta: $10 per 10,000 verified calls. Failures are always free.

Is what I teach shared?

Read-only routes on public sites are shared to the registry, scrubbed of anything personal, so everyone's agents get faster — you can turn that off. Logins, and anything that changes a site, are never shared.

Drop it in as your agent's browser. The first ask is already a route.

500 free calls a month. No card.

Get started freeConnect your agent