Quick verdict: If self-hosting and a mature “browser platform” with a long track record matters most, Browserless is hard to beat. If your priority is stealth by default, privacy by architecture (zero logs), and simpler integration surfaces (Request API + MCP + Playwright), browser.city is the cleaner foundation.
Browserless and browser.city solve different “pain centers”
Browserless is historically the “reliable hosted browser” option. It’s also one of the few vendors that treats self-hosting as a first-class path.
browser.city is built around a different set of constraints:
- stealth is not an add-on
- the system is designed to not retain session content (zero-logs posture)
- you get multiple product “shapes” for different workloads (Request API vs long-running sessions vs Humanized REST actions vs agent tools)
At a glance
| Dimension | browser.city | Browserless |
|---|---|---|
| Billing model | Simple usage model | “Units” model (often time-sliced) |
| Stealth | Default | Strong baseline; verify stealth behavior per plan |
| Best integration path | Request API + Playwright + MCP | Playwright/Puppeteer + Browserless-specific platform features |
| Self-hosting | Not the default story | Core differentiator |
| Best for | Production scraping/automation with stealth + privacy constraints | Teams that need hosted browsers with a self-hosting escape hatch |
The biggest practical difference: units vs minutes vs “head math”
If your workload has variable session lengths, billing models impact behavior:
- Unit/time-slice billing is easy to understand at small scale, but can create unexpected cliffs with retries, dynamic pages, and long sessions.
- A simple per-minute or per-session model tends to map more directly to what engineers see in logs.
If you’re comparing costs, do it with real traces:
- median session runtime
- retries per successful job
- proxy bandwidth usage
- concurrency spikes
API surface: infrastructure primitives vs platform features
browser.city focuses on primitives:
- Request API for “give me markdown for this URL”
- Sessions API for long-running Playwright automation
- Humanized REST tools (
/v1/do/*) for click/type/markdown over HTTP (no Playwright runtime) - MCP server for coding agents and frameworks
Example: pull markdown in one call (no Playwright code required):
const apiKey = process.env.BROWSERCITY_API_KEY!;const opts = { method: "POST", headers: { Authorization: `Bearer ${apiKey}` } };const res = await fetch("https://api.browser.city/v1/requests", { ...opts, body: JSON.stringify({ url: "https://example.com", markdown: true }),}).then((r) => r.json());console.log(res.content);import osimport requestsapi_key = os.environ["BROWSERCITY_API_KEY"]res = requests.post( "https://api.browser.city/v1/requests", headers={"Authorization": f"Bearer {api_key}"}, json={"url": "https://example.com", "markdown": True},).json()print(res["content"])using System.Net.Http.Headers;using System.Net.Http.Json;var apiKey = Environment.GetEnvironmentVariable("BROWSERCITY_API_KEY")!;var http = new HttpClient();http.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", apiKey);var res = await http.PostAsJsonAsync( "https://api.browser.city/v1/requests", new { url = "https://example.com", markdown = true });Console.WriteLine(await res.Content.ReadAsStringAsync());import java.net.URI;import java.net.http.*;var apiKey = System.getenv("BROWSERCITY_API_KEY");var http = HttpClient.newHttpClient();var body = "{\"url\":\"https://example.com\",\"markdown\":true}";var req = HttpRequest.newBuilder() .uri(URI.create("https://api.browser.city/v1/requests")) .header("Authorization", "Bearer " + apiKey) .POST(HttpRequest.BodyPublishers.ofString(body)) .build();var res = http.send(req, HttpResponse.BodyHandlers.ofString());System.out.println(res.body());
Browserless excels when you want a broader browser platform, including optional query languages and platform-specific capabilities. If those are central to your stack, migrating may not be worth it.
When to pick which
Choose Browserless if:
- you want self-hosting as a real option (for compliance, cost, or control)
- you prefer a mature platform with many knobs and operational history
- your workloads don’t depend on cutting-edge stealth by default
Choose browser.city if:
- you want stealth enabled by default without upgrading tiers
- you care about a zero-logs architecture for sensitive automation
- you want to unify workflows: extraction (Request API), automation (Playwright sessions), and agents (MCP tools)
Migration notes (Browserless → browser.city)
Most teams migrate a subset first:
- Move “content extraction” jobs to
POST /v1/requestsor/v1/requests/batch. - Move long-running flows by switching session provisioning to
POST /v1/sessionsand keeping Playwright code unchanged. - If you have self-hosting in the mix, keep it for the workloads that truly require it and use browser.city for stealth-heavy targets.