Saltar al contenido

Despliegue: Docker & endpoint CDP

Ejecuta Clearcote como un endpoint CDP permanente y apunta hacia él cualquier framework que ya uses —Playwright, Puppeteer, browser-use, Crawl4AI, Stagehand— sin cambiar el código. Lanza el binario directamente (sin --enable-automation), así que navigator.webdriver sigue en false: sigiloso por construcción.

Imagen oficial de Docker

Descarga la imagen y listo. Cualquier cliente CDP se conecta a través del puerto expuesto.

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

La imagen trae integrados el build abierto para Linux, verificado con SHA-256, y las fuentes con métricas clonadas de las de Windows (para que el texto latino mida como las fuentes de la persona; el paquete de fuentes del build abierto no incluye tipografías CJK, así que el texto en chino, japonés y coreano se renderiza sin fuente hasta que ejecutes el build con licencia, cuyo paquete sí las incluye), y usa por defecto una persona coherente de Linux nativo. El navegador se ejecuta en modo headed sobre una pantalla virtual (CC_HEADLESS=1 para headless puro). Se configura por completo con variables de entorno:

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
VariableSignificado
CC_FINGERPRINTSeed → identidad estable. Sin ella, todos los contenedores presentan la misma identidad (seed clearcote-docker), así que dale a cada contenedor la suya.
CC_PLATFORMlinux (por defecto) | windows | macos | android. Una persona de Windows también activa Widevine y, en el build con licencia (151 r15+), el dialecto de shaders HLSL (CC_WIDEVINE / CC_SHADER_DIALECT para cambiarlo).
CC_BRAND, CC_BRAND_VERSIONChrome (por defecto) | Edge | Opera | Vivaldi, y la versión que declara.
CC_ACCEPT_LANGUAGE, CC_TIMEZONELista de idiomas y zona horaria IANA.
CC_TLS_PROFILEDéjala sin definir: el TLS sigue a la versión de Chrome que declara la persona. Fija un chrome-<major> solo junto con un CC_BRAND_VERSION que coincida.
CC_HARDWARE_CONCURRENCY, CC_GPU_VENDOR, CC_GPU_RENDERER, CC_STORAGE_QUOTAValores individuales de la persona.
CC_HEADLESS, CC_SCREEN1 para headless puro; el tamaño de la pantalla virtual (por defecto 1920x1080x24).
CC_EXTRA_ARGSSwitches adicionales del navegador, separados por espacios.
CLEARCOTE_LICENSE_KEY, CC_VERSIONEjecutan el build con licencia; ver más abajo.
Declara el sistema operativo en el que corre el contenedor. Parte de lo que una página puede leer viene del sistema operativo del host, por debajo del navegador, y ningún ajuste de la persona llega hasta ahí. En esta imagen de Linux, el tamaño del texto lo calcula el escalador FreeType de Linux y las fuentes vienen de fontconfig, diga lo que diga CC_PLATFORM. Medido en esta imagen con CC_PLATFORM=windows: variar el tamaño de fuente en pasos de 0.01 px cambia el ancho del texto en el 66% de los pasos (Chrome real en Windows: 99%), y Segoe UI y Georgia aparecen como instaladas al medirlas, pero no se pueden cargar por nombre. El test de huella digital señala ambas cosas. La persona de Linux por defecto pasa el test. Para una identidad de Windows, ejecuta el build para Windows o usa los navegadores alojados, que corren en máquinas Windows. Lo mismo aplica a serve() y launch() en un servidor Linux. Detalles: el stack de fuentes por debajo del user agent.

Build con licencia en Docker: pasa una clave y monta la caché

La imagen trae integrado el build abierto. Define CLEARCOTE_LICENSE_KEY y el contenedor resuelve en su lugar el build con licencia: el más reciente o, en el plan Pro, uno concreto con CC_VERSION. Las claves gratuitas siempre ejecutan el build más reciente y se rechaza cualquier fijación de versión.

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

Monta siempre el volumen de caché. Un contenedor con licencia descarga el motor en el primer arranque; sin un volumen persistente, cada contenedor lo vuelve a hacer. Con el volumen, los contenedores siguientes arrancan desde el build en caché.

El log de arranque te dice qué motor obtuviste, así que una clave mal configurada se nota de inmediato y no en la primera solicitud bloqueada:

text
[clearcote] engine: /opt/xdg-cache/clearcote/pro-153.0.8010.36-r28/browser/chrome (licensed)
[clearcote] licence lease acquired
Requiere una imagen construida con el SDK 0.26.1 o posterior, y 0.30.0 o posterior para una clave gratuita de GitHub: el navegador con licencia espera que un contenedor gratuito mantenga su licencia al día mientras se ejecuta, y rechaza una imagen más antigua. Las imágenes publicadas más antiguas ignoran la clave y sirven el build abierto sin avisar; ejecuta docker pull teamflatearth/clearcote para actualizarla. Una ejecución con licencia también obtiene un lease de concurrencia al arrancar, así que el contenedor necesita acceso saliente a la API de licencias; si el lease falla, el contenedor termina indicando el motivo en lugar de iniciar un motor que no puede ejecutarse. Una clave gratuita ejecuta un navegador a la vez entre todos tus contenedores; consulta cómo se cuentan los navegadores con licencia.
Seguridad: un endpoint CDP da control total del navegador. Publícalo solo en redes de confianza; -p 127.0.0.1:9222:9222 lo mantiene local al host. El docker/ Dockerfile se puede auditar: recompílalo y verifícalo tú mismo.

Endpoint CDP permanente desde el SDK: serve()

Lanza el binario tú mismo y obtén una cdp_url a la que se conecta cualquier cliente. Es el mismo lanzamiento directo y sigiloso que el de la imagen, controlado desde tu propio proceso.

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 modo headless, el navegador servido recibe una pantalla de tamaño real —la de la persona, o una tomada de equipos de escritorio reales— y su ventana se ajusta al área de trabajo antes de que se conecte ningún cliente, así que cada página, pestaña y popup reporta una ventana que cabe en su pantalla (SDK 0.31+). Pasa windowSize: { width, height } (window_size en Python, WindowSize en .NET) si quieres una ventana más pequeña, o tu propio --window-size en args para tomar el control.

Un endpoint, muchas identidades: clearcote serve

Desde la shell (paquetes de Python y Node, 0.29+), clearcote serve ejecuta un endpoint permanente que inicia un navegador distinto para cada identidad que pide una conexión, con su seed, proxy, zona horaria e idioma tomados de la URL de conexión. Un mismo seed reutiliza el navegador que ya está en ejecución.

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)

Por defecto escucha en localhost y rechaza las solicitudes que podría hacer una página web. Las identidades inactivas se cierran tras --idle-timeout segundos, --max-browsers limita cuántas se ejecutan a la vez (las identidades adicionales reciben HTTP 429), --data-dir conserva el perfil de cada identidad entre reinicios, y --allow-host / --allow-origin permiten ejecutarlo detrás de un reverse proxy. Abre http://127.0.0.1:9222/ para ver qué está en ejecución. Con una clave Gratis con GitHub, solo se ejecuta un navegador a la vez. El script anterior de identidad única, clearcote-serve --port 9222 --fingerprint seed-123, sigue incluido en el paquete de Python.

Directo: el build abierto, sin SDK

El build abierto de la página de Releases es un binario de Chromium normal que puedes lanzar tú mismo con executable_path y switches. El build con licencia necesita el SDK, que es el que tiene su token de licencia. Los argumentos adicionales de abajo son los principales valores por defecto que el SDK agrega para este seed en Windows (además, combina feature flags y, detrás de un proxy, desactiva 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")

Construye tu propia imagen (con el SDK)

Clearcote distribuye un binario para Linux x64, así que se ejecuta en modo headless dentro de un contenedor. La imagen necesita las bibliotecas de runtime del navegador, fontconfig y el SDK. El navegador usa el paquete de fuentes de su propia versión en lugar de las fuentes del sistema; igual que en la imagen oficial, el build abierto no incluye tipografías CJK (el paquete del build con licencia sí las incluye). En Linux, la persona usa por defecto una identidad coherente de Linux nativo. La protección contra fugas de WebRTC está activada por defecto; las APIs de Privacy Sandbox siguen activadas, como en 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();
Ejecuta el contenedor con --shm-size=1g para evitar fallos de /dev/shm en páginas pesadas. En Python es idéntico (from clearcote import launch_persistent_context, opciones en snake_case).

Qué se conecta por CDP

ClienteCómo
Playwrightchromium.connect_over_cdp(url) / connectOverCDP(url)
Puppeteerpuppeteer.connect({ browserURL: url, defaultViewport: null })
browser-use · Crawl4AI · Stagehandapunta su ajuste de CDP/endpoint a la URL
Cualquier cosa que hable CDPel DevTools Protocol en bruto, en ese puerto

¿Prefieres que lo maneje un agente de IA? Consulta el servidor MCP. ¿Te preguntas por qué un lanzamiento directo es más sigiloso? Consulta Cómo funciona la detección.