Installation
Install the SDK and let it fetch a verified browser — or download and verify a build yourself.
Clearcote is in active development. Builds are available for Windows x64 and Linux x64 — the SDK downloads the right one for your OS. On an Apple Silicon Mac the licensed build runs natively as a preview; on an Intel Mac or without a licence key,launch()runs the Clearcote Docker image for you (see macOS). On a minimal Linux host, install the browser's runtime libraries (libnss3 libgbm1 libasound2 libatk1.0-0 libatk-bridge2.0-0 libcups2 libxkbcommon0 libpango-1.0-0 …) —clearcote infolists any that are missing. If you start the binary yourself as root (typical in containers), pass--no-sandbox; the SDK andclearcote servehandle that for you.
NewThe latest build is free for one browser with GitHub, a card check or a company Google account. Never charged.
Get it freeInstall the SDK (recommended)
npm i clearcote # Node 20+
pip install clearcote # Python 3.8+
dotnet add package Clearcote # .NET 8The first launch() downloads the browser for your OS, checks its SHA-256 and caches it. You don't run playwright install — each SDK brings its Playwright driver and fetches its own browser. Which build you get depends on whether a licence key is set:
| Build | Where it comes from | |
|---|---|---|
| No key | The open build — Chromium 151.0.7922.108 (v0.1.0-pre.25). BSD-3, reproducible from public source. | GitHub Releases, pinned by the SDK version |
| A key | The licensed build — Chromium 156.0.8078.47-r54. Free with GitHub for one browser at a time, or Pro. | clearcotelabs.com, the current build on every launch |
Set a licence key
The SDK looks for a key in this order: the licenseKey / license_key / LicenseKey launch option, then the CLEARCOTE_LICENSE_KEY environment variable, then ~/.clearcote/license.key — the file clearcote login writes. Every SDK, .NET included, reads that file. Get a free key from Licenses in your dashboard.
clearcote login --device # sign in from a browser on any device; nothing to paste
clearcote login # asks for the key; what you paste is not shown
clearcote login cc_lic_... # for scripts: checks the key, saves it to ~/.clearcote/license.key
export CLEARCOTE_LICENSE_KEY=cc_lic_... # or per process / per containerSign in from another device
clearcote login --device (SDK 0.40.0+, Python and Node; npx clearcote login --device with a local npm install) saves a key without you copying one. It prints a link and a short code. Open the link in a browser on any device where you can sign in to clearcotelabs.com, check that the page shows the same code as your terminal, tick the box confirming the terminal is yours, and approve. The page says the device is signed in, and the terminal prints Signed in as with your account's address (partly hidden), where it saved the key, and the plan and expiry. The key itself is never printed, on the page or in the terminal.
A code lasts 10 minutes; after that, run the command again for a new one. Ctrl-C while it waits saves nothing, and a second Ctrl-C stops at once. Use --device on a server you reach over SSH, in a container, or when a coding agent sets Clearcote up for you: the approval happens in your own browser and nothing secret passes through the terminal, its history or a chat. With the key at hand on your own machine, clearcote login is as good: since 0.40.0 it reads the key without showing it.
The clearcote command
The Python and Node packages install a clearcote command (with a local npm install, run it as npx clearcote …). The .NET package doesn't include one.
clearcote install # download + verify the browser now (CI, Docker builds)
clearcote info # this machine, SDK, key, cached builds, seats in use, a launch test, missing libraries
clearcote info --proxy <url> # the exit IP, timezone and language a launch through this proxy would get
clearcote bench --proxy <url> # what each browser costs here in CPU and RAM, page timings, how many fit at once
clearcote update # fetch a newer build if one exists (newest open build, or current licensed)
clearcote clear-cache # delete cached builds — old ones are kept until you do
clearcote login [key] # clearcote logout removes the saved key
clearcote serve # a standing CDP endpoint — see Deployment
clearcote connect [code] # start the helper for the web Profile Manager — see belowEvery command takes --help. From SDK 0.40.0, clearcote info tests the build launch() would run, including the one CLEARCOTE_BROWSER_VERSION names, and shows when the key expires if it was saved with clearcote login --device (no licence service reports a pasted key's expiry). From 0.41.0 it also reports, on Linux, which writing systems the fonts a launch would see can draw (see your own fonts on Linux). clearcote install --version 154 or --channel preview picks a specific build; see choosing a build. Next, wire it into Playwright or Puppeteer.
From 0.56.0, clearcote info starts with the machine (processor, memory, operating system, virtual machine or container, and whether there is a graphics card the browser can draw with), and clearcote bench starts --concurrency browsers (default 3) on --url for --duration seconds (default 30), through --proxy if given, and reports what each browser costs in CPU threads and RAM on this machine, page timings, errors, about how many browsers the machine runs at once and what to change. It runs fewer browsers when free memory looks too small (--force runs them all), and each browser holds a licence seat while it runs. Paste its output into a support request. In .NET, ClearcoteBench.RunAsync and ClearcoteHost.Info give the same report from code.
From 0.61.0, clearcote connect starts the Clearcote Helper in that terminal, so the web version of the Profile Manager at app.clearcotelabs.com can launch your profiles on this computer. In its Connect window, pick I use the Clearcote SDK and run the command it shows with its one-time code (npx clearcote connect 4F7-K2Q): that tab connects by itself, without the approval page. The first run downloads the helper release the SDK pins and checks its SHA-256. Keep the terminal open; Ctrl+C closes the helper and its browsers.
macOS
On an Apple Silicon Mac (M1 or newer, macOS 13 or later) with a licence key, the SDK (0.51.1+) downloads the licensed macOS build and starts it natively, as on Windows and Linux. It is a preview, and it can trail Windows and Linux: right now it is 155.0.8059.39-r49 while they run 156.0.8078.47-r54. An open 150 build for Apple Silicon is on GitHub Releases (v0.1.0-pre.24) to run by hand with executable_path; the SDK does not fetch it.
On an Intel Mac, or without a licence key, launch() (SDK 0.40.0+) starts the Clearcote Docker image (teamflatearth/clearcote:sdk-<SDK version>, a linux/amd64 image Docker Desktop runs on Intel and Apple silicon), connects to it and returns the same Playwright browser a local launch does. Your code does not change, and close() stops and removes the container. This covers launch() in Python (sync and async), Node and .NET (LaunchAsync); the other entry points, such as persistent contexts and serve(), still need a Clearcote binary, so on a Mac run those in the Docker image directly.
from clearcote import launch
browser = launch(fingerprint="acct-1") # on macOS: runs teamflatearth/clearcote:sdk-<version>
page = browser.new_page()
page.goto("https://example.com")
print(page.title())
browser.close() # stops and removes the container- Docker Desktop must be installed and running. Without it,
launch()raisesDockerUnavailableError(.NET:DockerUnavailableException) saying what to do. The first launch downloads the image, and with a licence key the latest build, once, into theclearcote-cachevolume; later launches start in seconds. - What goes into the container: the persona options,
headless,proxy,args,versionand the licence key (found as on any other machine, including the oneclearcote loginsaved). An option the container cannot take is refused by name. The key and the proxy reach the container as a file it reads once and deletes, sodocker inspectdoes not show them, and a launch with a key or a proxy is refused if the container does not run the licensed build or the proxy. - Nothing is left running. If your program exits or is killed without
close(), its container stops by itself about 30 seconds after nothing is connected to it, and the next launch removes leftovers whose program is gone. Containers that belong to other running programs, other users or other machines are never touched. Since SDK 0.41.0,close()returns only once Docker has removed the container and its volume, sodocker ps -ano longer lists it afterwards. - Chrome keeps its sandbox (SDK 0.41.0+ with an image from
sdk-0.41.0): the launch passes the image's seccomp profile, so Chrome runs with its sandbox inside the container (see Chrome's sandbox). That needs Docker on an x86_64 CPU; on Apple silicon the image runs emulated and the sandbox stays off for now. - The container runs Linux, so its default persona is a Linux one. Read Deployment before claiming another platform from a container.
| Setting | What it does |
|---|---|
docker=False (Node docker: false, .NET Docker = false) or CLEARCOTE_DOCKER=0 | Don't use Docker. On macOS you then pass executable_path to a compatible Clearcote binary yourself. |
docker=True or CLEARCOTE_DOCKER=1 | Use the Docker image on any OS that has Docker. |
docker_image= (Node dockerImage, .NET DockerImage) or CLEARCOTE_DOCKER_IMAGE | Run another image or tag, for example to pin teamflatearth/clearcote:sdk-0.46.0. An image older than sdk-0.40.0 still works, with a warning: it gets the key and the proxy as variables docker inspect shows, and it does not stop by itself if your program dies. |
CLEARCOTE_DOCKER_IDLE_EXIT | Seconds an unattended container waits before it stops (default 30, 0 = never). |
CLEARCOTE_DOCKER_CACHE_VOLUME | The volume the licensed build is kept in (default clearcote-cache). |
An image is published a few minutes after its SDK release, so right after an upgrade the matching tag may not exist yet; the error says so, and CLEARCOTE_DOCKER_IMAGE can point at an earlier tag meanwhile.
Manual install (open build)
Prefer the bare binary? GitHub Releases carries the open build. The licensed build isn't published there: it runs through the SDK, clearcote serve or the Docker image, and it won't start without the run token the SDK provides.
1. Download
Download the newest v0.1.0-pre.* release — currently v0.1.0-pre.25 (Chromium 151.0.7922.108). Each release ships:
clearcote-<version>-windows-x64.zip— the Windows build (Chromium + runtime + VC++ DLLs)clearcote-<version>-linux-x64.tar.xz— the Linux build.sha256files andSHA256SUMS.txt— checksums.ascfiles +clearcote-signing-key.asc— GPG detached signatures and the public key
2. Verify (recommended)
The open build is built so you don't have to trust us. Before extracting, confirm the download is exactly what was built and signed — see Verification.
3. Extract
The Windows archive is self-contained: the VC++ 2015–2022 runtime DLLs are bundled, so it runs on a clean Windows 10/11 box. The Linux archive needs the runtime libraries listed above.
Expand-Archive clearcote-151.0.7922.108-windows-x64.zip -DestinationPath C:\clearcote
# you now have:
# C:\clearcote\chrome.exe
# C:\clearcote\chrome.dll + runtime, locales, ICU, ANGLE, VC++ DLLs4. Smoke test
Launch it against a fingerprint test page with a seed:
C:\clearcote\chrome.exe --fingerprint=seed-123 --fingerprint-platform=windows https://abrahamjuliot.github.io/creepjs/Same --fingerprint seed ⇒ the same identity every launch; a new seed ⇒ a fresh one. To report a real machine's captured values instead of the seed-derived ones, import a captured profile — see Fingerprint flags. Then wire it into Playwright or Puppeteer.
Run in Docker
The official image runs Clearcote as a CDP endpoint — pull it and point any Playwright, Puppeteer, or browser-use client at it over the Chrome DevTools Protocol, no code change.
# Chrome's sandbox profile, shipped in the image
docker run --rm --tmpfs /opt/xdg-cache --entrypoint cat teamflatearth/clearcote /etc/clearcote/seccomp.json > clearcote-seccomp.json
docker run -d --rm --shm-size=1g -p 127.0.0.1:9222:9222 --security-opt seccomp=clearcote-seccomp.json -e CC_FINGERPRINT=user-7423 teamflatearth/clearcote # CDP on http://localhost:9222from playwright.sync_api import sync_playwright
with sync_playwright() as p:
browser = p.chromium.connect_over_cdp("http://localhost:9222") # your code, unchanged
page = browser.new_page(); page.goto("https://example.com")Configure the persona with env vars — CC_PLATFORM (windows/linux/macos/android), CC_FINGERPRINT (seed), CC_BRAND (Edge…), CC_ACCEPT_LANGUAGE, CC_TIMEZONE, CC_TLS_PROFILE. Without CC_FINGERPRINT each container gets its own random seed, kept across restarts; set it to choose or reuse an identity. The image ships the open build; add -e CLEARCOTE_LICENSE_KEY=cc_lic_… -v clearcote-cache:/opt/xdg-cache to run the latest licensed build, downloaded once into the volume. The browser runs headed on a virtual display (CC_HEADLESS=1 for pure headless), and the image is linux/amd64. The Dockerfile is auditable — rebuild it yourself. The CDP endpoint is full browser control, so publish it only to trusted networks (-p 127.0.0.1:9222:9222 keeps it host-local). More in Deployment.
Download limits
Downloads of the licensed build are rate-limited per licence, so a setup that fetches the full archive on every start can't run away. A launch that finds the build in its cache doesn't download anything and never counts — only real downloads do.
| Limit | Applies to | Counts |
|---|---|---|
| 20 downloads per minute and 30 per 24 hours | Every licence, per build (version + OS) | Archive downloads of the same build. A new release starts with a fresh budget. |
| 10 different builds per 24 hours | Free licences | Distinct builds fetched. A build you already downloaded today costs nothing again. |
| 60 checks per minute | Per IP address | The build check every launch makes to /api/v1/download/pro, cached or not. |
Over a limit, the SDK gets HTTP 429 with a JSON body — code is DOWNLOAD_RATE_LIMITED (per-build budget) or DOWNLOAD_LIMIT_EXCEEDED (free plan) — and a Retry-After header: the seconds until that limit resets. Launches whose build is already cached keep working. From SDK 0.62.0, a launch that cannot download a new build starts the newest build of the same Chromium version already in its cache instead of failing, and waits for Retry-After before it tries that download again. A launch pinned to an exact revision (r50) still gets that build or an error.
You hit these when many fresh machines or containers start at once, each with an empty cache. Download each build once per machine instead of once per start — starts get faster too, without a ~460 MB download:
- Keep the cache on a volume. Point
CLEARCOTE_CACHEat a directory that survives restarts. Starts that share it wait for the first download and reuse it. - Bake the browser into your image. Run
clearcote installat build time, so every container starts with the build in place. Rebuild the image when you upgrade.
# 1. a shared, persistent cache
docker run -v clearcote-cache:/clearcote-cache -e CLEARCOTE_CACHE=/clearcote-cache …
# 2. or in your Dockerfile: download once while the image is built (the key stays out of the layers)
ENV CLEARCOTE_CACHE=/opt/clearcote-cache
RUN --mount=type=secret,id=clearcote_key \
CLEARCOTE_LICENSE_KEY="$(cat /run/secrets/clearcote_key)" clearcote installNeed a higher limit? Tell us how you run Clearcote and we'll raise it for your licence.
Chat with usPersona limits
Every launch fetches its persona (the fingerprint that seed and options describe) from the persona service. Each licence can fetch a set number of different personas per day. Fetching a persona you already used today costs nothing, so a fixed set of profiles can relaunch as often as you like.
| Plan | Different personas per day |
|---|---|
| Free | 750 |
| Pro and other paid plans | 1,000,000 |
A persona is one seed with one set of fingerprint options (brand, platform and so on), so the same seed as Chrome and as Edge counts twice. The count resets at 00:00 UTC. Over the limit, the launch fails with HTTP 429 from the persona service (daily persona quota reached) until the reset.
You hit this when every launch uses a brand-new random seed. Reuse a fixed pool of seeds instead, for example a list of a few hundred names you rotate through: each one keeps the same fingerprint every time it starts, and relaunching it never counts again.
Requirements
- Windows 10 / 11 x64, or Linux x64 (glibc) with the runtime libraries above.
- macOS: on Apple Silicon (macOS 13+) with a licence key, nothing extra (SDK 0.51.1+). On an Intel Mac or without a key, Docker Desktop, running, for
launch()(SDK 0.40.0+). - No separate VC++ redistributable needed on Windows — it's bundled in the archive.
- SDK: Node 20+, Python 3.8+ or .NET 8. Each pulls in its own Playwright driver (
playwright-core,playwright,Microsoft.Playwright). - Using the open build's binary directly: your existing Playwright or Puppeteer install (Clearcote replaces the browser, not the driver).