feat: add Windows x64 support, update macOS to v145

This commit is contained in:
CloakHQ
2026-03-03 08:57:07 +01:00
parent 55418add96
commit f9887943c0
9 changed files with 53 additions and 44 deletions
+10 -13
View File
@@ -106,7 +106,7 @@ page.goto("https://example.com")
## What's New in v0.3.0
- **Chromium 145** (Linux) — latest stable, 25 fingerprint patches (up from 16). macOS v145 coming soon
- **Chromium 145** — latest stable, 25 fingerprint patches (up from 16). All platforms
- **9 new patches** — screen dimensions, device memory, audio, WebGL, and more
- **SHA-256 checksum verification** — binary downloads are verified for integrity
- **CDP hardening** — audited and patched known automation detection vectors
@@ -175,7 +175,7 @@ All tests verified against live detection services. Last tested: Mar 2026 (Chrom
CloakBrowser is a thin wrapper (Python + JavaScript) around a custom-built Chromium binary:
1. **You install**`pip install cloakbrowser` or `npm install cloakbrowser`
2. **First launch** → binary auto-downloads for your platform (Linux x64: Chromium 145, macOS: Chromium 142)
2. **First launch** → binary auto-downloads for your platform (Chromium 145)
3. **Every launch** → Playwright or Puppeteer starts with our binary + stealth args
4. **You write code** → standard Playwright/Puppeteer API, nothing new to learn
@@ -354,9 +354,9 @@ Every launch automatically generates a **unique fingerprint**. A random seed (10
### Default Fingerprint
Every `launch()` call sets these automatically. Defaults are **platform-aware** — macOS runs as a native Mac browser, Linux spoofs Windows:
Every `launch()` call sets these automatically. Defaults are **platform-aware** — macOS runs as a native Mac browser, Linux and Windows use the Windows fingerprint profile:
| Flag | Linux Default | macOS Default | Controls |
| Flag | Linux/Windows Default | macOS Default | Controls |
|------|--------------|---------------|----------|
| `--fingerprint` | Random (1000099999) | Random (1000099999) | Master seed for canvas, WebGL, audio, fonts, client rects |
| `--fingerprint-platform` | `windows` | `macos` | `navigator.platform`, User-Agent OS, GPU pool selection |
@@ -428,16 +428,14 @@ browser = launch(args=[
| Platform | Chromium | Patches | Status |
|---|---|---|---|
| Linux x86_64 | 145 | 25 | ✅ Latest |
| macOS arm64 (Apple Silicon) | 142 | 16 | ✅ Available (v145 coming soon) |
| macOS x86_64 (Intel) | 142 | 16 | ✅ Available (v145 coming soon) |
| Windows | — | | Planned |
| macOS arm64 (Apple Silicon) | 145 | 25 | ✅ Latest |
| macOS x86_64 (Intel) | 145 | 25 | ✅ Latest |
| Windows x86_64 | 145 | 25 | ✅ Latest |
The wrapper auto-downloads the correct binary for your platform. Linux gets Chromium 145 with all 25 patches. macOS currently runs Chromium 142 (16 patches) — the v145 macOS build is in progress.
The wrapper auto-downloads the correct binary for your platform.
**macOS first launch:** The binary is ad-hoc signed. On first run, macOS Gatekeeper will block it. Right-click the app → **Open** → click **Open** in the dialog. This is only needed once.
**On Windows?** You can still use CloakBrowser via Docker or with your own Chromium binary by setting `CLOAKBROWSER_BINARY_PATH=/path/to/chrome`.
## Examples
**Python** — see [`examples/`](examples/):
@@ -456,12 +454,11 @@ The wrapper auto-downloads the correct binary for your platform. Linux gets Chro
| Feature | Status |
|---------|--------|
| Linux x64 — Chromium 145 (25 patches) | ✅ Released |
| macOS arm64/x64 — Chromium 142 (16 patches) | ✅ Released |
| macOS arm64/x64 — Chromium 145 | 🔨 In progress |
| macOS arm64/x64 — Chromium 145 (25 patches) | ✅ Released |
| Windows x64 — Chromium 145 (25 patches) | ✅ Released |
| JavaScript/Puppeteer + Playwright support | ✅ Released |
| Fingerprint rotation per session | ✅ Released |
| Built-in proxy rotation | 📋 Planned |
| Windows support | 📋 Planned |
## Docker
+9 -6
View File
@@ -11,8 +11,7 @@ from ._version import __version__
# ---------------------------------------------------------------------------
# Chromium version shipped with this release.
# Different platforms may ship different versions (e.g. Linux gets v145 first,
# macOS stays on v142 until Mac builds are ready).
# Different platforms may ship different versions during transition periods.
# CHROMIUM_VERSION is the latest across all platforms (for display/reference).
# Use get_chromium_version() for the current platform's actual version.
# ---------------------------------------------------------------------------
@@ -22,6 +21,7 @@ PLATFORM_CHROMIUM_VERSIONS: dict[str, str] = {
"linux-x64": "145.0.7632.109",
"darwin-arm64": "145.0.7632.109",
"darwin-x64": "145.0.7632.109",
"windows-x64": "145.0.7632.109",
}
# ---------------------------------------------------------------------------
@@ -51,7 +51,7 @@ def get_default_stealth_args() -> list[str]:
"--fingerprint-gpu-renderer=ANGLE (Apple, ANGLE Metal Renderer: Apple M3, Unspecified Version)",
]
# Linux: spoof as Windows
# Linux/Windows: Windows fingerprint profile
return base + [
"--fingerprint-platform=windows",
"--fingerprint-hardware-concurrency=8",
@@ -79,6 +79,8 @@ SUPPORTED_PLATFORMS: dict[tuple[str, str], str] = {
("Linux", "aarch64"): "linux-arm64",
("Darwin", "arm64"): "darwin-arm64",
("Darwin", "x86_64"): "darwin-x64",
("Windows", "AMD64"): "windows-x64",
("Windows", "x86_64"): "windows-x64",
}
# Platforms with pre-built binaries available for download (derived from version map).
@@ -132,6 +134,8 @@ def get_binary_path(version: str | None = None) -> Path:
if platform.system() == "Darwin":
# macOS: Chromium.app bundle
return binary_dir / "Chromium.app" / "Contents" / "MacOS" / "Chromium"
elif platform.system() == "Windows":
return binary_dir / "chrome.exe"
else:
# Linux: flat binary
return binary_dir / "chrome"
@@ -150,9 +154,8 @@ def check_platform_available() -> None:
available = ", ".join(sorted(AVAILABLE_PLATFORMS))
import sys
sys.exit(
f"\n\033[1mCloakBrowser\033[0m — Pre-built binaries are currently only available for: {available}.\n"
f"Windows builds are coming soon.\n\n"
f"To use CloakBrowser now, run in Docker (see README) or set CLOAKBROWSER_BINARY_PATH."
f"\n\033[1mCloakBrowser\033[0m — Pre-built binaries are currently only available for: {available}.\n\n"
f"To use CloakBrowser now, set CLOAKBROWSER_BINARY_PATH to a local Chromium binary."
)
+3 -1
View File
@@ -330,7 +330,9 @@ def _is_executable(path: Path) -> bool:
def _make_executable(path: Path) -> None:
"""Make a file executable (chmod +x)."""
"""Make a file executable (chmod +x). Skipped on Windows (no-op / AV lock risk)."""
if platform.system() == "Windows":
return
current = path.stat().st_mode
path.chmod(current | stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH)
+1 -3
View File
@@ -176,9 +176,7 @@ const page = await browser.newPage();
| Linux x86_64 | ✅ Available |
| macOS arm64 (Apple Silicon) | ✅ Available |
| macOS x86_64 (Intel) | ✅ Available |
| Windows | Planned |
**On Windows?** You can still use CloakBrowser via Docker or with your own Chromium binary by setting `CLOAKBROWSER_BINARY_PATH=/path/to/chrome`.
| Windows x86_64 | ✅ Available |
## Requirements
+18 -9
View File
@@ -23,8 +23,7 @@ export { WRAPPER_VERSION };
// ---------------------------------------------------------------------------
// Chromium version shipped with this release.
// Different platforms may ship different versions (e.g. Linux gets v145 first,
// macOS stays on v142 until Mac builds are ready).
// Different platforms may ship different versions during transition periods.
// CHROMIUM_VERSION is the latest across all platforms (for display/reference).
// Use getChromiumVersion() for the current platform's actual version.
// ---------------------------------------------------------------------------
@@ -32,8 +31,9 @@ export const CHROMIUM_VERSION = "145.0.7632.109";
export const PLATFORM_CHROMIUM_VERSIONS: Record<string, string> = {
"linux-x64": "145.0.7632.109",
"darwin-arm64": "142.0.7444.175",
"darwin-x64": "142.0.7444.175",
"darwin-arm64": "145.0.7632.109",
"darwin-x64": "145.0.7632.109",
"windows-x64": "145.0.7632.109",
};
// ---------------------------------------------------------------------------
@@ -44,6 +44,7 @@ const SUPPORTED_PLATFORMS: Record<string, string> = {
"linux-arm64": "linux-arm64",
"darwin-arm64": "darwin-arm64",
"darwin-x64": "darwin-x64",
"win32-x64": "windows-x64",
};
// Platforms with pre-built binaries available for download (derived from version map).
@@ -64,6 +65,7 @@ export function getPlatformTag(): string {
else if (platform === "linux" && arch === "arm64") key = "linux-arm64";
else if (platform === "darwin" && arch === "arm64") key = "darwin-arm64";
else if (platform === "darwin" && arch === "x64") key = "darwin-x64";
else if (platform === "win32" && arch === "x64") key = "win32-x64";
else {
const supported = Object.values(SUPPORTED_PLATFORMS).join(", ");
throw new Error(
@@ -92,6 +94,9 @@ export function getBinaryPath(version?: string): string {
if (process.platform === "darwin") {
return path.join(binaryDir, "Chromium.app", "Contents", "MacOS", "Chromium");
}
if (process.platform === "win32") {
return path.join(binaryDir, "chrome.exe");
}
return path.join(binaryDir, "chrome");
}
@@ -102,9 +107,8 @@ export function checkPlatformAvailable(): void {
if (!AVAILABLE_PLATFORMS.has(tag)) {
const available = [...AVAILABLE_PLATFORMS].sort().join(", ");
throw new Error(
`CloakBrowser — Pre-built binaries are currently only available for: ${available}.\n` +
`Windows builds are coming soon.\n\n` +
`To use CloakBrowser now, run in Docker (see README) or set CLOAKBROWSER_BINARY_PATH.`
`CloakBrowser — Pre-built binaries are currently only available for: ${available}.\n\n` +
`To use CloakBrowser now, set CLOAKBROWSER_BINARY_PATH to a local Chromium binary.`
);
}
}
@@ -198,10 +202,15 @@ export function getDefaultStealthArgs(): string[] {
if (isMac) {
// macOS: run as native Mac browser — GPU/UA match natively
return [...base, "--fingerprint-platform=macos"];
return [
...base,
"--fingerprint-platform=macos",
"--fingerprint-gpu-vendor=Google Inc. (Apple)",
"--fingerprint-gpu-renderer=ANGLE (Apple, ANGLE Metal Renderer: Apple M3, Unspecified Version)",
];
}
// Linux: spoof as Windows
// Linux/Windows: Windows fingerprint profile
return [
...base,
"--fingerprint-platform=windows",
+2 -2
View File
@@ -363,9 +363,9 @@ async function extractArchive(
// Flatten single subdirectory if needed
flattenSingleSubdir(destDir);
// Make binary executable
// Make binary executable (skip on Windows — no-op / AV lock risk)
const bp = binaryPath || getBinaryPath();
if (fs.existsSync(bp)) {
if (process.platform !== "win32" && fs.existsSync(bp)) {
fs.chmodSync(bp, 0o755);
}
+1 -1
View File
@@ -7,7 +7,7 @@ describe("binaryInfo", () => {
const info = binaryInfo();
expect(info.version).toBe(getChromiumVersion());
expect(info.platform).toMatch(/^(linux|darwin)-(x64|arm64)$/);
expect(info.platform).toMatch(/^(linux|darwin|windows)-(x64|arm64)$/);
expect(info.binaryPath).toBeTruthy();
expect(typeof info.installed).toBe("boolean");
expect(info.cacheDir).toContain("cloakbrowser");
+4 -4
View File
@@ -100,7 +100,7 @@ describe("latest version (platform-aware)", () => {
{
tag_name: "chromium-v145.0.7718.0",
draft: false,
assets: makeAssets(["linux-x64", "darwin-arm64", "darwin-x64"]),
assets: makeAssets(["linux-x64", "darwin-arm64", "darwin-x64", "windows-x64"]),
},
]);
expect(await getLatestChromiumVersion()).toBe("145.0.7718.0");
@@ -116,7 +116,7 @@ describe("latest version (platform-aware)", () => {
{
tag_name: "chromium-v142.0.7444.175",
draft: false,
assets: makeAssets(["linux-x64", "darwin-arm64", "darwin-x64"]),
assets: makeAssets(["linux-x64", "darwin-arm64", "darwin-x64", "windows-x64"]),
},
]);
const result = await getLatestChromiumVersion();
@@ -133,14 +133,14 @@ describe("latest version (platform-aware)", () => {
{
tag_name: "chromium-v145.0.7718.0",
draft: false,
assets: [{ name: "cloakbrowser-windows-x64.tar.gz" }],
assets: [{ name: "cloakbrowser-freebsd-x64.tar.gz" }],
},
]);
expect(await getLatestChromiumVersion()).toBeNull();
});
it("skips draft releases", async () => {
const all = ["linux-x64", "darwin-arm64", "darwin-x64"];
const all = ["linux-x64", "darwin-arm64", "darwin-x64", "windows-x64"];
mockFetch([
{ tag_name: "chromium-v999.0.0.0", draft: true, assets: makeAssets(all) },
{ tag_name: "chromium-v145.0.7718.0", draft: false, assets: makeAssets(all) },
+5 -5
View File
@@ -166,7 +166,7 @@ class TestGetLatestVersion:
{
"tag_name": "chromium-v145.0.7718.0",
"draft": False,
"assets": self._make_assets(["linux-x64", "darwin-arm64", "darwin-x64"]),
"assets": self._make_assets(["linux-x64", "darwin-arm64", "darwin-x64", "windows-x64"]),
},
]
mock_response.raise_for_status = MagicMock()
@@ -187,7 +187,7 @@ class TestGetLatestVersion:
{
"tag_name": "chromium-v142.0.7444.175",
"draft": False,
"assets": self._make_assets(["linux-x64", "darwin-arm64", "darwin-x64"]),
"assets": self._make_assets(["linux-x64", "darwin-arm64", "darwin-x64", "windows-x64"]),
},
]
mock_response.raise_for_status = MagicMock()
@@ -202,7 +202,7 @@ class TestGetLatestVersion:
def test_skips_draft_releases(self):
mock_response = MagicMock()
all_platforms = ["linux-x64", "darwin-arm64", "darwin-x64"]
all_platforms = ["linux-x64", "darwin-arm64", "darwin-x64", "windows-x64"]
mock_response.json.return_value = [
{"tag_name": "chromium-v999.0.0.0", "draft": True, "assets": self._make_assets(all_platforms)},
{"tag_name": "chromium-v145.0.7718.0", "draft": False, "assets": self._make_assets(all_platforms)},
@@ -215,7 +215,7 @@ class TestGetLatestVersion:
def test_skips_non_chromium_tags(self):
mock_response = MagicMock()
all_platforms = ["linux-x64", "darwin-arm64", "darwin-x64"]
all_platforms = ["linux-x64", "darwin-arm64", "darwin-x64", "windows-x64"]
mock_response.json.return_value = [
{"tag_name": "v0.2.0", "draft": False, "assets": self._make_assets(all_platforms)},
{"tag_name": "chromium-v145.0.7718.0", "draft": False, "assets": self._make_assets(all_platforms)},
@@ -233,7 +233,7 @@ class TestGetLatestVersion:
{
"tag_name": "chromium-v145.0.7718.0",
"draft": False,
"assets": [{"name": "cloakbrowser-windows-x64.tar.gz"}],
"assets": [{"name": "cloakbrowser-freebsd-x64.tar.gz"}],
},
]
mock_response.raise_for_status = MagicMock()