Playwright & Puppeteer
Clearcote, c’est simplement Chromium : il remplace directement le navigateur dans les outils d’automatisation que vous utilisez déjà.
La méthode SDK (recommandée)
Le package clearcote (npm, PyPI et NuGet) transforme les options d’identité en arguments nommés et renvoie des objets Playwright ordinaires. À la première utilisation, il télécharge le navigateur et en vérifie le SHA-256 — le build ouvert sans clé de licence, le dernier build sous licence avec une clé (voir Installation) — puis applique les valeurs par défaut décrites plus bas.
# pip install clearcote
from clearcote import launch
browser = launch(fingerprint="seed-123", platform="windows", brand="Chrome")
page = browser.new_page()
page.goto("https://example.com")
browser.close()SDK actuel : 0.45.0. Depuis la 0.23, launch() en Python et en Node s’exécute sur un vrai répertoire de profil jetable (supprimé à la fermeture) au lieu de la navigation privée : la surface liée au profil correspond ainsi à celle d’un vrai Chrome, et widevine: true peut charger le module DRM. Il renvoie un handle qui se comporte comme un navigateur : newPage() fonctionne comme d’habitude, mais newContext() renvoie ce même contexte de profil plutôt qu’un contexte isolé. Pour cloisonner les cookies, lancez des navigateurs distincts ; passez ephemeralProfile: false / ephemeral_profile=False pour retrouver l’ancien Browser en navigation privée, ou userDataDir / user_data_dir pour conserver le profil.
L’API asynchrone (clearcote.async_api) accepte les mêmes options de persona et de proxy dans une boucle asyncio et renvoie des objets Playwright asynchrones ; son launch() est en navigation privée, utilisez donc launch_persistent_context() pour un profil (et pour widevine=True). Le SDK .NET couvre LaunchEphemeralProfileAsync (recommandé — le LaunchAsync de .NET est en navigation privée et ne sait pas ajuster une fenêtre headless), LaunchPersistentContextAsync, ServeAsync, le téléchargement vérifié, les licences, Geoip et la simulation d’entrées humaines (des appels explicites HumanClickAsync / HumanTypeAsync / HumanSelectOptionAsync plutôt qu’un flag de lancement). Les profils enregistrés, profile: "auto", les vérifications de cohérence du rendu, Widevine et les helpers d’agent sont pour l’instant réservés à Python & Node. Pour des workflows complets à copier-coller, voir Exemples.
Puppeteer et autres clients CDP (serve)
Le SDK n’a pas de lanceur Puppeteer. À la place, serve() démarre Clearcote avec les paramètres de lancement du SDK (persona, proxy, valeurs par défaut) et un endpoint CDP en loopback, auquel n’importe quel client CDP se connecte — Puppeteer, le connectOverCDP de Playwright, browser-use, Crawl4AI, Stagehand. Cela fonctionne avec le build sous licence, et rien n’ajoute --enable-automation. humanize agit côté Playwright : il ne s’applique donc pas à un client connecté de cette façon.
import { serve } from "clearcote";
import puppeteer from "puppeteer-core";
const srv = await serve({ fingerprint: "seed-123", platform: "windows" });
const browser = await puppeteer.connect({ browserURL: srv.cdpUrl, defaultViewport: null });
const page = await browser.newPage();
await page.goto("https://example.com");
await browser.disconnect();
await srv.close();En headless, serve() donne au navigateur un écran de taille réelle et ajuste sa fenêtre à la zone de travail avant que le moindre client ne se connecte (0.31+) ; passez windowSize / window_size pour une fenêtre plus petite. Depuis un shell, clearcote serve fait la même chose sous forme de service permanent — et peut attribuer à chaque connexion son propre navigateur, avec l’identité, le proxy, le fuseau horaire et la langue tirés de l’URL de connexion. Voir Déploiement.
Piloter directement le binaire (build ouvert)
Vous pouvez aussi pointer votre propre lanceur vers le build ouvert avec executablePath (Node) ou executable_path (Python) et passer les options d’identité dans args. Le build sous licence ne démarre pas de cette façon — il a besoin du jeton de licence que le SDK récupère ; utilisez donc launch() ou serve() ci-dessus. Retirez --enable-automation comme le fait le SDK (Puppeteer et les anciennes versions de Playwright l’ajoutent ; il fait passer Chromium en mode automatisation). Aucune des valeurs par défaut du SDK (langue, politique WebRTC, géométrie de la fenêtre) ne s’applique dans ce cas.
from playwright.sync_api import sync_playwright
with sync_playwright() as p:
browser = p.chromium.launch(
executable_path=r"C:\clearcote\chrome.exe",
headless=False,
ignore_default_args=["--enable-automation"],
args=[
"--fingerprint=seed-123",
"--fingerprint-platform=windows",
"--timezone=America/New_York",
],
)
page = browser.new_page()
page.goto("https://abrahamjuliot.github.io/creepjs/")
browser.close()Résoudre ou précharger le binaire vérifié
Le SDK résout le navigateur dans cet ordre : un executablePath / executable_path explicite, puis CLEARCOTE_BINARY, puis la version que vous avez demandée (ou CLEARCOTE_BROWSER_VERSION), puis le build sous licence si une clé de licence est trouvée (l’option licenseKey, CLEARCOTE_LICENSE_KEY ou ~/.clearcote/license.key), et enfin le build ouvert épinglé dans cette version du SDK. Si vous fournissez un chemin, le SDK vérifie avant le lancement qu’aucun fichier n’y manque ni n’est tronqué. Appelez download / executable_path pour préremplir le cache sans lancer le navigateur, utiliser un répertoire de cache personnalisé ou opter, à l’exécution, pour le build ouvert le plus récent publié sur GitHub.
from clearcote import download, launch
chrome = download(cache_dir=r"C:\clearcote-cache", auto_update=True)
browser = launch(executable_path=chrome, fingerprint="seed-123")Le mode épinglé vérifie les valeurs SHA-256 intégrées au SDK. autoUpdate / auto_update est à activer explicitement et vérifie le manifeste des sommes de contrôle de la version ; si gpg est disponible, il vérifie aussi le manifeste signé par rapport à l’empreinte épinglée de la clé de signature Clearcote. Il ne s’applique qu’au build ouvert : avec une clé de licence, download() récupère à la place le build sous licence actuel (choisissez-en un avec version ou releaseChannel — voir choisir un build). En .NET, DownloadAsync ne récupère que le build ouvert ; préchargez le build sous licence avec ExecutablePathAsync(new LaunchOptions { LicenseKey = … }).
Cohérent par défaut (sans flag supplémentaire)
Quelles que soient vos options de lancement, le moteur maintient les surfaces secondaires en accord avec la persona choisie — pour une persona Windows, avec ce que renvoie un vrai Chrome sur un PC de bureau Windows. La plateforme de la persona correspond par défaut à l’OS de votre hôte : sur un hôte Linux, ces surfaces suivent donc une persona Linux, sauf si vous passez platform. Les limites WebGL getParameter (WebGL1 + WebGL2) renvoient les valeurs de la persona, plafonnées à ce que le GPU de cette machine peut réellement fournir, et UNMASKED_RENDERER / UNMASKED_VENDOR sont constants sur toute la session (le même GPU sur tous les sites, qui suit la persona). Pour une persona Windows, navigator.getBattery() renvoie un PC de bureau sur secteur, navigator.connection une connexion résidentielle, et AudioContext la fréquence d’échantillonnage et la latence Windows-WASAPI correspondantes. getScreenDetails() renvoie un seul écran, et @media (pointer: fine) / (hover: hover) correspondent à un PC de bureau avec une souris.
Vérifié sur la 153 r26, en mode headed sous Windows (septembre 2026) : BrowserScan ne signale aucun bot et CreepJS affiche un score stealth de 0 %. Derrière un proxy, ajoutez geoip pour que le fuseau horaire et WebRTC correspondent à la sortie du proxy.
Valeurs par défaut cohérentes (modifiables)
Le SDK applique quelques valeurs par défaut pensées pour la furtivité, afin de ne pas laisser passer les indices évidents :
- En mode headed, aucun viewport n’est émulé par défaut (
viewport: null/no_viewport=True), pour quewindow.innerWidthsuive la vraie fenêtre de l’OS — un viewport émulé de 1280×720 posé sur une vraie fenêtre trahit une fenêtre impossible. Passez unviewportexplicite pour changer ce comportement. Sur un serveur Linux sans gestionnaire de fenêtres (Xvfb, votre propre conteneur), où--start-maximizedn’a aucun effet, une fenêtre headed est ajustée à la zone de travail de l’écran avant la première page, comme une fenêtre de bureau maximisée (SDK 0.42.0). - Les lancements headless reçoivent un affichage réaliste et une fenêtre ajustée à celui-ci avant la première page : l’écran de la persona ou, sans persona, une taille réelle d’écran de bureau. Depuis le SDK 0.42.0, c’est le cas sur toutes les plateformes, même lorsqu’une persona ne prend pas effet, si bien qu’une page ne voit jamais la surface headless brute de 800×600 du moteur. Une option
viewportouscreende votre choix désactive ce comportement, et avec votre propre--screen-info, c’est vous qui définissez l’affichage. Votre propre--window-size,--window-positionou--start-maximizedconserve l’affichage et ne saute que l’ajustement ; dansserve(), un--window-positionseul conserve aussi l’affichage, et seul un switch de taille ou--screen-infovous laisse entièrement la main sur la géométrie. - Une seule surface WebGL sous Linux : sur un hôte Linux, le WebGL d’une persona Linux est rendu par Mesa via EGL, en headless comme en headed (SDK 0.42.0 ; l’hôte a besoin de
libegl1), si bien qu’une page voit dans les deux cas la même chaîne renderer, la même liste d’extensions et les mêmes limites, sous la forme OpenGL ES que rapportent la plupart des vraies machines Linux. Sans EGL, un lancement headed utilise le GL de bureau de Mesa, et une persona Windows est rendue via SwiftShader. Votre propre--use-angleou--use-gldansargsl’emporte, et un lancement headless reçoit tout de même--ignore-gpu-blocklisten plus, pour que WebGL continue de fonctionner. - Le thème clair ou sombre vient de la persona sur le build sous licence à partir de la 154 r32 : les contextes que crée le SDK laissent désactivée l’émulation du thème de couleurs de Playwright (SDK 0.41.0+), là où Playwright imposerait sinon le thème clair. Passez
colorScheme/color_schemepour en émuler un malgré tout. - La persona reste hors de la ligne de commande sur le build sous licence à partir de la 154 r32 : la seed, les surcharges de persona et les identifiants du proxy parviennent au navigateur par son environnement, et non par son entrée dans la liste des processus (SDK 0.41.0+ ;
personaEnv: falsepour conserver la ligne de commande). Voir Options de lancement. - WebRTC utilise par défaut
disable_non_proxied_udp: aucun trafic UDP ne sort en dehors du proxy et l’adresse de votre machine reste privée. Seule votre propre--webrtc-ip-handling-policydansargsprend le dessus — ainsi que, sur le build ouvert,webrtcIp/geoip, qui laissent de nouveau l’UDP WebRTC sortir par votre propre connexion (le build sous licence bloque l’UDP WebRTC dans tous les cas). Avec cette politique et sanswebrtcIp, une page n’obtient aucun candidat ICE — derrière un proxy, passezgeoip(ouwebrtcIp) pour que WebRTC renvoie l’adresse du proxy, ousocks5Udppour faire passer du vrai UDP par un proxy SOCKS5. - Derrière un proxy, QUIC / HTTP-3 est désactivé, comme pour un vrai Chrome derrière un proxy — aucun trafic UDP n’est donc tenté en dehors de celui-ci.
- Par défaut, la plateforme de la persona est celle de votre OS hôte, et la marque est Google Chrome. Sans
timezonenigeoip, le fuseau horaire suit la langue (en-US→ New York). - Les identifiants du proxy sont transmis au navigateur, et non à Playwright, là où le moteur le permet : toujours en SOCKS5 (Playwright ne sait pas du tout s’authentifier en SOCKS5), en HTTP(S) sur la 151 r19+ pour que le cache des pages reste actif (Python & Node). Voir ci-dessous.
humanizeeffectue une vérification préalable d’actionnabilité avant chaque clic de confiance (visible / activé / stable + un contrôle de recouvrement viaelementFromPoint) et se rabat sur le clic natif : un clic de confiance ne se déclenche ainsi jamais sous un overlay ni en pleine animation.
Astuce : dérivez la seed de votre propre identifiant de compte/tenant pour que chaque identité soit reproductible — même seed, même empreinte de navigateur, à chaque fois. La liste complète des options se trouve dans Flags d’empreinte.