Quick verdict: If you want a polished AI-native platform and don’t mind tiered stealth features and “browser-hours” pricing, Browserbase is a strong incumbent. If you want stealth enabled by default, zero-logs by design, and an API surface that stays simple as you scale (Playwright + Request API + Humanized REST + MCP), browser.city is built for that.
What you’re actually choosing
Both products live in the same category: managed, remote browsers you control via APIs (Playwright/CDP style flows).
The difference is in the defaults:
- Browserbase optimizes for an AI-native product ecosystem and polished onboarding.
- browser.city optimizes for infrastructure ergonomics: stealth and privacy as a baseline, and fewer “gotchas” in cost and integration.
At a glance
| Dimension | browser.city | Browserbase |
|---|---|---|
| Stealth | On by default | Stealth features often tiered by plan |
| Pricing model | Clear (simple usage model) | Browser-hours plans + tiering |
| API modes | Playwright sessions, Request API, MCP, Humanized REST tools | Primarily Playwright/CDP-style workflows + SDKs |
| Privacy posture | Zero-logs architecture | Varies by platform (verify against their docs/security pages) |
| Best for | Teams that want predictable infra primitives | Teams that want an AI-native “platform” experience |
Stealth: defaults vs tiers
If your workload hits bot mitigation (Cloudflare / DataDome / PerimeterX / Kasada), the question isn’t “do you have stealth?” but:
- Is it enabled by default?
- Is it consistent across tiers and environments?
- Can you control fingerprint + egress without a matrix of add-ons?
browser.city’s posture is simple: stealth is on. You can still tune sessions (fingerprints, storage state, managed egress, BYOP), but the baseline is designed to work on hostile surfaces.
Pricing: what’s easy to estimate wins
When teams migrate off competitors, the most common reason is not performance, it’s billing complexity:
- credits vs units vs multipliers
- stealth priced as an “upgrade”
- proxy bandwidth billed separately with unclear ratios
Browserbase pricing is generally expressed in browser-hours with tiered plans. That can be totally fine, but you’ll want to model:
- expected concurrency
- long-running sessions
- proxy/bandwidth costs (if separate)
browser.city aims for “you can calculate it in your head” pricing and exposes a Request API for workloads that don’t need full browser orchestration.
API surface: four ways to ship
browser.city intentionally supports four “entry points,” depending on how agentic you need to be:
- Request API: fetch a URL and return clean markdown (fastest path to data pipelines).
- Sessions API: create a session and connect using Playwright.
- Humanized REST tools (
/v1/do/*): click/type/markdown over HTTP without running Playwright. - MCP server: give tools to coding agents and AI frameworks without writing glue.
Example: create a session and connect with Playwright:
import { chromium } from 'playwright';const { endpoint, token, id } = await fetch('https://api.browser.city/v1/sessions', { method: 'POST', headers: { Authorization: `Bearer ${process.env.BROWSERCITY_API_KEY}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ browser: 'chromium' }),}).then((r) => r.json());try { const browser = await chromium.connect(endpoint, { headers: { Authorization: `Bearer ${token}` }, }); const page = browser.contexts().at(0)!.pages().at(0)!; await page.goto('https://example.com'); console.log(await page.title());} finally { await fetch(`https://api.browser.city/v1/sessions/${id}`, { method: 'DELETE', headers: { Authorization: `Bearer ${process.env.BROWSERCITY_API_KEY}` }, });}using Microsoft.Playwright;using System.Net.Http.Headers;using System.Net.Http.Json;var http = new HttpClient();http.DefaultRequestHeaders.Authorization = new( "Bearer", Environment.GetEnvironmentVariable("BROWSERCITY_API_KEY"));var session = await (await http.PostAsJsonAsync( "https://api.browser.city/v1/sessions", new { browser = "chromium" })) .Content.ReadFromJsonAsync<Session>();var (id, endpoint, token) = session!;IPlaywright? pw = null;try { pw = await Playwright.CreateAsync(); var browser = await pw.Chromium.ConnectAsync(endpoint, new() { Headers = new() { ["Authorization"] = $"Bearer {token}" } }); var page = browser.Contexts[0].Pages[0]; await page.GotoAsync("https://example.com");} finally { try { if (session is not null) await http.DeleteAsync($"https://api.browser.city/v1/sessions/{id}"); } finally { pw?.Dispose(); }}record Session(string Id, string Endpoint, string Token);import com.fasterxml.jackson.databind.ObjectMapper;import com.microsoft.playwright.*;import java.net.URI;import java.net.http.*;import java.util.Map;public class Session { public static void main(String[] args) throws Exception { var key = System.getenv("BROWSERCITY_API_KEY"); var http = HttpClient.newHttpClient(); var req = HttpRequest.newBuilder(URI.create("https://api.browser.city/v1/sessions")) .header("Authorization", "Bearer %s".formatted(key)) .header("Content-Type", "application/json") .POST(HttpRequest.BodyPublishers.ofString("{\"browser\":\"chromium\"}")) .build(); var created = new ObjectMapper().readValue( http.send(req, HttpResponse.BodyHandlers.ofString()).body(), CreatedSession.class); var id = created.id(); var endpoint = created.endpoint(); var token = created.token(); Playwright pw = null; try { pw = Playwright.create(); var browser = pw.chromium().connect(endpoint, new BrowserType.ConnectOptions().setHeaders(Map.of("Authorization", "Bearer %s".formatted(token)))); var page = browser.contexts().get(0).pages().get(0); page.navigate("https://example.com"); } finally { try { http.send(HttpRequest.newBuilder(URI.create("https://api.browser.city/v1/sessions/" + id)) .header("Authorization", "Bearer %s".formatted(key)).DELETE().build(), HttpResponse.BodyHandlers.discarding()); } finally { if (pw != null) pw.close(); } } } record CreatedSession(String id, String endpoint, String token) {}}
When to pick which
Choose Browserbase if:
- you want an AI-first product suite and polished platform UX
- you’re already invested in their SDK ecosystem
- you’re OK with stealth/compliance features being plan-gated
Choose browser.city if:
- you want stealth by default with fewer configuration “traps”
- you care about a zero-logs posture as an architectural constraint
- you want multiple integration styles (Request API, Playwright sessions, Humanized REST, MCP tools) without switching products
Migration notes (Browserbase → browser.city)
Most migrations are mechanical:
- Swap session creation to
POST /v1/sessions - Keep your Playwright code, but connect using the returned
endpointandtokenheader - For “fetch + extract” flows, replace agent loops with
POST /v1/requestsorPOST /v1/requests/batch
If you want help mapping your current flows (sessions, egress, and fingerprint strategy), start with the Integrations hub and pick your toolchain.