Zum Inhalt springen

Playwright & Puppeteer

Clearcote ist schlicht Chromium und funktioniert daher als Drop-in-Browser mit den Automatisierungstools, die Sie bereits verwenden.

Das Paket clearcote (npm, PyPI und NuGet) macht aus Identitätsoptionen benannte Argumente und liefert gewöhnliche Playwright-Objekte zurück. Beim ersten Einsatz lädt es den Browser herunter und prüft ihn per SHA-256 — ohne Lizenzschlüssel den offenen Build, mit Schlüssel den neuesten lizenzierten Build (siehe Installation) — und wendet die weiter unten beschriebenen Standardwerte an.

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

Aktuelles SDK: 0.45.0. Seit 0.23 läuft launch() in Python und Node auf einem echten Wegwerf-Profilverzeichnis (wird beim Schließen gelöscht) statt im Inkognito-Modus. Dadurch entspricht alles, was vom Profil abhängt, einem echten Chrome, und widevine: true kann das DRM-Modul laden. Zurück kommt ein browserähnliches Handle: newPage() funktioniert wie gewohnt, newContext() liefert jedoch denselben Profilkontext statt eines isolierten. Für getrennte Cookie-Jars starten Sie getrennte Browser; übergeben Sie ephemeralProfile: false / ephemeral_profile=False für den alten Inkognito-Browser oder userDataDir / user_data_dir, um das Profil zu behalten.

Die Async-API (clearcote.async_api) nimmt innerhalb einer asyncio-Schleife dieselben Persona- und Proxy-Optionen entgegen und liefert die Async-Objekte von Playwright; ihr launch() startet inkognito, für ein Profil (und für widevine=True) verwenden Sie daher launch_persistent_context(). Das .NET-SDK umfasst LaunchEphemeralProfileAsync (empfohlen — LaunchAsync startet unter .NET inkognito und kann das Fenster headless nicht an den Bildschirm anpassen), LaunchPersistentContextAsync,ServeAsync, den verifizierten Download, die Lizenzierung, Geoip und menschenähnliche Eingaben (explizite Aufrufe von HumanClickAsync / HumanTypeAsync / HumanSelectOptionAsync statt eines Launch-Flags). Gespeicherte Profile, profile: "auto", Render-Kohärenzprüfungen, Widevine und die Agent-Helfer gibt es vorerst nur für Python & Node. Komplette Workflows zum Kopieren finden Sie unter Beispiele.

Puppeteer und andere CDP-Clients (serve)

Einen Puppeteer-Launcher hat das SDK nicht. Stattdessen startet serve() Clearcote mit den Launch-Einstellungen des SDK (Persona, Proxy, Standardwerte) und einem CDP-Endpunkt auf Loopback, an den sich jeder CDP-Client anhängen kann — Puppeteer, connectOverCDP von Playwright, browser-use, Crawl4AI, Stagehand. Das funktioniert mit dem lizenzierten Build, und nichts fügt --enable-automation hinzu. humanize arbeitet auf der Playwright-Seite und greift daher nicht bei einem Client, der auf diesem Weg verbunden ist.

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

Im Headless-Modus gibt serve() dem Browser ein Display in realer Größe und passt sein Fenster an den Arbeitsbereich an, bevor sich ein Client verbindet (0.31+); für ein kleineres Fenster übergeben Sie windowSize / window_size. Aus der Shell erledigt clearcote serve dasselbe als dauerhafter Dienst — und kann jeder Verbindung einen eigenen Browser geben, mit Identität, Proxy, Zeitzone und Sprache aus der Verbindungs-URL. Siehe Deployment.

Das Binary direkt ansteuern (offener Build)

Sie können auch Ihren eigenen Launcher per executablePath (Node) oder executable_path (Python) auf den offenen Build richten und die Identitätsoptionen als args übergeben. Der lizenzierte Build startet auf diese Weise nicht — er braucht das Lizenz-Token, das das SDK bezieht; nehmen Sie also launch() oder serve() von oben. Lassen Sie --enable-automation weg, wie es das SDK tut (Puppeteer und ältere Playwright-Versionen setzen es; es schaltet Chromium in seinen Automatisierungsmodus). Keine der Standardeinstellungen des SDK (Sprache, WebRTC-Richtlinie, Fenstergeometrie) greift auf diesem Weg.

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

Das verifizierte Binary auflösen oder vorab laden

Das SDK ermittelt den Browser in dieser Reihenfolge: ein explizit angegebener executablePath / executable_path, dann CLEARCOTE_BINARY, dann eine von Ihnen angeforderte version (oder CLEARCOTE_BROWSER_VERSION), dann der lizenzierte Build, sofern ein Lizenzschlüssel gefunden wird (die Option licenseKey, CLEARCOTE_LICENSE_KEY oder ~/.clearcote/license.key), und zuletzt der offene Build, den diese SDK-Version fest vorgibt. Ein von Ihnen angegebener Pfad wird vor dem Start auf fehlende oder abgeschnittene Dateien geprüft. Rufen Sie download / executable_path auf, wenn Sie den Cache ohne Start vorwärmen, ein eigenes Cache-Verzeichnis verwenden oder zur Laufzeit per Opt-in den neuesten offenen Build von GitHub beziehen möchten.

from clearcote import download, launch

chrome = download(cache_dir=r"C:\clearcote-cache", auto_update=True)
browser = launch(executable_path=chrome, fingerprint="seed-123")

Im gepinnten Modus werden die fest ins SDK eingebauten SHA-256-Werte geprüft. autoUpdate / auto_update ist Opt-in und prüft das Prüfsummen-Manifest des Releases; ist gpg verfügbar, wird zusätzlich das signierte Manifest gegen den fest hinterlegten Fingerprint des Clearcote-Signaturschlüssels geprüft. Das gilt nur für den offenen Build: Mit Lizenzschlüssel holt download() stattdessen den aktuellen lizenzierten Build (einen bestimmten wählen Sie mit version oder releaseChannel — siehe Build auswählen). Unter .NET holt DownloadAsync nur den offenen Build; den lizenzierten laden Sie vorab mit ExecutablePathAsync(new LaunchOptions { LicenseKey = … }).

Standardmäßig kohärent (ohne zusätzliche Flags)

Egal, womit Sie starten: Die Engine hält die sekundären Signale im Einklang mit der gewählten Persona — bei einer Windows-Persona mit dem, was ein echter Chrome-Desktop unter Windows meldet. Die Plattform der Persona entspricht standardmäßig Ihrem Host-Betriebssystem; auf einem Linux-Host folgen diese Werte also einer Linux-Persona, sofern Sie nicht platform übergeben. Die WebGL-Limits von getParameter (WebGL1 + WebGL2) melden die Werte der Persona, begrenzt auf das, was die GPU dieses Rechners tatsächlich leisten kann, und UNMASKED_RENDERER / UNMASKED_VENDOR sind für die ganze Session konstant (auf jeder Website dieselbe GPU, passend zur Persona). Bei einer Windows-Persona meldet navigator.getBattery() einen Desktop am Stromnetz, navigator.connection einen privaten Internetanschluss und AudioContext die passende Windows-WASAPI-Samplerate und -Latenz. getScreenDetails() meldet einen einzelnen Monitor, und @media (pointer: fine) / (hover: hover) entsprechen einem Desktop mit Maus.

Geprüft mit 153 r26, headed unter Windows (September 2026): BrowserScan meldet keinen Bot, und CreepJS zeigt 0 % Stealth. Hinter einem Proxy fügen Sie geoip hinzu, damit Zeitzone und WebRTC zum Exit passen.

Kohärente Standardwerte (überschreibbar)

Das SDK setzt einige stealth-gerechte Standardwerte, damit die offensichtlichen Indizien nicht durchrutschen:

  • Headed-Starts verwenden standardmäßig keinen emulierten Viewport (viewport: null / no_viewport=True), sodass window.innerWidth dem echten OS-Fenster folgt — ein emulierter Viewport von 1280×720 in einem echten Fenster verrät ein unmögliches Fenster. Zum Überschreiben übergeben Sie einen expliziten viewport. Auf einem Linux-Server ohne Fenstermanager (Xvfb, Ihr eigener Container), wo --start-maximized nichts bewirkt, wird ein Headed-Fenster vor der ersten Seite an den Arbeitsbereich des Bildschirms angepasst, wie ein maximiertes Desktop-Fenster (SDK 0.42.0).
  • Headless-Starts bekommen vor der ersten Seite ein realistisches Display und ein daran angepasstes Fenster: den Bildschirm der Persona oder, ohne Persona, eine echte Desktop-Größe. Ab SDK 0.42.0 gilt das auf jeder Plattform, auch wenn eine Persona nicht greift, sodass eine Seite nie die nackte Headless-Oberfläche der Engine mit 800×600 sieht. Eine eigene viewport- oder screen-Option schaltet das ab, und mit einem eigenen --screen-info legen Sie das Display selbst fest. Ein eigenes --window-size, --window-position oder --start-maximized behält das Display bei und überspringt nur die Anpassung; in serve() behält auch ein bloßes --window-position das Display bei, und erst ein Größen-Switch oder --screen-info überlässt die Geometrie ganz Ihnen.
  • Eine einheitliche WebGL-Oberfläche unter Linux: Auf einem Linux-Host rendert das WebGL einer Linux-Persona headless wie headed über Mesa auf EGL (SDK 0.42.0; der Host braucht libegl1), sodass eine Seite in beiden Fällen denselben Renderer-String, dieselbe Erweiterungsliste und dieselben Limits sieht, in der OpenGL-ES-Form, die die meisten echten Linux-Rechner melden. Ohne EGL verwendet ein Headed-Start das Desktop-GL von Mesa, und eine Windows-Persona rendert über SwiftShader. Ein eigenes --use-angle oder --use-gl in args hat Vorrang, und ein Headless-Start bekommt dazu trotzdem --ignore-gpu-blocklist, damit WebGL weiter funktioniert.
  • Hell oder dunkel kommt von der Persona auf dem lizenzierten Build ab 154 r32: Kontexte, die das SDK anlegt, lassen die Farbschema-Emulation von Playwright ausgeschaltet (SDK 0.41.0+), wo Playwright sonst ein helles Schema erzwingen würde. Übergeben Sie colorScheme / color_scheme, um trotzdem eines zu emulieren.
  • Die Persona bleibt von der Kommandozeile fern auf dem lizenzierten Build ab 154 r32: Seed, Persona-Overrides und Proxy-Zugangsdaten erreichen den Browser über seine Umgebung, nicht über seinen Eintrag in der Prozessliste (SDK 0.41.0+; personaEnv: false behält die Kommandozeile bei). Siehe Launch-Optionen.
  • WebRTC verwendet standardmäßig disable_non_proxied_udp, sodass kein UDP am Proxy vorbei nach außen geht und die eigene Adresse Ihres Rechners privat bleibt. Überschrieben wird das nur durch Ihre eigene --webrtc-ip-handling-policy in args — und auf dem offenen Build durch webrtcIp / geoip, die WebRTC-UDP wieder über Ihre eigene Verbindung hinauslassen (der lizenzierte Build blockiert WebRTC-UDP in jedem Fall). Mit dieser Richtlinie und ohne webrtcIp erhält eine Seite überhaupt keine ICE-Kandidaten — hinter einem Proxy übergeben Sie daher geoip (oder webrtcIp), damit WebRTC die Adresse des Proxys meldet, oder socks5Udp, um echtes UDP über einen SOCKS5-Proxy zu leiten.
  • Hinter einem Proxy ist QUIC / HTTP-3 aus, wie bei einem echten Chrome hinter einem Proxy — es wird also kein UDP am Proxy vorbei versucht.
  • Die Plattform der Persona entspricht standardmäßig Ihrem Host-Betriebssystem, die Marke ist standardmäßig Google Chrome. Ohne timezone und ohne geoip folgt die Zeitzone der Sprache (en-US → New York).
  • Proxy-Zugangsdaten gehen an den Browser, nicht an Playwright, sofern die Engine das unterstützt: bei SOCKS5 immer (Playwright kann sich bei SOCKS5 überhaupt nicht authentifizieren), bei HTTP(S) ab 151 r19, damit der Seiten-Cache aktiv bleibt (Python & Node). Siehe unten.
  • humanize führt vor jedem vertrauenswürdigen Klick einen Actionability-Pre-Flight durch (sichtbar / aktiviert / stabil + eine Verdeckungsprüfung per elementFromPoint) und fällt auf den nativen Klick zurück, sodass ein vertrauenswürdiger Klick nie unter einem Overlay oder mitten in einer Animation ausgelöst wird.
Tipp: Leiten Sie den Seed aus Ihrer eigenen Account-/Tenant-ID ab, damit jede Identität reproduzierbar ist — gleicher Seed, gleicher Browser-Fingerprint, jedes Mal. Die vollständige Liste der Switches finden Sie unter Fingerprint-Flags.