Zum Inhalt springen

Deployment — Docker & CDP-Endpunkt

Betreiben Sie Clearcote als dauerhaften CDP-Endpunkt und richten Sie jedes vorhandene Framework darauf — Playwright, Puppeteer, browser-use, Crawl4AI, Stagehand —, ohne Code zu ändern. Das Binary wird direkt gestartet (ohne --enable-automation), daher bleibt navigator.webdriver auf false: konstruktionsbedingt unauffällig.

Offizielles Docker-Image

Image ziehen und loslegen. Jeder CDP-Client verbindet sich über den freigegebenen Port.

bash
docker run -d --rm -p 127.0.0.1:9222:9222 -e CC_FINGERPRINT=user-7423 teamflatearth/clearcote   # CDP on http://localhost:9222
python
from 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.contexts[0].new_page()                            # the container's own profile
    page.goto("https://example.com")
    print(page.title())

Das Image enthält fest eingebaut den per SHA-256 verifizierten offenen Build für Linux und die metrikkompatiblen Nachbauten der Windows-Schriften (damit lateinischer Text dieselben Maße hat wie mit den Schriften der Persona; das Bundle des offenen Builds enthält keine CJK-Schriften, chinesischer, japanischer und koreanischer Text wird also ohne Schrift dargestellt, bis Sie den lizenzierten Build verwenden, dessen Bundle sie enthält) und nutzt standardmäßig eine kohärente native Linux-Persona. Der Browser läuft im Headed-Modus auf einem virtuellen Display (CC_HEADLESS=1 für reinen Headless-Betrieb). Konfigurieren lässt sich das Image vollständig über Umgebungsvariablen:

bash
docker run -d -p 127.0.0.1:9222:9222 -e CC_PLATFORM=linux -e CC_FINGERPRINT=user-7423 -e CC_ACCEPT_LANGUAGE=en-US -e CC_TIMEZONE=America/New_York teamflatearth/clearcote
VariableBedeutung
CC_FINGERPRINTSeed → stabile Identität. Ohne diese Variable präsentieren alle Container dieselbe Identität (Seed clearcote-docker); geben Sie also jedem Container einen eigenen.
CC_PLATFORMlinux (Standard) | windows | macos | android. Eine Windows-Persona schaltet außerdem Widevine ein und auf dem lizenzierten Build (151 r15+) den HLSL-Shader-Dialekt (zum Überschreiben: CC_WIDEVINE / CC_SHADER_DIALECT).
CC_BRAND, CC_BRAND_VERSIONChrome (Standard) | Edge | Opera | Vivaldi sowie die Version, die diese Marke angibt.
CC_ACCEPT_LANGUAGE, CC_TIMEZONESprachliste und IANA-Zeitzone.
CC_TLS_PROFILENicht setzen: TLS folgt dann der Chrome-Version, die die Persona angibt. Pinnen Sie chrome-<major> nur zusammen mit einer passenden CC_BRAND_VERSION.
CC_HARDWARE_CONCURRENCY, CC_GPU_VENDOR, CC_GPU_RENDERER, CC_STORAGE_QUOTAEinzelne Persona-Werte.
CC_HEADLESS, CC_SCREEN1 für reinen Headless-Betrieb; die Größe des virtuellen Bildschirms (Standard 1920x1080x24).
CC_EXTRA_ARGSZusätzliche Browser-Switches, durch Leerzeichen getrennt.
CLEARCOTE_LICENSE_KEY, CC_VERSIONStartet den lizenzierten Build — siehe unten.
Geben Sie sich als das Betriebssystem aus, auf dem der Container läuft. Manches, was eine Seite auslesen kann, stammt vom Host-Betriebssystem unterhalb des Browsers, und keine Persona-Einstellung reicht bis dorthin. In diesem Linux-Image wird Text vom FreeType-Scaler von Linux skaliert, und die Schriften kommen aus fontconfig, ganz gleich, was CC_PLATFORM sagt. Gemessen auf diesem Image mit CC_PLATFORM=windows: Wird die Schriftgröße in Schritten von 0,01 px verändert, ändert sich die Textbreite bei 66 % der Schritte (echtes Chrome unter Windows: 99 %), und Segoe UI und Georgia gelten bei der Messung als installiert, lassen sich aber nicht per Name laden. Der Fingerprint-Test schlägt bei beidem an. Die Standard-Linux-Persona besteht. Für eine Windows-Identität nutzen Sie den Windows-Build oder gehostete Browser, die auf Windows-Rechnern laufen. Dasselbe gilt für serve() und launch() auf einem Linux-Server. Details: Der Font-Stack unter dem User-Agent.

Lizenzierter Build in Docker — Schlüssel übergeben, Cache mounten

Das Image bringt den offenen Build fest eingebaut mit. Setzen Sie CLEARCOTE_LICENSE_KEY, und der Container bezieht stattdessen den lizenzierten Build — den neuesten oder, im Pro-Plan, einen bestimmten per CC_VERSION. Mit kostenlosen Schlüsseln läuft immer der neueste Build; eine gepinnte Version wird abgelehnt.

bash
docker run -d -p 127.0.0.1:9222:9222 -v clearcote-cache:/opt/xdg-cache -e CLEARCOTE_LICENSE_KEY=cc_lic_... teamflatearth/clearcote

# Pro only: pin a major, an exact build, or a revision
#   -e CC_VERSION=153        -e CC_VERSION=153.0.8010.36        -e CC_VERSION=r28

Mounten Sie immer das Cache-Volume. Ein lizenzierter Container lädt die Engine beim ersten Start herunter; ohne persistentes Volume tut das jeder Container erneut. Mit dem Volume starten spätere Container aus dem gecachten Build.

Das Startup-Log zeigt, welche Engine Sie bekommen haben — ein falsch konfigurierter Schlüssel fällt so sofort auf und nicht erst beim ersten blockierten Request:

text
[clearcote] engine: /opt/xdg-cache/clearcote/pro-153.0.8010.36-r28/browser/chrome (licensed)
[clearcote] licence lease acquired
Erfordert ein Image, das mit SDK 0.26.1 oder neuer gebaut wurde, und mit 0.30.0 oder neuer für einen kostenlosen Schlüssel von GitHub — der lizenzierte Browser erwartet, dass ein kostenloser Container seine Lizenz während der Laufzeit aktuell hält, und verweigert ein älteres Image. Ältere veröffentlichte Images ignorieren den Schlüssel und liefern stillschweigend den offenen Build aus — aktualisieren Sie mit docker pull teamflatearth/clearcote. Ein lizenzierter Lauf bezieht beim Start außerdem ein Concurrency-Lease, der Container braucht also ausgehenden Zugriff auf die Lizenz-API; schlägt das Lease fehl, beendet sich der Container unter Angabe des Grundes, statt eine Engine zu starten, die nicht laufen kann. Mit einem kostenlosen Schlüssel läuft über alle Ihre Container hinweg immer nur ein Browser gleichzeitig — siehe wie lizenzierte Browser gezählt werden.
Sicherheit: Wer den CDP-Endpunkt erreicht, hat volle Kontrolle über den Browser. Geben Sie ihn nur in vertrauenswürdigen Netzen frei — -p 127.0.0.1:9222:9222 hält ihn lokal auf dem Host. Das docker/ Dockerfile ist nachprüfbar — bauen und verifizieren Sie es selbst.

Dauerhafter CDP-Endpunkt aus dem SDK — serve()

Starten Sie das Binary selbst und erhalten Sie eine cdp_url, an die sich jeder Client anhängen kann. Derselbe unauffällige Direktstart wie beim Image, gesteuert aus Ihrem eigenen Prozess.

python
from clearcote import serve

srv = serve(fingerprint="seed-123", platform="windows")   # -> srv.cdp_url
# attach ANY CDP client:
#   playwright:  p.chromium.connect_over_cdp(srv.cdp_url)
#   puppeteer:   puppeteer.connect({ browserURL: srv.cdp_url, defaultViewport: null })
#   browser-use / Crawl4AI / Stagehand: point them at srv.cdp_url
srv.close()
javascript
import { serve } from "clearcote";
const srv = await serve({ fingerprint: "seed-123", platform: "windows" });
// srv.cdpUrl -> connectOverCDP / puppeteer.connect({ browserURL, defaultViewport: null })
await srv.close();

Im Headless-Modus bekommt der bereitgestellte Browser ein Display in realer Größe — das der Persona oder eines, das aus echten Desktops ausgewählt wird —, und sein Fenster wird an den Arbeitsbereich angepasst, bevor sich ein Client verbindet. So meldet jede Seite, jeder Tab und jedes Popup ein Fenster, das auf den Bildschirm passt (SDK 0.31+). Für ein kleineres Fenster übergeben Sie windowSize: { width, height } (window_size in Python, WindowSize in .NET); mit Ihrem eigenen --window-size in args übernehmen Sie selbst die Kontrolle.

Ein Endpunkt, viele Identitäten — clearcote serve

Aus der Shell (Python- und Node-Pakete, 0.29+) betreibt clearcote serve einen dauerhaften Endpunkt, der für jede Identität, die eine Verbindung anfordert, einen eigenen Browser startet — Seed, Proxy, Zeitzone und Sprache kommen aus der Verbindungs-URL. Derselbe Seed nutzt seinen bereits laufenden Browser wieder.

bash
clearcote serve --port 9222 --idle-timeout 300 --max-browsers 16

# then, from any Playwright client:
#   chromium.connect_over_cdp("http://127.0.0.1:9222?fingerprint=acct-1&platform=windows")
#   chromium.connect_over_cdp("http://127.0.0.1:9222?fingerprint=acct-2&proxy=socks5://user:pass@host:1080&geoip=true")
#   (a password-protected proxy needs the licensed build)

Standardmäßig bindet sich der Endpunkt an localhost und lehnt Requests ab, die eine Webseite auslösen könnte. Inaktive Identitäten werden nach --idle-timeout Sekunden geschlossen, --max-browsers begrenzt, wie viele gleichzeitig laufen (weitere Identitäten erhalten HTTP 429), --data-dir behält das Profil jeder Identität über Neustarts hinweg, und --allow-host / --allow-origin ermöglichen den Betrieb hinter einem Reverse-Proxy. Unter http://127.0.0.1:9222/ sehen Sie, was gerade läuft. Mit einem Schlüssel „Kostenlos mit GitHub“ läuft jeweils nur ein Browser. Das ältere Skript clearcote-serve --port 9222 --fingerprint seed-123 für eine einzelne Identität ist weiterhin im Python-Paket enthalten.

Direkt — der offene Build ohne SDK

Der offene Build auf der Releases-Seite ist ein gewöhnliches Chromium-Binary, das Sie selbst mit executable_path und Switches starten können. Der lizenzierte Build braucht das SDK, das sein Lizenz-Token verwaltet. Die zusätzlichen Argumente unten sind die wichtigsten Standardwerte, die das SDK für diesen Seed unter Windows hinzufügt (außerdem führt es Feature-Flags zusammen und schaltet hinter einem Proxy QUIC ab):

python
from playwright.sync_api import sync_playwright

with sync_playwright() as p:
    browser = p.chromium.launch(
        executable_path=r"C:\clearcote\chrome.exe",
        ignore_default_args=["--enable-automation", "--enable-unsafe-swiftshader"],
        args=[
            "--fingerprint=seed-123",
            "--fingerprint-platform=windows",
            "--fingerprint-brand=chrome",
            "--accept-lang=en-US,en",
            "--lang=en-US",
            "--timezone=America/New_York",
            "--webrtc-ip-handling-policy=disable_non_proxied_udp",
            "--ignore-gpu-blocklist",
        ],
    )
    browser.new_page().goto("https://example.com")

Eigenes Image bauen (SDK-gesteuert)

Clearcote liefert ein Linux-x64-Binary und läuft daher headless in einem Container. Das Image braucht die Laufzeitbibliotheken des Browsers, fontconfig und das SDK. Der Browser verwendet das Schriften-Bundle seines Releases statt der Systemschriften; wie beim offiziellen Image enthält der offene Build keine CJK-Schriften (das Bundle des lizenzierten Builds enthält sie). Unter Linux ist die Persona standardmäßig eine kohärente native Linux-Identität. Der Schutz vor WebRTC-Leaks ist standardmäßig aktiv; die Privacy-Sandbox-APIs bleiben an, wie in Google Chrome.

dockerfile
FROM node:22-slim
RUN apt-get update && apt-get install -y --no-install-recommends \
      xz-utils libnss3 libnspr4 libgbm1 libasound2 libatk1.0-0 libatk-bridge2.0-0 libcups2 libdrm2 \
      libxkbcommon0 libxcomposite1 libxdamage1 libxrandr2 libxfixes3 libxext6 libxrender1 \
      libpango-1.0-0 libcairo2 libx11-6 libxcb1 libexpat1 libdbus-1-3 ca-certificates \
      fontconfig fonts-liberation fonts-noto-color-emoji fonts-unifont fonts-ipafont-gothic fonts-wqy-zenhei \
 && rm -rf /var/lib/apt/lists/*
WORKDIR /app
RUN npm i clearcote
RUN node --input-type=module -e "import { download } from 'clearcote'; await download();"   # bake the binary in
COPY run.mjs .
CMD ["node", "run.mjs"]
run.mjs
import { launchPersistentContext } from "clearcote";
const ctx = await launchPersistentContext("/tmp/prof", {
  headless: true,
  fingerprint: "user-1",
  proxy: { server: "http://gateway:8080", username: "u", password: "p" },
  geoip: true,      // timezone + languages + WebRTC IP matched to the proxy exit
  humanize: true,   // trusted bezier input; navigator.webdriver stays false
  args: ["--no-sandbox"],
});
const page = ctx.pages()[0] ?? (await ctx.newPage());
await page.goto("https://example.com");
await ctx.close();
Starten Sie den Container mit --shm-size=1g, um Abstürze wegen /dev/shm auf aufwendigen Seiten zu vermeiden. In Python funktioniert es genauso (from clearcote import launch_persistent_context, Optionen in snake_case).

Was sich per CDP verbinden lässt

ClientVorgehen
Playwrightchromium.connect_over_cdp(url) / connectOverCDP(url)
Puppeteerpuppeteer.connect({ browserURL: url, defaultViewport: null })
browser-use · Crawl4AI · Stagehanddie CDP-/Endpoint-Einstellung auf die URL richten
Alles, was CDP sprichtdas rohe DevTools Protocol auf dem Port

Soll stattdessen ein KI-Agent den Browser steuern? Siehe den MCP-Server. Sie fragen sich, warum ein Direktstart unauffälliger ist? Siehe Wie Erkennung funktioniert.