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
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:
@@ -8,6 +8,10 @@ Changes are tagged: **[wrapper]** for Python/JS wrapper, **[binary]** for Chromi
|
|||||||
|
|
||||||
## [Unreleased]
|
## [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
|
## [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.
|
- **[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.
|
||||||
|
|||||||
@@ -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
|
- **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
|
- **`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
|
- **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
|
- **`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:
|
**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)
|
- **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.
|
- **.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
|
## 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 |
|
| 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** (non-interactive) | FAIL | **PASS** | Auto-resolve |
|
||||||
| **Cloudflare Turnstile** (managed) | FAIL | **PASS** | Single click |
|
| **Cloudflare Turnstile** (managed) | FAIL | **PASS** | Single click |
|
||||||
| **ShieldSquare** | BLOCKED | **PASS** | Production site |
|
| **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 |
|
| **BrowserScan** bot detection | DETECTED | **NORMAL** (4/4) | browserscan.net |
|
||||||
| **bot.incolumitas.com** | 13 fails | **1 fail** | WEBDRIVER spec only |
|
| **bot.incolumitas.com** | 13 fails | **1 fail** | WEBDRIVER spec only |
|
||||||
| **deviceandbrowserinfo.com** | 6 true flags | **0 true flags** | `isBot: false` |
|
| **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">
|
<p align="center">
|
||||||
<img src="https://i.imgur.com/hvIQyMv.png" width="600" alt="reCAPTCHA v3 — Score 0.9">
|
<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>
|
||||||
|
|
||||||
<p align="center">
|
<p align="center">
|
||||||
@@ -245,7 +245,7 @@ All tests verified against live detection services. Last tested: Jun 2026 (Chrom
|
|||||||
|
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<img src="https://i.imgur.com/9n2C7tu.png" width="600" alt="FingerprintJS — Passed">
|
<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>
|
||||||
|
|
||||||
<p align="center">
|
<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 |
|
| 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** |
|
| Cloudflare Turnstile | Fail | Sometimes | Sometimes | Pass | **Pass** |
|
||||||
| Patch level | None | JS injection | Config patches | C++ (Firefox) | **C++ (Chromium)** |
|
| Patch level | None | JS injection | Config patches | C++ (Firefox) | **C++ (Chromium)** |
|
||||||
| Survives Chrome updates | N/A | Breaks often | Breaks often | Yes | **Yes** |
|
| Survives Chrome updates | N/A | Breaks often | Breaks often | Yes | **Yes** |
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
__version__ = "0.4.6"
|
__version__ = "0.4.7"
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
|
|
||||||
<!-- NuGet packaging metadata -->
|
<!-- NuGet packaging metadata -->
|
||||||
<PackageId>CloakBrowser</PackageId>
|
<PackageId>CloakBrowser</PackageId>
|
||||||
<Version>0.4.6</Version>
|
<Version>0.4.7</Version>
|
||||||
<Authors>CloakHQ</Authors>
|
<Authors>CloakHQ</Authors>
|
||||||
<Description>Stealth Chromium that passes every bot detection test. Drop-in Playwright (.NET) replacement with source-level fingerprint patches.</Description>
|
<Description>Stealth Chromium that passes every bot detection test. Drop-in Playwright (.NET) replacement with source-level fingerprint patches.</Description>
|
||||||
<PackageLicenseExpression>MIT</PackageLicenseExpression>
|
<PackageLicenseExpression>MIT</PackageLicenseExpression>
|
||||||
|
|||||||
@@ -4,5 +4,5 @@ namespace CloakBrowser;
|
|||||||
public static class CloakVersion
|
public static class CloakVersion
|
||||||
{
|
{
|
||||||
/// <summary>The CloakBrowser .NET wrapper version.</summary>
|
/// <summary>The CloakBrowser .NET wrapper version.</summary>
|
||||||
public const string Version = "0.4.6";
|
public const string Version = "0.4.7";
|
||||||
}
|
}
|
||||||
|
|||||||
+81
-75
@@ -10,7 +10,6 @@ Usage:
|
|||||||
python examples/stealth_test.py --proxy http://10.50.96.5:8888
|
python examples/stealth_test.py --proxy http://10.50.96.5:8888
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import json
|
|
||||||
import sys
|
import sys
|
||||||
import time
|
import time
|
||||||
|
|
||||||
@@ -54,8 +53,8 @@ def test_bot_incolumitas(page):
|
|||||||
"""bot.incolumitas.com — comprehensive 30+ check bot detection."""
|
"""bot.incolumitas.com — comprehensive 30+ check bot detection."""
|
||||||
page.goto("https://bot.incolumitas.com", wait_until="networkidle", timeout=30000)
|
page.goto("https://bot.incolumitas.com", wait_until="networkidle", timeout=30000)
|
||||||
|
|
||||||
# Poll until test count stabilizes (site runs tests progressively)
|
|
||||||
last_total = 0
|
last_total = 0
|
||||||
|
results = {"passed": 0, "failed": 0, "failedTests": [], "total": 0}
|
||||||
for _ in range(15):
|
for _ in range(15):
|
||||||
time.sleep(2)
|
time.sleep(2)
|
||||||
results = page.evaluate("""() => {
|
results = page.evaluate("""() => {
|
||||||
@@ -63,12 +62,7 @@ def test_bot_incolumitas(page):
|
|||||||
const okMatches = text.match(/"\\w+":\\s*"OK"/g) || [];
|
const okMatches = text.match(/"\\w+":\\s*"OK"/g) || [];
|
||||||
const failMatches = text.match(/"\\w+":\\s*"FAIL"/g) || [];
|
const failMatches = text.match(/"\\w+":\\s*"FAIL"/g) || [];
|
||||||
const failedTests = failMatches.map(m => m.match(/"(\\w+)"/)[1]);
|
const failedTests = failMatches.map(m => m.match(/"(\\w+)"/)[1]);
|
||||||
return {
|
return {passed: okMatches.length, failed: failMatches.length, failedTests, total: okMatches.length + failMatches.length};
|
||||||
passed: okMatches.length,
|
|
||||||
failed: failMatches.length,
|
|
||||||
failedTests,
|
|
||||||
total: okMatches.length + failMatches.length
|
|
||||||
};
|
|
||||||
}""")
|
}""")
|
||||||
if results["total"] >= 30 and results["total"] == last_total:
|
if results["total"] >= 30 and results["total"] == last_total:
|
||||||
break
|
break
|
||||||
@@ -77,6 +71,22 @@ def test_bot_incolumitas(page):
|
|||||||
return results
|
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):
|
def test_browserscan(page):
|
||||||
"""browserscan.net/bot-detection — WebDriver, UA, CDP, Navigator checks."""
|
"""browserscan.net/bot-detection — WebDriver, UA, CDP, Navigator checks."""
|
||||||
page.goto("https://www.browserscan.net/bot-detection", wait_until="networkidle", timeout=30000)
|
page.goto("https://www.browserscan.net/bot-detection", wait_until="networkidle", timeout=30000)
|
||||||
@@ -123,47 +133,17 @@ def test_deviceandbrowserinfo(page):
|
|||||||
return results
|
return results
|
||||||
|
|
||||||
|
|
||||||
def test_fingerprintjs(page):
|
def test_creepjs_noise_off(page):
|
||||||
"""demo.fingerprint.com/web-scraping — industry-standard bot detection."""
|
"""CreepJS — lie detection with fingerprint noise disabled."""
|
||||||
page.goto("https://demo.fingerprint.com/web-scraping", wait_until="domcontentloaded", timeout=30000)
|
page.goto("https://abrahamjuliot.github.io/creepjs/", wait_until="domcontentloaded", timeout=30000)
|
||||||
time.sleep(8)
|
time.sleep(15)
|
||||||
|
|
||||||
# Click search to trigger bot detection — bots get blocked, humans see flights
|
return page.evaluate("""() => {
|
||||||
try:
|
const fp = window.Fingerprint;
|
||||||
page.click("button:has-text('Search')", timeout=5000)
|
if (!fp) return {error: 'Fingerprint not ready', totalLies: null};
|
||||||
time.sleep(5)
|
const lies = fp.lies || {};
|
||||||
except Exception:
|
return {totalLies: lies.totalLies || 0};
|
||||||
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 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 = [
|
TESTS = [
|
||||||
@@ -180,11 +160,33 @@ TESTS = [
|
|||||||
"url": "https://bot.incolumitas.com",
|
"url": "https://bot.incolumitas.com",
|
||||||
"runner": test_bot_incolumitas,
|
"runner": test_bot_incolumitas,
|
||||||
"verdict": lambda r: f"{r['passed']}/{r['total']} passed"
|
"verdict": lambda r: f"{r['passed']}/{r['total']} passed"
|
||||||
+ (" — ALL GREEN" if r.get("failed", 0) == 0
|
+ (
|
||||||
else f" (FAILED: {', '.join(r.get('failedTests', []))} — known false positives)"
|
" — ALL GREEN"
|
||||||
if set(r.get("failedTests", [])) <= {"WEBDRIVER", "connectionRTT"}
|
if r.get("failed", 0) == 0
|
||||||
else f" (FAILED: {', '.join(r.get('failedTests', []))})"),
|
else f" (FAILED: {', '.join(r.get('failedTests', []))} — known false positives)"
|
||||||
"pass": lambda r: set(r.get("failedTests", [])) <= {"WEBDRIVER", "connectionRTT"}, # 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"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"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",
|
"name": "BrowserScan",
|
||||||
@@ -194,26 +196,12 @@ TESTS = [
|
|||||||
"pass": lambda r: r.get("abnormal", 1) == 0,
|
"pass": lambda r: r.get("abnormal", 1) == 0,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "deviceandbrowserinfo.com",
|
"name": "CreepJS lies (noise=false)",
|
||||||
"url": "https://deviceandbrowserinfo.com/are_you_a_bot",
|
"url": "https://abrahamjuliot.github.io/creepjs/",
|
||||||
"runner": test_deviceandbrowserinfo,
|
"runner": test_creepjs_noise_off,
|
||||||
"verdict": lambda r: f"isBot: {r.get('isBot', 'unknown')}"
|
"verdict": lambda r: f"lies: {r.get('totalLies', 'N/A')}",
|
||||||
+ (f" checks: {json.dumps(r.get('checks', {}))}" if r.get("checks") else ""),
|
"pass": lambda r: r.get("totalLies") == 0,
|
||||||
"pass": lambda r: not r.get("isBot", True),
|
"args": ["--fingerprint-noise=false"],
|
||||||
},
|
|
||||||
{
|
|
||||||
"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,
|
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -229,6 +217,7 @@ def main():
|
|||||||
print("Launching stealth browser...", flush=True)
|
print("Launching stealth browser...", flush=True)
|
||||||
|
|
||||||
browser = launch(headless=not HEADED, proxy=PROXY, geoip=True)
|
browser = launch(headless=not HEADED, proxy=PROXY, geoip=True)
|
||||||
|
shared_browser_closed = False
|
||||||
page = browser.new_page()
|
page = browser.new_page()
|
||||||
|
|
||||||
# Show browser fingerprint details
|
# Show browser fingerprint details
|
||||||
@@ -281,8 +270,19 @@ def main():
|
|||||||
print(f"--- {name} ---")
|
print(f"--- {name} ---")
|
||||||
print(f"URL: {test['url']}")
|
print(f"URL: {test['url']}")
|
||||||
|
|
||||||
|
test_browser = browser
|
||||||
|
test_context = None
|
||||||
|
test_page = page
|
||||||
try:
|
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)
|
passed = test["pass"](result)
|
||||||
verdict = test["verdict"](result)
|
verdict = test["verdict"](result)
|
||||||
status = "PASS" if passed else "FAIL"
|
status = "PASS" if passed else "FAIL"
|
||||||
@@ -292,16 +292,22 @@ def main():
|
|||||||
|
|
||||||
if SCREENSHOTS:
|
if SCREENSHOTS:
|
||||||
filename = f"stealth_test_{name.replace('.', '_').replace(' ', '_').replace('/', '_')}.png"
|
filename = f"stealth_test_{name.replace('.', '_').replace(' ', '_').replace('/', '_')}.png"
|
||||||
page.screenshot(path=filename)
|
test_page.screenshot(path=filename)
|
||||||
print(f"Screenshot: {filename}")
|
print(f"Screenshot: {filename}")
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
results_summary.append((name, "ERROR", str(e)))
|
results_summary.append((name, "ERROR", str(e)))
|
||||||
print(f"Error: {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()
|
print()
|
||||||
|
|
||||||
browser.close()
|
if not shared_browser_closed:
|
||||||
|
browser.close()
|
||||||
|
|
||||||
# Summary table
|
# Summary table
|
||||||
print("=" * 60)
|
print("=" * 60)
|
||||||
|
|||||||
Generated
+2
-2
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "cloakbrowser",
|
"name": "cloakbrowser",
|
||||||
"version": "0.4.6",
|
"version": "0.4.7",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "cloakbrowser",
|
"name": "cloakbrowser",
|
||||||
"version": "0.4.6",
|
"version": "0.4.7",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"tar": "^7.0.0"
|
"tar": "^7.0.0"
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "cloakbrowser",
|
"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.",
|
"description": "Stealth Chromium that passes every bot detection test. Drop-in Playwright/Puppeteer replacement with source-level fingerprint patches.",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.js",
|
||||||
|
|||||||
Reference in New Issue
Block a user