release: v0.4.7 — update cloaktest
Publish / test (push) Has been cancelled
Publish / validate-version (push) Has been cancelled
Publish / publish-pypi (push) Has been cancelled
Publish / publish-npm (push) Has been cancelled
Publish / publish-nuget (push) Has been cancelled
Publish / publish-docker (push) Has been cancelled

This commit is contained in:
CloakHQ
2026-07-03 00:01:46 +02:00
parent 49a9cfc51b
commit a3e0994a31
8 changed files with 101 additions and 91 deletions
+4
View File
@@ -8,6 +8,10 @@ Changes are tagged: **[wrapper]** for Python/JS wrapper, **[binary]** for Chromi
## [Unreleased]
## [0.4.7] — 2026-07-02
- **[docker]** Update the public `cloaktest` suite to use free-tier-stable bot-detection checks while Pro continues to verify reCAPTCHA v3 at 0.9. The Docker smoke test now runs Sannysoft, Incolumitas, Rebrowser, deviceandbrowserinfo, BrowserScan, and CreepJS lies/noise=false; FingerprintJS and reCAPTCHA v3 are no longer hard-pass checks for the free v146 image.
## [0.4.6] — 2026-07-02
- **[wrapper]** The resolved Pro license key is now passed to the browser process at launch (via `CLOAKBROWSER_LICENSE_KEY`) so the Pro binary can authenticate itself, including when you supply a custom `env`. Fixes launch failures on the newest Pro binaries. Python, JS, and .NET.
+10 -10
View File
@@ -38,11 +38,11 @@ Same API, same code — just swap the import. <strong>3 lines of code, 30 second
- **58 source-level C++ patches** — canvas, WebGL, audio, fonts, GPU, screen, WebRTC, network timing, automation signals, CDP input behavior
- **`humanize=True`** — human-like mouse curves, keyboard timing, and scroll patterns. One flag, behavioral detection passes
- **0.9 reCAPTCHA v3 score** — human-level, server-verified
- **Pro: 0.9 reCAPTCHA v3 score** — human-level, server-verified
- **Passes Cloudflare Turnstile**, FingerprintJS, BrowserScan — tested against 30+ detection sites
- **Auto-updating binary** — background update checks, always on the latest stealth build
- **Auto-downloads the right binary** — free or Pro based on your license
- **`pip install cloakbrowser`** or **`npm install cloakbrowser`** — binary auto-downloads, zero config
- **Free and open source** — no subscriptions, no usage limits
- **Open-source wrappers** — free v146 binary, Pro for latest builds
**Try it now** — no install needed:
@@ -150,7 +150,7 @@ page.goto("https://example.com")
---
## Latest: v0.4.6 — 59 source-level stealth patches, now on every platform (Chromium 148.0.7778.215.3)
## Latest: v0.4.7 — 59 source-level stealth patches, now on every platform (Chromium 148.0.7778.215.3)
- **CloakBrowser Pro** — the latest binary (Chromium 148.0.7778.215.3, 59 source-level patches) is available to Pro subscribers, now on **all platforms including macOS** (Apple Silicon + Intel); v146 stays free forever. Set a `license_key` (`licenseKey` in JS) or the `CLOAKBROWSER_LICENSE_KEY` env var and the wrapper fetches the latest build automatically. See [CloakBrowser Pro](#cloakbrowser-pro)
- **.NET 8 / C# client** — CloakBrowser now ships as a NuGet package (`CloakBrowser`), mirroring the Python and JS wrappers.
@@ -206,15 +206,15 @@ Pro plans → **[cloakbrowser.dev](https://cloakbrowser.dev)**
## Test Results
All tests verified against live detection services. Last tested: Jun 2026 (Chromium 148).
All tests verified against live detection services. Results below are for the latest Pro/current build unless noted. Last tested: Jul 2026 (Chromium 148).
| Detection Service | Stock Playwright | CloakBrowser | Notes |
|---|---|---|---|
| **reCAPTCHA v3** | 0.1 (bot) | **0.9** (human) | Server-side verified |
| **reCAPTCHA v3** | 0.1 (bot) | **0.9** (human) | Pro/current build; server-side verified |
| **Cloudflare Turnstile** (non-interactive) | FAIL | **PASS** | Auto-resolve |
| **Cloudflare Turnstile** (managed) | FAIL | **PASS** | Single click |
| **ShieldSquare** | BLOCKED | **PASS** | Production site |
| **FingerprintJS** bot detection | DETECTED | **PASS** | demo.fingerprint.com |
| **FingerprintJS** bot detection | DETECTED | **PASS** | Pro/current build; demo.fingerprint.com |
| **BrowserScan** bot detection | DETECTED | **NORMAL** (4/4) | browserscan.net |
| **bot.incolumitas.com** | 13 fails | **1 fail** | WEBDRIVER spec only |
| **deviceandbrowserinfo.com** | 6 true flags | **0 true flags** | `isBot: false` |
@@ -230,7 +230,7 @@ All tests verified against live detection services. Last tested: Jun 2026 (Chrom
<p align="center">
<img src="https://i.imgur.com/hvIQyMv.png" width="600" alt="reCAPTCHA v3 — Score 0.9">
<br><em>reCAPTCHA v3 score 0.9 — server-side verified (human-level)</em>
<br><em>Pro/latest build: reCAPTCHA v3 score 0.9 — server-side verified (human-level)</em>
</p>
<p align="center">
@@ -245,7 +245,7 @@ All tests verified against live detection services. Last tested: Jun 2026 (Chrom
<p align="center">
<img src="https://i.imgur.com/9n2C7tu.png" width="600" alt="FingerprintJS — Passed">
<br><em>FingerprintJS web-scraping demo — data served, not blocked</em>
<br><em>Pro/latest build: FingerprintJS web-scraping demo — data served, not blocked</em>
</p>
<p align="center">
@@ -257,7 +257,7 @@ All tests verified against live detection services. Last tested: Jun 2026 (Chrom
| Feature | Playwright | playwright-stealth | undetected-chromedriver | Camoufox | CloakBrowser |
|---|---|---|---|---|---|
| reCAPTCHA v3 score | 0.1 | 0.3-0.5 | 0.3-0.7 | 0.7-0.9 | **0.9** |
| reCAPTCHA v3 score (Pro/current) | 0.1 | 0.3-0.5 | 0.3-0.7 | 0.7-0.9 | **0.9** |
| Cloudflare Turnstile | Fail | Sometimes | Sometimes | Pass | **Pass** |
| Patch level | None | JS injection | Config patches | C++ (Firefox) | **C++ (Chromium)** |
| Survives Chrome updates | N/A | Breaks often | Breaks often | Yes | **Yes** |
+1 -1
View File
@@ -1 +1 @@
__version__ = "0.4.6"
__version__ = "0.4.7"
+1 -1
View File
@@ -10,7 +10,7 @@
<!-- NuGet packaging metadata -->
<PackageId>CloakBrowser</PackageId>
<Version>0.4.6</Version>
<Version>0.4.7</Version>
<Authors>CloakHQ</Authors>
<Description>Stealth Chromium that passes every bot detection test. Drop-in Playwright (.NET) replacement with source-level fingerprint patches.</Description>
<PackageLicenseExpression>MIT</PackageLicenseExpression>
+1 -1
View File
@@ -4,5 +4,5 @@ namespace CloakBrowser;
public static class CloakVersion
{
/// <summary>The CloakBrowser .NET wrapper version.</summary>
public const string Version = "0.4.6";
public const string Version = "0.4.7";
}
+78 -72
View File
@@ -10,7 +10,6 @@ Usage:
python examples/stealth_test.py --proxy http://10.50.96.5:8888
"""
import json
import sys
import time
@@ -54,8 +53,8 @@ def test_bot_incolumitas(page):
"""bot.incolumitas.com — comprehensive 30+ check bot detection."""
page.goto("https://bot.incolumitas.com", wait_until="networkidle", timeout=30000)
# Poll until test count stabilizes (site runs tests progressively)
last_total = 0
results = {"passed": 0, "failed": 0, "failedTests": [], "total": 0}
for _ in range(15):
time.sleep(2)
results = page.evaluate("""() => {
@@ -63,12 +62,7 @@ def test_bot_incolumitas(page):
const okMatches = text.match(/"\\w+":\\s*"OK"/g) || [];
const failMatches = text.match(/"\\w+":\\s*"FAIL"/g) || [];
const failedTests = failMatches.map(m => m.match(/"(\\w+)"/)[1]);
return {
passed: okMatches.length,
failed: failMatches.length,
failedTests,
total: okMatches.length + failMatches.length
};
return {passed: okMatches.length, failed: failMatches.length, failedTests, total: okMatches.length + failMatches.length};
}""")
if results["total"] >= 30 and results["total"] == last_total:
break
@@ -77,6 +71,22 @@ def test_bot_incolumitas(page):
return results
def test_rebrowser(page):
"""bot-detector.rebrowser.net — automation signal detector."""
page.goto("https://bot-detector.rebrowser.net/", wait_until="networkidle", timeout=30000)
time.sleep(10)
return page.evaluate("""() => {
const el = document.getElementById('detections-json');
if (!el) return {failing: [], totalFails: 0, passed: 0, notTriggered: 0, error: 'no detections-json element'};
const tests = JSON.parse(el.value);
const failing = tests.filter(t => t.rating === 1).map(t => t.type);
const passed = tests.filter(t => t.rating === -1).length;
const notTriggered = tests.filter(t => t.rating === 0).length;
return {failing, totalFails: failing.length, passed, notTriggered, total: tests.length};
}""")
def test_browserscan(page):
"""browserscan.net/bot-detection — WebDriver, UA, CDP, Navigator checks."""
page.goto("https://www.browserscan.net/bot-detection", wait_until="networkidle", timeout=30000)
@@ -123,47 +133,17 @@ def test_deviceandbrowserinfo(page):
return results
def test_fingerprintjs(page):
"""demo.fingerprint.com/web-scraping — industry-standard bot detection."""
page.goto("https://demo.fingerprint.com/web-scraping", wait_until="domcontentloaded", timeout=30000)
time.sleep(8)
def test_creepjs_noise_off(page):
"""CreepJS — lie detection with fingerprint noise disabled."""
page.goto("https://abrahamjuliot.github.io/creepjs/", wait_until="domcontentloaded", timeout=30000)
time.sleep(15)
# Click search to trigger bot detection — bots get blocked, humans see flights
try:
page.click("button:has-text('Search')", timeout=5000)
time.sleep(5)
except Exception:
pass
results = page.evaluate("""() => {
const text = document.body.innerText;
// Bots see error messages; humans see flight prices
const hasFlights = text.includes('Price per adult') || text.includes('$');
const isBlocked = text.includes('request was blocked') || text.includes('bot visit detected');
return {passed: hasFlights && !isBlocked, isBlocked, hasFlights};
return page.evaluate("""() => {
const fp = window.Fingerprint;
if (!fp) return {error: 'Fingerprint not ready', totalLies: null};
const lies = fp.lies || {};
return {totalLies: lies.totalLies || 0};
}""")
return results
def test_recaptcha(page):
"""recaptcha-demo.appspot.com — Google's official reCAPTCHA v3 score."""
page.goto(
"https://recaptcha-demo.appspot.com/recaptcha-v3-request-scores.php",
wait_until="domcontentloaded",
timeout=30000,
)
# Wait for score to appear (polls up to 30s)
for _ in range(15):
time.sleep(2)
score = page.evaluate("""() => {
const text = document.body.innerText;
const match = text.match(/"score":\\s*(\\d+\\.\\d+)/);
return match ? parseFloat(match[1]) : null;
}""")
if score is not None:
break
return {"score": score}
TESTS = [
@@ -180,11 +160,33 @@ TESTS = [
"url": "https://bot.incolumitas.com",
"runner": test_bot_incolumitas,
"verdict": lambda r: f"{r['passed']}/{r['total']} passed"
+ (" — ALL GREEN" if r.get("failed", 0) == 0
+ (
" — ALL GREEN"
if r.get("failed", 0) == 0
else f" (FAILED: {', '.join(r.get('failedTests', []))} — known false positives)"
if set(r.get("failedTests", [])) <= {"WEBDRIVER", "connectionRTT"}
else f" (FAILED: {', '.join(r.get('failedTests', []))})"),
"pass": lambda r: set(r.get("failedTests", [])) <= {"WEBDRIVER", "connectionRTT"}, # known false positives
else f" (FAILED: {', '.join(r.get('failedTests', []))})"
),
"pass": lambda r: set(r.get("failedTests", [])) <= {"WEBDRIVER", "connectionRTT"},
},
{
"name": "Rebrowser Bot Detector",
"url": "https://bot-detector.rebrowser.net/",
"runner": test_rebrowser,
"verdict": lambda r: (
f"🟢{r.get('passed', 0)}{r.get('notTriggered', 0)} — ALL CLEAN"
if r.get("totalFails", 1) == 0
else f"FAIL: {', '.join(r.get('failing', []))}"
),
"pass": lambda r: r.get("totalFails", 1) == 0,
},
{
"name": "deviceandbrowserinfo.com",
"url": "https://deviceandbrowserinfo.com/are_you_a_bot",
"runner": test_deviceandbrowserinfo,
"verdict": lambda r: f"isBot: {r.get('isBot', 'unknown')}"
+ (f", trueFlags: {sum(1 for v in r.get('checks', {}).values() if v)}" if r.get("checks") else ""),
"pass": lambda r: not r.get("isBot", True) and not any(r.get("checks", {}).values()),
},
{
"name": "BrowserScan",
@@ -194,26 +196,12 @@ TESTS = [
"pass": lambda r: r.get("abnormal", 1) == 0,
},
{
"name": "deviceandbrowserinfo.com",
"url": "https://deviceandbrowserinfo.com/are_you_a_bot",
"runner": test_deviceandbrowserinfo,
"verdict": lambda r: f"isBot: {r.get('isBot', 'unknown')}"
+ (f" checks: {json.dumps(r.get('checks', {}))}" if r.get("checks") else ""),
"pass": lambda r: not r.get("isBot", True),
},
{
"name": "FingerprintJS",
"url": "https://demo.fingerprint.com/web-scraping",
"runner": test_fingerprintjs,
"verdict": lambda r: "PASSED (flights shown)" if r.get("passed") else "BLOCKED" if r.get("isBlocked") else "NO FLIGHTS",
"pass": lambda r: r.get("passed", False),
},
{
"name": "reCAPTCHA v3 (Google)",
"url": "https://recaptcha-demo.appspot.com/recaptcha-v3-request-scores.php",
"runner": test_recaptcha,
"verdict": lambda r: f"Score: {r.get('score', 'N/A')}",
"pass": lambda r: (r.get("score") or 0) >= 0.7,
"name": "CreepJS lies (noise=false)",
"url": "https://abrahamjuliot.github.io/creepjs/",
"runner": test_creepjs_noise_off,
"verdict": lambda r: f"lies: {r.get('totalLies', 'N/A')}",
"pass": lambda r: r.get("totalLies") == 0,
"args": ["--fingerprint-noise=false"],
},
]
@@ -229,6 +217,7 @@ def main():
print("Launching stealth browser...", flush=True)
browser = launch(headless=not HEADED, proxy=PROXY, geoip=True)
shared_browser_closed = False
page = browser.new_page()
# Show browser fingerprint details
@@ -281,8 +270,19 @@ def main():
print(f"--- {name} ---")
print(f"URL: {test['url']}")
test_browser = browser
test_context = None
test_page = page
try:
result = test["runner"](page)
if test.get("args"):
browser.close()
shared_browser_closed = True
test_browser = launch(headless=not HEADED, proxy=PROXY, geoip=True, args=test["args"])
test_context = test_browser.new_context(viewport={"width": 1920, "height": 1080})
test_page = test_context.new_page()
result = test["runner"](test_page)
passed = test["pass"](result)
verdict = test["verdict"](result)
status = "PASS" if passed else "FAIL"
@@ -292,15 +292,21 @@ def main():
if SCREENSHOTS:
filename = f"stealth_test_{name.replace('.', '_').replace(' ', '_').replace('/', '_')}.png"
page.screenshot(path=filename)
test_page.screenshot(path=filename)
print(f"Screenshot: {filename}")
except Exception as e:
results_summary.append((name, "ERROR", str(e)))
print(f"Error: {e}")
finally:
if test_context is not None:
test_context.close()
if test_browser is not browser:
test_browser.close()
print()
if not shared_browser_closed:
browser.close()
# Summary table
+2 -2
View File
@@ -1,12 +1,12 @@
{
"name": "cloakbrowser",
"version": "0.4.6",
"version": "0.4.7",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "cloakbrowser",
"version": "0.4.6",
"version": "0.4.7",
"license": "MIT",
"dependencies": {
"tar": "^7.0.0"
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "cloakbrowser",
"version": "0.4.6",
"version": "0.4.7",
"description": "Stealth Chromium that passes every bot detection test. Drop-in Playwright/Puppeteer replacement with source-level fingerprint patches.",
"type": "module",
"main": "dist/index.js",