Fingerprint-Flags
Die Identität steuern Sie über Chromium-Kommandozeilen-Switches. Das SDK setzt sie anhand benannter Optionen; mit dem offenen Build können Sie sie auch als args an Ihren eigenen Launcher übergeben.
Die meisten Switches gibt es in beiden Builds. Einige sind dem lizenzierten Build vorbehalten (Kostenlos mit GitHub oder Pro) – die Switch-Liste unten kennzeichnet sie mit der Engine-Revision, in der sie hinzugekommen sind. Ohne Lizenzschlüssel startet das SDK den offenen Build, in dem diese Optionen wirkungslos sind.
Das Seed-Modell
Alles hängt an --fingerprint=<seed>. Aus dem Seed (einer Ganzzahl oder einem beliebigen String) wird die Persona deterministisch abgeleitet – und er verrauscht die beiden Render-Schnittstellen, die unten unter Wo Farbling greift aufgeführt sind:
- Gleicher Seed ⇒ gleiche Identität über alle Starts hinweg – ein wiederkehrender Besucher.
- Neuer Seed ⇒ eine frische, plausible Identität.
- Das Canvas- und WebGL-Rauschen wird pro Website abgeleitet (angelehnt an Braves Farbling), daher unterscheiden sich diese Hashes von Domain zu Domain. Die Persona selbst – GPU, Bildschirm, Hardware, Schriften – ist überall dieselbe, wie bei einem echten Rechner auch.
Sie hätten lieber die Identität eines echten Rechners statt der synthetischen, aus dem Seed abgeleiteten? Erfassen Sie mit dem Collector ein Spender-Chrome und importieren Sie es über --fingerprint-profile=<gzip+base64 JSON> (oder die SDK-Option fingerprint_profile / fingerprintProfile, die das gzip+base64 für Sie übernimmt). Felder, die im Profil vorhanden sind, überschreiben die Persona; fehlende Felder fallen auf die Persona des --fingerprint-Seeds zurück oder, ohne Seed, auf die Standardwerte des Browsers. Beide Builds lesen importierte Profile; im lizenzierten Build greifen sie ab 151 r19 vollständig. Wie Sie ein erfasstes Profil über das SDK importieren, zeigt die Playwright-Anleitung.
Wo Farbling greift – und wo bewusst nicht
Wer eine Schnittstelle verrauscht, gewinnt Unverkettbarkeit und bezahlt mit Kohärenz – und dieser Tausch lohnt sich nicht überall. Clearcote verrauscht die beiden Schnittstellen, bei denen das Rauschen der gewöhnlichen Hardware-Streuung am nächsten kommt, und lässt den Rest unverrauscht – denn dort fällt ein verrauschter Wert stärker auf als ein geteilter. Unverrauscht heißt allerdings nicht unangetastet: Einige Werte werden trotzdem komplett durch Persona-Werte ersetzt; die Tabelle und der Hinweis darunter führen das aus. Manche Prüftools schlagen dennoch auf das Rauschen selbst an; wenn das eine Rolle spielt, schaltet fingerprintNoise: false es ab und behält die Identität bei (siehe Wie Erkennung funktioniert).
| Schnittstelle | Rauschen pro Seed | Warum |
|---|---|---|
Canvas 2D – toDataURL, getImageData und die anderen Wege, auf denen eine Seite ein Canvas exportieren kann (im lizenzierten Build liefern ab 152 r21 alle Exportpfade dasselbe Ergebnis) | Ja | Der Readback unterscheidet sich schon zwischen echten Rechnern je nach GPU, Treiber und Rasterisierungspfad; eine kleine Störung liegt daher innerhalb der natürlichen Streuung. |
WebGL – readPixels, toDataURL | Ja | Gleiche Begründung. Mit disableGpuFingerprint liefert readPixels die unverfälschten Pixel, die Exporte eines WebGL-Canvas (toDataURL() und Ähnliches) sind aber weiterhin verrauscht – kombinieren Sie es mit fingerprintNoise: false, damit jeder Lesezugriff auf das Canvas dasselbe ergibt. |
Audio – Samplewerte des AudioContext | Nein – bewusst | Die Ausgabe von Web Audio ist für eine gegebene Pipeline deterministisch. Sie zu verrauschen hieße entweder eine Samplerate außerhalb der Spezifikation (44099.99 statt 44100) oder Samples, die kein Standard-Renderer erzeugt – beides Werte, die ein echter Browser nicht liefern kann, und damit ein deutlicheres Indiz als zwei Profile mit demselben Audio-Hash. Die gemeldeten Skalare sind eine andere Sache und folgen sehr wohl der Persona – siehe unten. |
| Client-Rects & Textmetriken | Nein – bewusst | Chrome quantisiert das Layout auf ein natives 1/512-px-Raster, daher ist jedes unverfälschte Rect ein exaktes Vielfaches von 0.001953125. Ein nachträglich angewendeter Skalierungsfaktor schiebt jedes Rect aus diesem Raster heraus, und Geometrie außerhalb des Rasters lässt sich mit einer einzigen Messung nachweisen, egal wie klein der Faktor ist. |
| WebGPU – Adapter und Limits | Nein | Folgt der GPU der Persona statt des Seeds und stimmt so weiterhin mit dem überein, was WebGL meldet. Nennen zwei GPU-APIs auf einer Seite verschiedene Hersteller, lässt sich das mit einem einzigen Aufruf auslesen. |
Die praktische Folge für die Arbeit mit mehreren Accounts: Canvas und WebGL trennen Ihre Identitäten, gerendertes Audio und Client-Rects nicht. Das sind Eigenschaften der Maschine darunter – derselbe Host rendert dieselbe Audio-Pipeline und dasselbe Layout-Raster, egal welches Profil geladen ist, genau wie bei zwei verschiedenen Menschen auf identischer Hardware. Korreliert eine Zielseite speziell über diese Werte, sind getrennte Rechner die Antwort, nicht ein anderer Switch.
Eine Ausnahme sollten Sie kennen: Die drei Skalare des AudioContext folgen sehr wohl der Persona. sampleRate, baseLatency und outputLatency kommen aus der Persona, sobald eine aktiv ist – über einen --fingerprint-Seed oder ein importiertes Profil –, sodass sie zwischen Identitäten variieren, statt das Audio-Backend des Hosts preiszugeben. Ist keins von beiden gesetzt, werden alle drei unverändert vom echten Rechner durchgereicht. Eine Rate, die die Seite ausdrücklich anfordert, wird nach wie vor respektiert, und outputLatency läuft weiterhin durch Chromes eigenen, berechtigungsabhängigen Quantisierer. Ab 153 r26 folgt baseLatency außerdem der Render-Größe, die die Seite anfordert, und ein Kontext, der noch nicht mit dem Rendern begonnen hat, meldet dieselbe Latenz wie ein reguläres Chrome.
Kohärente sekundäre Schnittstellen
Über die verrauschten Signale hinaus sorgt die Engine dafür, dass die sekundären Schnittstellen der Persona mit einem echten Chrome auf der Plattform der Persona übereinstimmen. Standardmäßig setzt das SDK die Plattform auf das Betriebssystem Ihres Hosts; die Windows-spezifischen Werte unten gelten für eine Windows-Persona.
- WebGL-Limits (WebGL1 + WebGL2) folgen der GPU der Persona, soweit dieser Rechner sie tatsächlich einhalten kann. Ein Limit wird nie höher gemeldet, als der echte Treiber durchsetzt; auf einem Software-Renderer liegen einige Werte daher unter denen der genannten GPU.
- UNMASKED_RENDERER / UNMASKED_VENDOR bleiben für die ganze Session konstant – eine GPU auf jeder Website, passend zur Persona, statt eines verräterischen Werts pro Origin.
- navigator.getBattery() meldet einen Desktop am Stromnetz (lädt, Level 1.0, keine Entladung), navigator.connection das Profil eines Privatanschlusses (effectiveType 4g, gerundete rtt/downlink, saveData aus).
- navigator.keyboard.getLayoutMap() liefert ein US-QWERTY-Layout, und unter einer Windows-Persona meldet AudioContext die Samplerate und Latenz des Windows-Audio-Stacks.
- window.getScreenDetails() meldet einen einzigen, kohärenten Monitor;
@media (pointer: fine)/(hover: hover)entsprechen einem Desktop mit Maus. - URLs – unter einer Windows-Persona liefert
new URL("C:/").protocolden Wertfile:, und ab 153 r26 führt jeder Weg, auf dem eine Seite eine URL bauen kann, zum selben Ergebnis. navigator.share / canShare sind passend zum Windows-UA verfügbar. - WebGPU – Adapter-Info sowie Limits/Features von
navigator.gpufolgen derselben GPU wie WebGL (im lizenzierten Build eingeschränkt auf das, was der Host leisten kann). - Locale –
Accept-Language,navigator.language, die vollständige Listenavigator.languagesundIntl(Main-Thread + Worker) stammen alle aus einer Liste (acceptLanguageodergeoip). Das SDK setzt--accept-langund--langfür Sie; wenn Sie die Switches direkt übergeben, setzen Sie beide. - Sprachausgabe –
speechSynthesisliefert die Stimmen der Persona, einschließlich der Google-Netzwerkstimmen, die ein Chrome dieser Version auflistet (153 r27).fingerprintVoices: falsebehält stattdessen die eigenen Stimmen des Rechners bei (152 r22). - Hardware – der Messwert zur Prozessorgeschwindigkeit (
navigator.cpuPerformance) folgt der Persona statt des echten Prozessors (152 r20), und die Speicherobergrenze für Skripte (performance.memory.jsHeapSizeLimit) folgt dem Arbeitsspeicher, den die Persona angibt (153 r26). - Codecs & Geräte –
MediaCapabilities.decodingInfo()meldet eine Codec-Matrix der Persona,enumerateDevices()einen Satz Mediengeräte der Persona (IDs stabil pro Seed, leere Labels vor der Berechtigung). - UA-CH High-Entropy –
bitness=64 /wow64=false /model; unter einer Linux-Persona istplatformVersionleer, so wie es echtes Chrome unter Linux meldet (153 r26).navigator.storage.estimate()meldet ein realistisches Speicherkontingent auf der Festplatte, wenn SiestorageQuotasetzen.
Experimentell: Canvas-Bridge mit echter GPU
Optional leiten Sie Canvas-/WebGL-Operationen an einen entfernten Host mit echter GPU weiter, sodass Readbacks (getImageData / toDataURL / readPixels / measureText) zu der GPU passen, die Sie präsentieren – selbst auf Hardware, die sie lokal nicht rendern kann. Weil die Bridge die Operationen weiterleitet (keine vorab aufgezeichneten Bilder), kommt sie mit den meisten Canvases zurecht, nicht nur mit bekannten Prüfskripten. Aktiviert wird sie mit --canvas-bridge-url=ws://host:port (plus --no-sandbox); ohne diesen Switch läuft alles vollständig lokal, genau wie bisher. Der Render-Server steuert einen Browser auf dem Host mit echter GPU (ein reguläres Chrome über CDP oder ein Headless-Clearcote). Die vollständige Einrichtung beschreibt die Canvas-Bridge-Anleitung.
Native Metadaten-Overrides & light_stealth
Neben der aus dem Seed abgeleiteten Persona gibt es eine Reihe nativer Einzelwert-Overrides, mit denen Sie einzelne navigator-/screen-Werte direkt spoofen – hardwareConcurrency, deviceMemory, colorDepth, devicePixelRatio, maxTouchPoints und (per Opt-in) die Abmessungen von screen/avail*. Jeder Wert wird direkt von seinem Getter gelesen, mit der Rangfolge Flag > --fingerprint-Persona > echter Host; ein fest gesetzter Wert schlägt also jeden Seed, und die Overrides funktionieren mit oder ohne einen --fingerprint-Seed – die Persona-Mechanik wird dabei nie aktiviert.
Das SDK bündelt eine leichte Teilmenge hinter einem einzigen Flag, light_stealth: Es wendet eines von wenigen kohärenten Metadaten-Bündeln an (hardwareConcurrency, deviceMemory, colorDepth, devicePixelRatio, maxTouchPoints), und zwar ausschließlich über diese nativen Switches. Der Seed wählt nur das Bündel aus und wird nicht an die Engine übergeben; es gibt also kein Canvas- oder WebGL-Rauschen, und alle light_stealth-Sessions auf einem Rechner teilen sich den Canvas-Hash des Hosts – nutzen Sie einen fingerprint-Seed pro Account ohne lightStealth, wenn sich diese Hashes unterscheiden müssen. Der TLS-ClientHello und die echte Browserversion bleiben unverändert. Die Abmessungen von screen werden standardmäßig bewusst nicht gespooft (Opt-in über screenWidth usw.), weil ein gefälschter Bildschirm, der sich nicht mit der echten Render-Fläche in Einklang bringen lässt, leicht auffällt; prüfen Sie auf einem unskalierten Display, ob der gewählte devicePixelRatio dazu passt, oder setzen Sie ihn selbst. Eine explizit gesetzte Option hat immer Vorrang vor dem Preset.
import { launch } from "clearcote";
// one coherent metadata bundle; "my-seed" only picks which one — no seed reaches the engine, so no canvas noise:
const browser = await launch({ lightStealth: true, fingerprint: "my-seed" });
// or set individual values by hand (no --fingerprint needed):
const b2 = await launch({
hardwareConcurrency: 8,
deviceMemory: 8,
devicePixelRatio: 1.25,
maxTouchPoints: 0,
});Alle Switches
Filtern Sie nach Name oder Wirkung, oder grenzen Sie auf ein Subsystem ein. Klicken Sie auf einen Switch, um zu lesen, was er bewirkt, und seine kürzeste gültige Form zu sehen.
Master-Seed (Integer oder String). Leitet die gesamte Persona ab (GPU, Bildschirm, Hardware, Schriftarten) und steuert das Canvas- und WebGL-Rauschen pro Website. Sprache und Zeitzone werden nicht aus dem Seed abgeleitet: Sie kommen aus --accept-lang / --timezone (SDK: acceptLanguage, timezone oder geoip). Gerendertes Audio und Client-Rects werden nicht verändert; die AudioContext-Skalare sampleRate/baseLatency/outputLatency liefert die Persona, sobald eine aktiv ist – siehe Fingerprint-Doku. Gleicher Seed ⇒ gleiche Identität.
Beispiele
Das hier sind reine Kommandozeilen-Flag-Sets. Vollständige Workflows für Python und Node finden Sie unter Beispiele.
Eine vollständige, kohärente Windows-Identität:
--fingerprint=acme-tenant-7 \
--fingerprint-platform=windows \
--fingerprint-brand=Chrome \
--accept-lang=en-US,en \
--lang=en-US \
--timezone=America/New_York \
--fingerprint-hardware-concurrency=8Eine Windows-Identität mit eigenen GPU-Strings, in der Form, in der ANGLE sie unter Windows meldet:
--fingerprint=42 \
--fingerprint-platform=windows \
--fingerprint-gpu-vendor="Google Inc. (NVIDIA)" \
--fingerprint-gpu-renderer="ANGLE (NVIDIA, NVIDIA GeForce RTX 3060 (0x00002504) Direct3D11 vs_5_0 ps_5_0, D3D11)"Die Strings ändern, was gemeldet wird, nicht, womit gerendert wird: Die Pixel kommen weiterhin von der GPU dieses Rechners. Geben Sie die GPU an, auf der Sie tatsächlich rendern, oder nutzen Sie die Canvas-Bridge. Die Plattform macos ändert die Identitäts-Strings (UA, Client Hints, navigator.platform), dahinter steht aber kein macOS-Gerätemodell, und android ist eine Mobile-Persona nach dem Best-Effort-Prinzip.
Legen Sie einen Standort zusammen mit seiner Zeitzone fest, damit Geolocation und Uhr übereinstimmen:
--fingerprint=nyc-1 \
--timezone=America/New_York \
--fingerprint-location=40.7128,-74.0060Die Werte eines echten Rechners importieren
Statt eines synthetischen Seeds können Sie die exakten Werte ausgeben, die ein echtes Chrome gemeldet hat – GPU-Strings + getParameter-Tabelle, Bildschirm, Schriften, Stimmen, Audio. Die Werte werden ersetzt; gerendert wird weiterhin auf Ihrem eigenen Rechner. Ein Profil gibt zwei Accounts also keine unterschiedlichen Canvases – ein --fingerprint-Seed pro Account schon. Holen Sie sich eines aus der kuratierten clearcote-profiles-Bibliothek (Tausende Profile echter Rechner, nach GPU-Hersteller getaggt) oder erfassen Sie Ihr eigenes mit dem Collector; laden Sie es anschließend und weisen Sie nach, dass es geladen wurde:
import { launch } from "clearcote";
// path to a captured .json profile, a profile object, or a JSON string
const browser = await launch({ fingerprintProfile: "./real-machine.json" });
// fields present in the profile override the persona;
// absent fields fall back to the --fingerprint seed's persona, or the browser's defaults with no seed.Ablauf der Erfassung: Öffnen Sie die Collector-Seite in dem echten Chrome, das Sie klonen möchten, exportieren Sie das JSON und übergeben Sie es über fingerprintProfile (SDK) / --fingerprint-profile (Engine). Prüfen können Sie es mit tools/fingerprint-collect/verify_profile.py.
Was die einzelnen Patches tun
Jeder Switch des offenen Builds entspricht einem lesbaren Engine-Patch: Die Diffs liegen in patches/, eine einzeilige Zusammenfassung jedes Patches in patches/README.md. Switches mit dem Vermerk “lizenzierter Build” stammen aus dem eigenen Patch-Set des lizenzierten Builds, das nicht öffentlich ist.
Kohärenz zählt mehr als jeder Einzelwert: Halten Sie Plattform, Zeitzone, Locale und GPU gemeinsam plausibel. Wie die Engine sie konsistent hält, lesen Sie unter Architektur; warum das JavaScript-Spoofing überlegen ist, unter Wie Erkennung funktioniert.
Weiterlesen