Aller au contenu

Déploiement — Docker & endpoint CDP

Exécutez Clearcote comme endpoint CDP permanent et pointez-y n’importe quel framework existant — Playwright, Puppeteer, browser-use, Crawl4AI, Stagehand — sans modifier votre code. Il lance directement le binaire (sans --enable-automation), donc navigator.webdriver reste à false : furtif par construction.

Image Docker officielle

Récupérez l’image et c’est parti. N’importe quel client CDP se connecte via le port exposé.

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())

L’image embarque le build ouvert pour Linux, vérifié par SHA-256, ainsi que des polices aux métriques identiques à celles de Windows (pour que le texte latin ait les mêmes dimensions qu’avec les polices de la persona ; le bundle du build ouvert ne contient aucune police CJK, si bien que le texte chinois, japonais et coréen s’affiche sans police tant que vous n’exécutez pas le build sous licence, dont le bundle les inclut), et utilise par défaut une persona Linux native cohérente. Le navigateur tourne en mode headed sur un écran virtuel (CC_HEADLESS=1 pour du pur headless). Tout se configure par variables d’environnement :

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
VariableRôle
CC_FINGERPRINTSeed → identité stable. Sans cette variable, tous les conteneurs présentent la même identité (seed clearcote-docker) : donnez donc à chaque conteneur la sienne.
CC_PLATFORMlinux (par défaut) | windows | macos | android. Une persona Windows active aussi Widevine et, sur le build sous licence (151 r15+), le dialecte de shader HLSL (CC_WIDEVINE / CC_SHADER_DIALECT pour changer ce comportement).
CC_BRAND, CC_BRAND_VERSIONChrome (par défaut) | Edge | Opera | Vivaldi, et la version annoncée.
CC_ACCEPT_LANGUAGE, CC_TIMEZONEListe des langues et fuseau horaire IANA.
CC_TLS_PROFILEÀ laisser vide : le TLS suit la version de Chrome annoncée par la persona. N’épinglez un chrome-<major> qu’avec un CC_BRAND_VERSION correspondant.
CC_HARDWARE_CONCURRENCY, CC_GPU_VENDOR, CC_GPU_RENDERER, CC_STORAGE_QUOTAValeurs individuelles de la persona.
CC_HEADLESS, CC_SCREEN1 pour du pur headless ; la taille de l’écran virtuel (par défaut 1920x1080x24).
CC_EXTRA_ARGSOptions supplémentaires du navigateur, séparées par des espaces.
CLEARCOTE_LICENSE_KEY, CC_VERSIONExécuter le build sous licence — voir ci-dessous.
Annoncez l’OS sur lequel tourne le conteneur. Une partie de ce qu’une page peut lire provient du système d’exploitation hôte, sous le navigateur, et aucun réglage de la persona ne l’atteint. Dans cette image Linux, le texte est dimensionné par le scaler FreeType de Linux et les polices viennent de fontconfig, quoi que dise CC_PLATFORM. Mesuré sur cette image avec CC_PLATFORM=windows : faire varier une taille de police par pas de 0,01 px modifie la largeur du texte pour 66 % des pas (vrai Chrome sous Windows : 99 %), et Segoe UI et Georgia apparaissent comme installées à la mesure, mais ne peuvent pas être chargées par leur nom. Le test d’empreinte signale les deux. La persona Linux par défaut passe le test. Pour une identité Windows, utilisez le build Windows ou les navigateurs hébergés, qui tournent sur des machines Windows. Il en va de même pour serve() et launch() sur un serveur Linux. Pour en savoir plus : la pile de polices sous le user agent.

Build sous licence dans Docker — passez une clé, montez le cache

L’image embarque le build ouvert. Définissez CLEARCOTE_LICENSE_KEY et le conteneur résout à la place le build sous licence — le plus récent, ou, avec l’offre Pro, un build précis via CC_VERSION. Les clés gratuites exécutent toujours le dernier build, et tout épinglage est refusé.

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

Montez toujours le volume de cache. Un conteneur sous licence télécharge le moteur à son premier démarrage ; sans volume persistant, chaque conteneur recommence. Avec le volume, les conteneurs suivants démarrent à partir du build en cache.

Le log de démarrage indique quel moteur vous avez obtenu, si bien qu’une clé mal configurée se voit tout de suite plutôt qu’à la première requête bloquée :

text
[clearcote] engine: /opt/xdg-cache/clearcote/pro-153.0.8010.36-r28/browser/chrome (licensed)
[clearcote] licence lease acquired
Nécessite une image construite à partir du SDK 0.26.1 ou plus récent, et 0.30.0 ou plus récent pour une clé gratuite obtenue via GitHub — le navigateur sous licence attend d’un conteneur gratuit qu’il maintienne sa licence à jour pendant qu’il tourne, et refuse une image plus ancienne. Les anciennes images publiées ignorent la clé et servent discrètement le build ouvert — lancez docker pull teamflatearth/clearcote pour mettre à jour. Une exécution sous licence prend aussi un bail de concurrence au démarrage : le conteneur a donc besoin d’un accès sortant à l’API de licence ; si le bail échoue, le conteneur s’arrête en indiquant la raison au lieu de démarrer un moteur incapable de tourner. Une clé gratuite exécute un seul navigateur à la fois sur l’ensemble de vos conteneurs — voir comment les navigateurs sous licence sont comptés.
Sécurité : un endpoint CDP donne le contrôle total du navigateur. Ne l’exposez qu’à des réseaux de confiance — -p 127.0.0.1:9222:9222 le limite à la machine hôte. Le Dockerfile de docker/ est auditable — reconstruisez l’image et vérifiez-la vous-même.

Endpoint CDP permanent depuis le SDK — serve()

Lancez vous-même le binaire et obtenez une cdp_url à laquelle n’importe quel client se connecte. Le même lancement direct et furtif que l’image, piloté depuis votre propre processus.

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();

En headless, le navigateur servi reçoit un écran de taille réelle — celui de la persona, ou un écran tiré de vrais PC de bureau — et sa fenêtre est ajustée à la zone de travail avant que le moindre client ne se connecte : chaque page, onglet et popup renvoie ainsi une fenêtre qui tient dans son écran (SDK 0.31+). Passez windowSize: { width, height } (window_size en Python, WindowSize en .NET) pour une fenêtre plus petite, ou votre propre --window-size dans args pour prendre la main.

Un endpoint, plusieurs identités — clearcote serve

Depuis le shell (packages Python et Node, 0.29+), clearcote serve fait tourner un endpoint permanent qui démarre un navigateur distinct pour chaque identité demandée par une connexion — sa seed, son proxy, son fuseau horaire et sa langue étant tirés de l’URL de connexion. Une même seed réutilise son navigateur déjà lancé.

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)

Par défaut, il écoute sur localhost et refuse les requêtes qu’une page web pourrait émettre. Les identités inactives se ferment au bout de --idle-timeout secondes, --max-browsers plafonne le nombre de navigateurs simultanés (les identités supplémentaires reçoivent un HTTP 429), --data-dir conserve le profil de chaque identité d’un redémarrage à l’autre, et --allow-host / --allow-origin permettent de le faire tourner derrière un reverse proxy. Ouvrez http://127.0.0.1:9222/ pour voir ce qui tourne. Avec une clé Gratuit avec GitHub, un seul navigateur tourne à la fois. L’ancien script mono-identité clearcote-serve --port 9222 --fingerprint seed-123 est toujours présent dans le package Python.

Lancement direct — le build ouvert, sans SDK

Le build ouvert publié sur la page Releases est un simple binaire Chromium que vous pouvez lancer vous-même avec executable_path et des options en ligne de commande. Le build sous licence nécessite le SDK, qui détient son jeton de licence. Les arguments supplémentaires ci-dessous sont les principales valeurs par défaut que le SDK ajoute pour cette seed sous Windows (il fusionne aussi des feature flags et, derrière un proxy, désactive QUIC) :

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")

Construire votre propre image (pilotée par le SDK)

Clearcote fournit un binaire Linux x64 : il tourne donc en headless dans un conteneur. L’image a besoin des bibliothèques d’exécution du navigateur, de fontconfig et du SDK. Le navigateur utilise le bundle de polices propre à sa version plutôt que les polices du système ; comme avec l’image officielle, le build ouvert ne contient aucune police CJK (le bundle du build sous licence les inclut). Sous Linux, la persona correspond par défaut à une identité Linux native cohérente. La protection contre les fuites WebRTC est active par défaut ; les API Privacy Sandbox restent actives, comme dans 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();
Lancez le conteneur avec --shm-size=1g pour éviter les plantages liés à /dev/shm sur les pages lourdes. En Python, c’est identique (from clearcote import launch_persistent_context, options en snake_case).

Ce qui se connecte via CDP

ClientComment
Playwrightchromium.connect_over_cdp(url) / connectOverCDP(url)
Puppeteerpuppeteer.connect({ browserURL: url, defaultViewport: null })
browser-use · Crawl4AI · Stagehandpointez leur réglage CDP/endpoint vers l’URL
Tout ce qui parle CDPle DevTools Protocol brut, sur le port

Vous préférez le faire piloter par un agent IA ? Voir le serveur MCP. Curieux de savoir pourquoi un lancement direct est plus furtif ? Voir Comment fonctionne la détection.