Deploy — Docker & endpoint CDP
Rode o Clearcote como um endpoint CDP permanente e aponte para ele qualquer framework que você já usa — Playwright, Puppeteer, browser-use, Crawl4AI, Stagehand — sem mudar o código. Ele inicia o binário diretamente (sem --enable-automation), então navigator.webdriver continua false: discreto por construção.
Imagem Docker oficial
Baixe a imagem e pronto. Qualquer cliente CDP se conecta pela porta exposta.
docker run -d --rm -p 127.0.0.1:9222:9222 -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.contexts[0].new_page() # the container's own profile
page.goto("https://example.com")
print(page.title())A imagem já vem com o build aberto para Linux, com SHA-256 verificado, e com as fontes metric-clone do Windows (para que texto em alfabeto latino tenha as mesmas medidas das fontes da persona; o bundle do build aberto não tem faces CJK, então texto em chinês, japonês e coreano é renderizado sem fonte até você rodar o build licenciado, cujo bundle as inclui), e usa por padrão uma persona Linux nativa coerente. O navegador roda em modo headed num display virtual (CC_HEADLESS=1 para headless puro). Configure tudo com variáveis de ambiente:
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| Variável | Significado |
|---|---|
CC_FINGERPRINT | Seed → identidade estável. Sem essa variável, todos os contêineres apresentam a mesma identidade (seed clearcote-docker), então dê a cada contêiner o seu próprio seed. |
CC_PLATFORM | linux (padrão) | windows | macos | android. Uma persona Windows também ativa o Widevine e, no build licenciado (151 r15+), o dialeto de shader HLSL (use CC_WIDEVINE / CC_SHADER_DIALECT para substituir). |
CC_BRAND, CC_BRAND_VERSION | Chrome (padrão) | Edge | Opera | Vivaldi, e a versão que a marca declara. |
CC_ACCEPT_LANGUAGE, CC_TIMEZONE | Lista de idiomas e fuso horário IANA. |
CC_TLS_PROFILE | Deixe sem definir: o TLS segue a versão do Chrome que a persona declara. Fixe um chrome-<major> só junto com um CC_BRAND_VERSION correspondente. |
CC_HARDWARE_CONCURRENCY, CC_GPU_VENDOR, CC_GPU_RENDERER, CC_STORAGE_QUOTA | Valores individuais da persona. |
CC_HEADLESS, CC_SCREEN | 1 para headless puro; o tamanho da tela virtual (padrão 1920x1080x24). |
CC_EXTRA_ARGS | Switches extras do navegador, separados por espaço. |
CLEARCOTE_LICENSE_KEY, CC_VERSION | Rodar o build licenciado — veja abaixo. |
Declare o mesmo sistema operacional em que o contêiner roda. Parte do que uma página consegue ler vem do sistema operacional do host, abaixo do navegador, e nenhuma configuração de persona chega até lá. Nesta imagem Linux, o texto é dimensionado pelo scaler FreeType do Linux e as fontes vêm do fontconfig, não importa o que diga oCC_PLATFORM. Medido nesta imagem comCC_PLATFORM=windows: variar o tamanho da fonte em passos de 0,01 px muda a largura do texto em 66% dos passos (Chrome real no Windows: 99%), e Segoe UI e Georgia aparecem como instaladas nas medições, mas não podem ser carregadas pelo nome. O teste de fingerprint sinaliza as duas coisas. A persona Linux padrão passa. Para uma identidade Windows, rode o build para Windows ou use os navegadores hospedados, que rodam em máquinas Windows. O mesmo vale paraserve()elaunch()num servidor Linux. Detalhes: a pilha de fontes por baixo do user agent.
Build licenciado no Docker — passe uma chave, monte o cache
A imagem já vem com o build aberto embutido. Defina CLEARCOTE_LICENSE_KEY e o contêiner passa a resolver o build licenciado — o mais recente ou, no plano Pro, um específico com CC_VERSION. Chaves gratuitas sempre rodam o build mais recente, e a fixação de versão é recusada.
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=r28Sempre monte o volume de cache. Um contêiner licenciado baixa o motor na primeira inicialização; sem um volume persistente, cada contêiner faz isso de novo. Com o volume, os contêineres seguintes iniciam a partir do build em cache.
O log de inicialização mostra qual motor você recebeu, então uma chave mal configurada aparece na hora, e não na primeira requisição bloqueada:
[clearcote] engine: /opt/xdg-cache/clearcote/pro-153.0.8010.36-r28/browser/chrome (licensed)
[clearcote] licence lease acquiredExige uma imagem gerada a partir do SDK 0.26.1 ou mais recente, e 0.30.0 ou mais recente para uma chave gratuita via GitHub — o navegador licenciado espera que um contêiner gratuito mantenha a licença em dia enquanto roda, e recusa uma imagem mais antiga. Imagens publicadas mais antigas ignoram a chave e servem o build aberto sem avisar — rode docker pull teamflatearth/clearcote para atualizar. Uma execução licenciada também reserva um lease de concorrência na inicialização, então o contêiner precisa de acesso de saída à API de licenças; se o lease falhar, o contêiner encerra informando o motivo, em vez de iniciar um motor que não consegue rodar. Uma chave gratuita roda um navegador por vez, somando todos os seus contêineres — veja como os navegadores licenciados são contados.Segurança: um endpoint CDP dá controle total do navegador. Publique-o apenas em redes confiáveis — -p 127.0.0.1:9222:9222 o mantém restrito ao host. O docker/ Dockerfile é auditável — faça o build e verifique você mesmo.Endpoint CDP permanente pelo SDK — serve()
Inicie o binário você mesmo e receba uma cdp_url à qual qualquer cliente se conecta. A mesma inicialização direta e discreta da imagem, controlada pelo seu próprio processo.
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()import { serve } from "clearcote";
const srv = await serve({ fingerprint: "seed-123", platform: "windows" });
// srv.cdpUrl -> connectOverCDP / puppeteer.connect({ browserURL, defaultViewport: null })
await srv.close();No modo headless, o navegador servido recebe um display de tamanho real — o da persona, ou um sorteado entre desktops reais — e a janela é ajustada à área útil da tela antes que qualquer cliente se conecte, então toda página, aba e popup reporta uma janela que cabe na tela (SDK 0.31+). Passe windowSize: { width, height } (window_size no Python, WindowSize no .NET) para uma janela menor, ou o seu próprio --window-size em args para assumir o controle.
Um endpoint, muitas identidades — clearcote serve
No shell (pacotes de Python e Node, 0.29+), o clearcote serve roda um endpoint permanente que inicia um navegador separado para cada identidade que uma conexão pede — com seed, proxy, fuso horário e idioma tirados da URL de conexão. O mesmo seed reaproveita o navegador que já está rodando.
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 padrão, ele escuta só em localhost e recusa requisições que uma página web poderia fazer. Identidades ociosas são fechadas depois de --idle-timeout segundos, --max-browsers limita quantas rodam ao mesmo tempo (as identidades além do limite recebem HTTP 429), --data-dir mantém o perfil de cada identidade entre reinicializações, e --allow-host / --allow-origin permitem rodá-lo atrás de um proxy reverso. Abra http://127.0.0.1:9222/ para ver o que está rodando. Com uma chave Grátis com GitHub, só um navegador roda por vez. O script antigo de identidade única, clearcote-serve --port 9222 --fingerprint seed-123, continua no pacote Python.
Direto — o build aberto, sem SDK
O build aberto da página de Releases é um binário comum do Chromium, que você pode iniciar por conta própria com executable_path e switches. O build licenciado precisa do SDK, que guarda o token de licença. Os argumentos extras abaixo são os principais padrões que o SDK adiciona para este seed no Windows (ele também mescla feature flags e, atrás de um proxy, desliga o QUIC):
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")Crie a sua própria imagem (com o SDK)
O Clearcote distribui um binário Linux x64, então ele roda em modo headless num contêiner. A imagem precisa das bibliotecas de runtime do navegador, do fontconfig e do SDK. O navegador usa o bundle de fontes da própria versão, e não as fontes do sistema; assim como na imagem oficial, o build aberto não tem faces CJK (o bundle do build licenciado as inclui). No Linux, a persona usa por padrão uma identidade Linux nativa coerente. A proteção contra vazamentos do WebRTC vem ativada por padrão; as APIs do Privacy Sandbox continuam ativas, como no Google Chrome.
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"]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();Rode o contêiner com--shm-size=1gpara evitar crashes de/dev/shmem páginas pesadas. Em Python é idêntico (from clearcote import launch_persistent_context, opções emsnake_case).
O que se conecta via CDP
| Cliente | Como |
|---|---|
| Playwright | chromium.connect_over_cdp(url) / connectOverCDP(url) |
| Puppeteer | puppeteer.connect({ browserURL: url, defaultViewport: null }) |
| browser-use · Crawl4AI · Stagehand | aponte a configuração de CDP/endpoint deles para a URL |
| Qualquer coisa que fale CDP | o DevTools Protocol puro, na porta |
Prefere que um agente de IA controle o navegador? Veja o servidor MCP. Quer saber por que uma inicialização direta é mais discreta? Veja Como a detecção funciona.