Canvas bridge
Effectuez le rendu canvas et WebGL sur un vrai GPU distant, pour que les pixels relus par une page soient cohérents avec le GPU dont dispose réellement l’hôte de rendu — réglez les chaînes GPU de votre profil pour qu’elles lui correspondent. Expérimental et à activer explicitement — sans --canvas-bridge-url, Clearcote effectue tout le rendu en local, exactement comme avant.
Pourquoi il existe
Clearcote effectue le rendu canvas/WebGL sur le GPU dont dispose réellement la machine hôte, quel qu’il soit. Si un profil annonce un GPU différent de celui de l’hôte, les contrôles stricts d’anti-détection / d’altération du navigateur, qui comparent les pixels rendus au matériel annoncé, peuvent remarquer l’incohérence — impossible, en logiciel, de faire produire à un GPU les pixels exacts d’un autre GPU. Le canvas bridge supprime cette incohérence : au lieu de faire le rendu en local et de ne falsifier que la chaîne du GPU, il transfère les opérations canvas/WebGL vers un hôte distant doté du GPU que vous voulez présenter, et renvoie les vrais pixels de cet hôte. Comme il transfère les opérations (et non une bibliothèque figée d’images préenregistrées), il gère la plupart des canvas générés, pas seulement les sondes connues.
Fonctionnement
Les API de relecture — getImageData, toDataURL, readPixels et measureText — renvoient les pixels authentiques de l’hôte du bridge ; le bruit de farbling local est court-circuité sur le chemin du bridge (les pixels du bridge font foi). Le transport repose sur un WebSocket qui achemine un flux compact de messages binaires. Les pixels proviennent du GPU dont dispose le navigateur de rendu, quel qu’il soit.
clearcote (your automation host) bridge host (real GPU)
+-----------------------------+ +-------------------------+
| page: getImageData / | ops --> | render browser |
| toDataURL / readPixels | | renders on the real GPU,|
| CanvasBridgeClient <-- pixels ---------| reads back the pixels |
+-----------------------------+ +-------------------------+Ce qu’il vous faut
- Un hôte de rendu — n’importe quelle machine dont vous voulez présenter le GPU (un GPU Windows pour une persona Windows). Son GPU devient l’identité canvas que présentent vos profils : choisissez donc un matériel qui correspond à la persona que vous voulez montrer (une machine NVIDIA pour présenter du NVIDIA, et ainsi de suite). Pointez le
--backend cdpdu serveur vers un Chrome classique que vous exécutez sur cette machine (recommandé), ou utilisez--backend localavec un binaire Clearcote. - Un chemin réseau privé entre votre hôte d’automatisation et l’hôte du bridge. Le bridge parle en WebSocket non chiffré (
ws://) — faites-le toujours passer par un réseau privé ou un tunnel chiffré (Tailscale, WireGuard ou redirection de port SSH). N’exposez jamais le port du bridge sur l’internet public.
Mise en place
1. Démarrez le serveur de rendu sur l’hôte au vrai GPU. C’est un petit coordinateur Python qui pilote un navigateur headless et rejoue les opérations transférées sur son vrai canvas, si bien que les pixels qu’il renvoie sont exactement ceux que produit ce GPU. Le vrai GPU de l’hôte de rendu devient l’identité canvas/WebGL. Avec --backend cdp, il affiche au démarrage la chaîne renderer du GPU de rendu (render GPU='ANGLE (…)') — notez-la pour l’étape 3. Avec --backend local, relevez plutôt les chaînes dans un Chrome classique sur la même machine.
pip install playwright # one-time (no browser download needed for CDP)
# a regular Chrome on the GPU host, started with --remote-debugging-port=9222
# --user-data-dir=<a separate folder> (Chrome ignores the port on its default profile);
# its CDP URL is webSocketDebuggerUrl from http://127.0.0.1:9222/json/version
python tools/canvas-bridge-server/server.py \
--backend cdp \
--cdp-url ws://127.0.0.1:9222/devtools/browser/... \
--port 8443
# Or let the server launch a Clearcote binary itself:
# python tools/canvas-bridge-server/server.py \
# --backend local \
# --chrome /path/to/clearcote/chrome.exe \
# --port 84432. Faites-le passer par un tunnel. ws:// n’est pas chiffré — placez les deux hôtes sur le même réseau Tailscale/WireGuard, ou redirigez le port via SSH. Par défaut, le serveur n’écoute que sur localhost : avec Tailscale/WireGuard, démarrez-le donc avec --host <that interface's IP> ; la voie SSH ci-dessous fonctionne telle quelle :
ssh -N -L 8443:localhost:8443 user@bridge-host
# the bridge is now reachable at ws://127.0.0.1:84433. Lancez le client (votre Clearcote d’automatisation) en le pointant vers le bridge, avec les chaînes du GPU de rendu — le renderer exactement tel que le serveur l’a affiché, et le vendor sous la forme Google Inc. (<first name in the renderer>), par exemple Google Inc. (Intel). Le bridge fait correspondre les pixels au GPU de rendu, et ces options en font autant pour les chaînes rapportées. Sans elles, le nom de GPU de la persona et les pixels issus du bridge se contredisent :
--canvas-bridge-url=ws://127.0.0.1:8443 \
--no-sandbox \
--fingerprint=<seed> \
--fingerprint-gpu-vendor='Google Inc. (Intel)' \
--fingerprint-gpu-renderer='ANGLE (Intel, Intel(R) UHD Graphics ... D3D11)'| Flag | Signification |
|---|---|
| --canvas-bridge-url | Endpoint du bridge ws://host:port. Obligatoire pour activer le bridge. |
| --canvas-bridge-auth | Identifiants HTTP Basic user:secret facultatifs, pour un déploiement qui place une authentification devant le serveur. Le serveur de référence ne les vérifie pas : comptez donc sur le réseau privé ou le tunnel pour le contrôle d’accès. |
| --no-sandbox | Obligatoire — le client ouvre le socket du bridge depuis le processus renderer, ce que la sandbox bloque. |
| --fingerprint | La seed de votre persona. |
| --fingerprint-gpu-vendor / --fingerprint-gpu-renderer | Les chaînes du GPU de rendu : le renderer exactement tel que le serveur l’a affiché, le vendor sous la forme Google Inc. (<first name in the renderer>). |
| --canvas-bridge-mode | Politique par origine : off, all (par défaut), allow ou deny. |
| --canvas-bridge-allow / --canvas-bridge-deny | Listes d’eTLD+1 séparées par des virgules, utilisées par mode=allow ou mode=deny. |
| --canvas-bridge-fallback | Comportement sur un cache miss à froid : block (par défaut) attend le bridge ; local sert des pixels locaux au lieu de rester bloqué. |
Depuis le SDK
Le SDK (Node, Python et .NET ; version actuelle 0.31.1) expose une option à part entière, canvasBridge / canvas_bridge / CanvasBridge. Définir une URL de bridge émet les switches et ajoute automatiquement --no-sandbox. Pour la même politique de liste d’autorisation dans un script de lancement complet, consultez Exemples.
const browser = await clearcote.launch({
fingerprint: "user-1",
gpuVendor: "Google Inc. (Intel)", // "Google Inc. (<first name in the renderer>)"
gpuRenderer: "ANGLE (Intel, Intel(R) UHD Graphics ... D3D11)", // exactly as the server printed it
canvasBridge: {
url: "ws://127.0.0.1:8443",
auth: "user:secret",
mode: "allow",
allow: ["example.com"],
fallback: "local",
},
});Vérifier qu’il fonctionne
- Le journal du client affiche
canvas-bridge: connected to <host>:<port>quand la connexion réussit (lancez avec--enable-logging=stderr --v=1pour le voir). - Chargez une page qui calcule le hash d’une surface canvas/WebGL — bridge connecté, les hashes correspondent au GPU de l’hôte du bridge, pas à celui de votre hôte d’automatisation. Vérification rapide : exécutez le même
canvas.toDataURL()avec et sans le bridge ; les résultats diffèrent. - Si le bridge est injoignable, Clearcote journalise un avertissement et se rabat sur le rendu local — un bridge mal configuré se dégrade proprement, il ne casse jamais la page.
Mises en garde & limites
- Identité canvas = l’hôte du bridge, pas la seed. Tous les profils qui partagent un même hôte de bridge partagent le hash canvas/WebGL de cet hôte : on peut donc les relier entre eux par ce hash. Pour de nombreuses identités impossibles à relier, utilisez un hôte de bridge (GPU) par groupe d’identités.
- Latence. Une relecture de pixels qui rate le cache du bridge est un aller-retour réseau bloquant (délai de 5 s, puis repli local), sauf si
fallbackvautlocal; le moteur précharge après chaque dessin, si bien que les lectures répétées de pixels d’un canvas inchangé n’attendent pas. Chaque appel àmeasureTextreste un aller-retour. Gardez l’hôte du bridge sur le même LAN/datacenter ; évitez le bridge pour les pages lourdes en canvas et sensibles à la latence. - Les textures WebGL procédurales passent par le bridge. Les sources de textures image, canvas 2D, vidéo,
ImageBitmapet 3D basculent en rendu local pour ce canvas : elles restent correctes, mais hors bridge. --no-sandboxest obligatoire côté client, et le transport se fait en clair — passez toujours par un tunnel ; n’exposez jamais publiquement le port du bridge.
Expérimental. Présent dans le build ouvert depuis v0.1.0-pre.12, et dans le build sous licence. Pour la référence canonique (avec le tableau de dépannage complet), consultez le guide du canvas bridge sur GitHub. La plupart des configurations n’ont pas besoin du bridge — consultez Flags d’empreinte pour les contrôles standard au niveau du moteur.