Skip to content

Hosted browsers

Start a Clearcote browser on our servers with one API call and drive it over the Chrome DevTools Protocol, from Playwright, Puppeteer or any CDP client. Nothing to install or run yourself. Traffic leaves through residential IPs by default, and you pay per GB from a prepaid balance.

  • Residential IPs, not datacenter. Websites see a real home internet connection from a consumer provider, not a hosting or cloud address.
  • Real hardware, not a VPS. Browsers run on our own dedicated physical servers, not on shared cloud virtual machines.
More on hosted browsers: one SDK for local and cloud (launch(cloud=True)), agent runs (a task in, JSON out), recordings and the event timeline, cookie sync, secrets and 2FA, and hand-off to a person and webhooks.

FreeGet €5 of traffic free when you connect GitHub. No card.

One-time, one per GitHub account. The GitHub account must be at least 30 days old.

Claim €5

1. Get an API key

Create one on the API keys page. It starts with cc_live_ and is sent as a bearer token. Keep it secret: anyone holding it can spend your balance.

2. Start a browser and connect

POST /api/v1/browsers returns a connectUrl: a single-use WebSocket URL for that browser. Connect within two minutes; it cannot be used twice. The browser starts as you connect, usually within a few seconds, but with a country it can take up to about half a minute, because the exit IP's location is looked up first. Playwright gives up after 30 seconds by default, so the examples pass a two-minute timeout.

javascript
// Node.js + Playwright
import { chromium } from "playwright";

const res = await fetch("https://www.clearcotelabs.com/api/v1/browsers", {
  method: "POST",
  headers: { authorization: "Bearer cc_live_...", "content-type": "application/json" },
  body: JSON.stringify({ identity: "account-1", country: "us" }),
});
const { connectUrl, id, error } = await res.json();
if (error) throw new Error(error);

const browser = await chromium.connectOverCDP(connectUrl, { timeout: 120_000 }); // the browser starts as you connect
const context = browser.contexts()[0];
const page = context.pages()[0] ?? (await context.newPage());
await page.goto("https://example.com");
await browser.close(); // ends the session
javascript
// Puppeteer: the same connectUrl
const browser = await puppeteer.connect({ browserWSEndpoint: connectUrl, defaultViewport: null });
python
# Python + Playwright
import requests
from playwright.sync_api import sync_playwright

r = requests.post("https://www.clearcotelabs.com/api/v1/browsers",
                  headers={"authorization": "Bearer cc_live_..."},
                  json={"identity": "account-1", "country": "de"}).json()
with sync_playwright() as p:
    browser = p.chromium.connect_over_cdp(r["connectUrl"], timeout=120_000)
    page = browser.contexts[0].new_page()
    page.goto("https://example.com")
    browser.close()

The create call answers 201 with everything your code needs to connect and to know the price:

json
{
  "id": "bs_…",                       // use it with GET / DELETE /api/v1/browsers/<id>
  "connectUrl": "wss://…/v1/connect/bs_…?token=…",
  "expiresAt": "2026-09-24T10:02:00.000Z", // connect before this (two minutes)
  "worker": "w_…",
  "pricing": { "eurPerGb": 1, "eurPerHour": 0 },
  "limits": { "maxSeconds": 14400, "idleSeconds": 300 } // plus maxBytes when capped
}

Best practices

  1. Connect, never launch. Use connectOverCDP or puppeteer.connect with the connectUrl; chromium.launch() starts a browser on your own machine instead.
  2. Use what is there. Take browser.contexts()[0] and its first page rather than a new context: a new context starts without the profile's cookies and storage, and Playwright gives it an emulated 1280×720 viewport that does not match the browser window.
  3. Set the persona at create, not from the script. Country, timezone and language belong in the create call. Overriding the user agent, the viewport or navigator properties from a script creates exactly the inconsistencies detection looks for.
  4. Keep CDP hooks narrow. Broad listeners, interception of every request and init scripts are the automation's own fingerprint. Stock Playwright and Puppeteer work as they are, apart from two calls (setContent and exposeFunction): the engine keeps the Runtime.enable side effects away from the page itself, so a patched driver such as Patchright is optional rather than needed.
  5. One session, many pages. Starting a browser is the slow part; navigate within it. Sign in once with a profile instead of on every run.
  6. Always stop. Close the browser in a finally, and set maxGb and idleTimeoutSec to fit the job, so a bug cannot leave a browser running on your balance.
  7. Look before you add code. When a site misbehaves, watch it in the live view (or take control) before adding waits and workarounds.