Browserbase
A cloud browser is a proxy problem in disguise: it launches from someone else's datacenter, on someone else's IPv4 pool, and every site it touches sees a shared, anonymous exit.
No identity, no accountability, nothing to hand a downstream API that expects a stable address; bot-detection flags the pool on sight, and when something goes wrong there's no address to point at. Point Browserbase's external-proxy option at Whisper instead and the browser leaves from your agent's own routable, DNSSEC-signed, RDAP-documented IPv6 /128 — the same identity it uses everywhere else, provable by anyone with dig -x and no key.
This page is the BYOP (Bring-Your-Own-Proxy) recipe: how Browserbase's proxies field maps onto the Whisper egress, the exact wire mechanics, and a runnable two-tier example.
Why this is worth doing
- Real IPv6, not a shared IPv4 pool. Browserbase's own egress is IPv4-only. Routing a session through Whisper is the only way to give a Browserbase browser a routable IPv6 identity at all.
- The address is independently verifiable. Anyone — not just you — can run
dig -xor an RDAP lookup against the IP a page saw and get back a real, signed answer: this is a Whisper agent, here's its identity record. Compare that to a rotating proxy-pool IP, which resolves to nothing. - No infrastructure to run. No VPN box, no sidecar, no proxy fleet to keep alive. The egress is a standing Whisper service; you supply a bearer credential, Browserbase does the rest.
- Keyless half works today, for anyone. You don't need a Whisper account to check whether a given IP is a Whisper agent — that's public infrastructure, covered below.
The mechanism: BYOP is just HTTP CONNECT with Basic auth
Browserbase's sessions.create accepts a proxies array. For an external proxy, Browserbase's browser issues an HTTP CONNECT to your server for every outbound TCP stream and authenticates with a Proxy-Authorization: Basic <base64(username:password)> header — RFC 7617 Basic auth, carried over the RFC 9110 §9.3.6 CONNECT method. That's it — no proprietary SDK on the wire, just a standard forward-proxy handshake:
CONNECT v6.ident.me:443 HTTP/1.1
Host: v6.ident.me:443
Proxy-Authorization: Basic dzp3aGlzcGVyX2VncmVzc19iZWFyZXI...
Whisper's egress tier (connect.whisper.online:443) speaks exactly this: username w, password = the agent's egress bearer (issued at register/connect time), and it source-binds every accepted stream to the agent's /128 via IP_FREEBIND + AnyIP over 2a04:2a01::/32 before it ever touches the target. Browserbase validates the proxy at sessions.create, not mid-run — a bad bearer fails immediately with a clear error, not a silent hang three requests in.
const session = await bb.sessions.create({
projectId,
proxies: [{
type: "external",
server: "http://connect.whisper.online:443",
username: "w",
password: process.env.WHISPER_PROXY_PASS, // the agent's egress bearer
}],
});
const browser = await chromium.connectOverCDP(session.connectUrl);
External proxies on Browserbase are a paid-plan feature — on the free tier, sessions.create with a non-empty proxies array returns 402 Payment Required. This is a Browserbase account gate, not a Whisper one: the keyless verify tier below works on any Browserbase plan, or with no Browserbase account at all.
With stock tools
Everything Whisper emits here is a standard record — you can drive the whole loop with dig, curl, and openssl, no Whisper software involved.
Prove the demo agent's address is a real, delegated, DNSSEC-signed identity:
# Forward: name -> address, DNSSEC-validated
dig +dnssec AAAA acef2002a323d40d4.demo.agents.whisper.online
# Reverse: address -> name (the PTR Whisper synthesizes for every /128 it allocates)
dig -x 2a04:2a01:eb5a:ca74:cef2:2a:323d:40d4
# RDAP: the IP-anchored assignment document (RFC 7482/9083) — who holds this /128, since when
curl -s https://rdap.whisper.online/ip/2a04:2a01:eb5a:ca74:cef2:2a:323d:40d4 | jq .
Confirm the TLS identity presented on that address is bound to it (DANE, RFC 6698):
kdig +short TLSA _443._tcp.acef2002a323d40d4.demo.agents.whisper.online
# 3 1 1 b653a4ef...fcb82d1d
openssl s_client -connect '[2a04:2a01:eb5a:ca74:cef2:2a:323d:40d4]:443' \
-servername acef2002a323d40d4.demo.agents.whisper.online < /dev/null 2>/dev/null \
| openssl x509 -noout -pubkey \
| openssl pkey -pubin -outform der | openssl sha256
# compare the hash against the TLSA record above
Drive Browserbase's proxy manually — no Whisper SDK, plain curl through the CONNECT tunnel to sanity-check the credential before wiring it into Playwright:
curl -v -x http://w:$WHISPER_PROXY_PASS@connect.whisper.online:443 \
https://v6.ident.me/
# -> the agent's own /128, printed back by the echo service
With Whisper
The whisper-examples/browserbase recipe wraps exactly this into a two-tier script — whisper-edge for the keyless half, the Browserbase JS SDK + Playwright for the keyed half.
Tier 1 — keyless verify (no key, no Browserbase account needed):
node index.mjs verify 2a04:2a01:eb5a:ca74:cef2:2a:323d:40d4
# { "address": "2a04:2a01:...", "is_whisper_agent": true, "rdap": { ... } }
Tier 2 — keyed egress (needs a Browserbase key + a provisioned agent):
# provision an agent + egress credential, if you don't have one yet
whisper create my-browser-agent
# -> address: 2a04:2a01:eb5a:ca74:cef2:2a:323d:40d4
# -> egress bearer printed once; store it, never log it
export BROWSERBASE_API_KEY=bb_...
export BROWSERBASE_PROJECT_ID=...
export WHISPER_PROXY_PASS=... # the egress bearer from `whisper create`
export WHISPER_AGENT_128=2a04:2a01:eb5a:ca74:cef2:2a:323d:40d4
node index.mjs
# { "tier": "egress", "session": "...", "seen_ip": "2a04:2a01:...",
# "is_whisper_agent": true, "expected": "2a04:2a01:...", "matches_agent_address": true }
Same provisioning call, over the control plane directly:
CALL whisper.agents({op:'register', args:{label:'my-browser-agent'}})
CALL whisper.agents({op:'connect', args:{agent:'my-browser-agent', tier:'socks5'}})
-> { http_proxy, connection_string, dns, doh_url }
http_proxy is exactly the server/username/password triple Browserbase's proxies array expects — copy it in directly. The example script closes the loop itself: after the browser loads the IPv6 echo page, it calls verify(seen_ip) from whisper-edge and asserts the observed address is both a real Whisper agent and the specific /128 you expected — proving, end to end, that the cloud browser's traffic left from your agent's identity, not a shared pool.
Where this fits
Browserbase is one BYOP consumer of the same egress tier that backs every Whisper connect path — see Connect for the full tier ladder (routed WireGuard, SOCKS5/HTTP egress, DoH-only). If you'd rather not hold an egress bearer in your automation at all, the forward gateway offers a single stateless fetch-style endpoint that sources from your agent's /128 without a persistent proxy connection — a good fit for one-shot page fetches instead of a full interactive browser session.
Next
Continue with Connect for the full egress tier reference, or The forward gateway for a proxy-less alternative.