Playwright Connect
Native BrowserType.connect() integration. Use existing test scripts — just change the connection URL.
Run your Playwright tests against real cloud browsers. Use custom fingerprints to test geo-specific content and mobile emulation to ensure your site is perfectly responsive.
Native BrowserType.connect() integration. Use existing test scripts — just change the connection URL.
Test on iPhone, Android, tablet viewports with matching user agents, touch events, and screen density.
Run tests from 195+ countries. Verify geo-specific content, localization, and regional restrictions.
Control OS, GPU, WebGL, fonts, timezone, locale. Test how your site behaves across different device profiles.
Run up to 50 concurrent browser sessions. Execute your test suite faster with real cloud browsers.
Capture full session recordings for debugging. Replay exact browser state to diagnose test failures.
Drop in your browser.city endpoint — your existing test scripts work without any other changes.
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://your-app.com');} finally { const { summary } = await fetch(`https://api.browser.city/v1/sessions/${id}`, { method: 'DELETE', headers: { Authorization: `Bearer ${process.env.BROWSERCITY_API_KEY}` }, }).then((r) => r.json()); console.log('Runtime seconds:', summary?.stats?.runtimeSeconds ?? 0); console.log('Cookies stored:', summary?.storage?.cookies?.length ?? 0);}import os, requestsfrom playwright.sync_api import sync_playwrightauth = {'Authorization': f"Bearer {os.environ['BROWSERCITY_API_KEY']}"}session = requests.post( 'https://api.browser.city/v1/sessions', headers=auth, json={'browser': 'chromium'}).json()endpoint = session['endpoint']token = session['token']session_id = session['id']playwright = Nonetry: playwright = sync_playwright().start() browser = playwright.chromium.connect( endpoint, headers={'Authorization': f'Bearer {token}'}, ) page = browser.contexts[0].pages[0] page.goto('https://your-app.com')finally: try: deleted = requests.delete(f'https://api.browser.city/v1/sessions/{session_id}', headers=auth).json() summary = deleted.get('summary') or {} print('Runtime seconds:', (summary.get('stats') or {}).get('runtimeSeconds', 0)) cookies = (summary.get('storage') or {}).get('cookies') or [] print('Cookies stored:', len(cookies)) finally: if playwright: playwright.stop()using Microsoft.Playwright;using System.Collections.Generic;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://your-app.com");} finally { try { if (session is not null) { var deleted = await (await http.DeleteAsync($"https://api.browser.city/v1/sessions/{id}")) .Content.ReadFromJsonAsync<DeleteSessionResponse>(); Console.WriteLine($"Runtime seconds: {deleted?.Summary?.Stats?.RuntimeSeconds ?? 0}"); Console.WriteLine($"Cookies stored: {deleted?.Summary?.Storage?.Cookies?.Count ?? 0}"); } } finally { pw?.Dispose(); }}record Session(string Id, string Endpoint, string Token);record DeleteSessionResponse(DeleteSessionSummary? Summary);record DeleteSessionSummary(DeleteSessionStats? Stats, DeleteSessionStorage? Storage);record DeleteSessionStats(double? RuntimeSeconds);record DeleteSessionStorage(List<object>? Cookies);import com.fasterxml.jackson.databind.ObjectMapper;import com.microsoft.playwright.*;import java.net.URI;import java.net.http.*;import java.util.List;import java.util.Map;public class Test { public static void main(String[] args) throws Exception { var key = System.getenv("BROWSERCITY_API_KEY"); var http = HttpClient.newHttpClient(); var json = new ObjectMapper(); 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 = json.readValue(http.send(req, HttpResponse.BodyHandlers.ofString()).body(), Session.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://your-app.com"); } finally { try { var deleteResponse = http.send(HttpRequest.newBuilder(URI.create("https://api.browser.city/v1/sessions/" + id)) .header("Authorization", "Bearer %s".formatted(key)).DELETE().build(), HttpResponse.BodyHandlers.ofString()); if (deleteResponse.statusCode() / 100 != 2) { throw new RuntimeException("Delete failed: " + deleteResponse.statusCode()); } var deleteBody = deleteResponse.body(); if (deleteBody.strip().startsWith("{")) { var deleted = json.readValue(deleteBody, Map.class); Object runtimeSeconds = 0; int cookieCount = 0; if (deleted.get("summary") instanceof Map<?, ?> summary) { if (summary.get("stats") instanceof Map<?, ?> stats && stats.get("runtimeSeconds") != null) { runtimeSeconds = stats.get("runtimeSeconds"); } if (summary.get("storage") instanceof Map<?, ?> storage && storage.get("cookies") instanceof List<?> cookies) { cookieCount = cookies.size(); } } System.out.println("Runtime seconds: " + runtimeSeconds); System.out.println("Cookies stored: " + cookieCount); } } finally { if (pw != null) pw.close(); } } } record Session(String id, String endpoint, String token) {}} Start for free. No credit card required. Private sessions by default.