Start Tiny (Hobbyists)
One request to extract markdown. Great for price alerts, personal research, and weekend projects.
Stop managing browser instances and proxy networks. BrowserCity provides a stealth-first browser backend designed for scale, with multiple integration styles to fit any stack.
One request to extract markdown. Great for price alerts, personal research, and weekend projects.
Humanized REST tools let you open, navigate, click, type, and screenshot over HTTP. No Playwright infra needed.
If you already run Playwright, connect to remote sessions for deterministic workflows and deep debugging.
Zero-logs posture, BYOP, labels, and sane defaults for running stealth browser workloads inside real orgs.
Fingerprints, proxies, and anti-bot defenses are handled for you. You ship outcomes, not browser plumbing.
Expose the same primitives as discoverable tools for Codex, Claude Code, Cursor, and other MCP clients.
If you want interactive steps but don’t want to run Playwright, Humanized REST tools give you a clean HTTP surface over remote sessions.
const actionUrl = (action: string) => `https://api.browser.city/v1/do/${action}`;const doAction = (action: string, body: unknown) => fetch(actionUrl(action), { method: 'POST', headers: { Authorization: `Bearer ${process.env.BROWSERCITY_API_KEY}`, 'Content-Type': 'application/json' }, body: JSON.stringify(body), }).then((r) => r.json());const opened = await doAction('open', { browser: 'chromium', egress: { mode: 'managed', proxyType: 'residential', country: 'US' } });try { await doAction('navigate', { sessionId: opened.sessionId, url: 'https://example.com' }); const page = await doAction('markdown', { sessionId: opened.sessionId }); console.log(page.result);} finally { await doAction('close', { sessionId: opened.sessionId });}import os, requestsAPI_BASE = 'https://api.browser.city/v1/do'def do_action(action, body): return requests.post( f'{API_BASE}/{action}', headers={'Authorization': f"Bearer {os.environ['BROWSERCITY_API_KEY']}"}, json=body, ).json()opened = do_action('open', {'browser': 'chromium', 'egress': {'mode': 'managed', 'proxyType': 'residential', 'country': 'US'}})try: do_action('navigate', {'sessionId': opened['sessionId'], 'url': 'https://example.com'}) page = do_action('markdown', {'sessionId': opened['sessionId']}) print(page.get('result'))finally: do_action('close', {'sessionId': opened['sessionId']})using System.Net.Http.Headers;using System.Net.Http.Json;using System.Text.Json.Nodes;var http = new HttpClient();var apiBase = new Uri("https://api.browser.city/v1/do/");http.DefaultRequestHeaders.Authorization = new( "Bearer", Environment.GetEnvironmentVariable("BROWSERCITY_API_KEY"));async Task<JsonNode?> Do(string action, object body) => await (await http.PostAsJsonAsync( new Uri(apiBase, action), body)).Content.ReadFromJsonAsync<JsonNode>();var opened = await Do("open", new { browser = "chromium", egress = new { mode = "managed", proxyType = "residential", country = "US" } });try { await Do("navigate", new { sessionId = (string?)opened!["sessionId"], url = "https://example.com" }); var page = await Do("markdown", new { sessionId = (string?)opened!["sessionId"] }); Console.WriteLine((string?)page!["result"]);} finally { await Do("close", new { sessionId = (string?)opened!["sessionId"] });}import com.fasterxml.jackson.databind.*;import java.net.URI;import java.net.http.*;import java.util.Map;public class Stealth { static final URI API = URI.create("https://api.browser.city/v1/do/"); static final HttpClient HTTP = HttpClient.newHttpClient(); static final ObjectMapper JSON = new ObjectMapper(); public static void main(String[] args) throws Exception { var opened = callAction("open", Map.of( "browser", "chromium", "egress", Map.of("mode", "managed", "proxyType", "residential", "country", "US"))); var sessionId = opened.get("sessionId").asText(); try { callAction("navigate", Map.of("sessionId", sessionId, "url", "https://example.com")); var page = callAction("markdown", Map.of("sessionId", sessionId)); System.out.println(page.get("result").asText()); } finally { callAction("close", Map.of("sessionId", sessionId)); } } static JsonNode callAction(String action, Object body) throws Exception { var req = HttpRequest.newBuilder(API.resolve(action)) .header("Authorization", "Bearer %s".formatted(System.getenv("BROWSERCITY_API_KEY"))) .header("Content-Type", "application/json") .POST(HttpRequest.BodyPublishers.ofString(JSON.writeValueAsString(body))).build(); return JSON.readTree(HTTP.send(req, HttpResponse.BodyHandlers.ofString()).body()); }} Start for free. No credit card required. Private sessions by default.