mirror of
https://github.com/CloakHQ/CloakBrowser.git
synced 2026-06-23 11:41:46 +02:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
132cafe13c | ||
|
|
6c94b9e985 | ||
|
|
fdc1ae0484 | ||
|
|
2ded0c1866 |
@@ -0,0 +1,29 @@
|
|||||||
|
---
|
||||||
|
name: Bug Report
|
||||||
|
about: Report a bug or detection issue
|
||||||
|
labels: bug
|
||||||
|
---
|
||||||
|
|
||||||
|
Description: <!-- What happened? What did you expect? -->
|
||||||
|
|
||||||
|
CloakBrowser version: <!-- pip show cloakbrowser / npm list cloakbrowser -->
|
||||||
|
|
||||||
|
Wrapper: <!-- Python or JavaScript -->
|
||||||
|
|
||||||
|
Environment: <!-- OS, Docker y/n, base image, architecture -->
|
||||||
|
|
||||||
|
Launch options:
|
||||||
|
|
||||||
|
|
||||||
|
Tested with a different IP or proxy? <!-- Yes (same result) / Yes (works with different IP) / No -->
|
||||||
|
|
||||||
|
Works outside Docker / on host machine? <!-- Yes / No / Not using Docker -->
|
||||||
|
|
||||||
|
Steps to reproduce:
|
||||||
|
|
||||||
|
|
||||||
|
Error output / screenshots:
|
||||||
|
|
||||||
|
Dockerfile (if applicable):
|
||||||
|
|
||||||
|
Additional notes:
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
blank_issues_enabled: true
|
||||||
@@ -6,6 +6,13 @@ Changes are tagged: **[wrapper]** for Python/JS wrapper, **[binary]** for Chromi
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## [0.3.18] — 2026-03-15
|
||||||
|
|
||||||
|
- **[wrapper]** Fix welcome banner printing to stdout — now writes to stderr so it won't corrupt JSON output in programmatic usage (fixes #59)
|
||||||
|
- **[wrapper]** Fix `cloakserve` Docker WebGL by adding `--ignore-gpu-blocklist` flag
|
||||||
|
- **[docs]** Add Crawlee integration example
|
||||||
|
- **[meta]** Add GitHub issue template for bug reports
|
||||||
|
|
||||||
## [0.3.17] — 2026-03-15
|
## [0.3.17] — 2026-03-15
|
||||||
|
|
||||||
- **[binary]** Windows x64 build upgraded to 145.0.7632.159.7 — 33 source-level C++ patches, matching Linux
|
- **[binary]** Windows x64 build upgraded to 145.0.7632.159.7 — 33 source-level C++ patches, matching Linux
|
||||||
|
|||||||
@@ -631,6 +631,7 @@ browser = await launch_async(args=["--remote-debugging-port=9242"])
|
|||||||
|-----------|-------|----------|---------|
|
|-----------|-------|----------|---------|
|
||||||
| [browser-use](https://github.com/browser-use/browser-use) | 70K | Python | [`browser_use_example.py`](examples/integrations/browser_use_example.py) |
|
| [browser-use](https://github.com/browser-use/browser-use) | 70K | Python | [`browser_use_example.py`](examples/integrations/browser_use_example.py) |
|
||||||
| [Crawl4AI](https://github.com/unclecode/crawl4ai) | 58K | Python | [`crawl4ai_example.py`](examples/integrations/crawl4ai_example.py) |
|
| [Crawl4AI](https://github.com/unclecode/crawl4ai) | 58K | Python | [`crawl4ai_example.py`](examples/integrations/crawl4ai_example.py) |
|
||||||
|
| [Crawlee](https://github.com/apify/crawlee-python) | 8.6K | Python | [`crawlee_example.py`](examples/integrations/crawlee_example.py) |
|
||||||
| [Scrapling](https://github.com/D4Vinci/Scrapling) | 21K | Python | [`scrapling_example.py`](examples/integrations/scrapling_example.py) |
|
| [Scrapling](https://github.com/D4Vinci/Scrapling) | 21K | Python | [`scrapling_example.py`](examples/integrations/scrapling_example.py) |
|
||||||
| [Stagehand](https://github.com/browserbase/stagehand) | 21K | TypeScript | [`stagehand.ts`](js/examples/stagehand.ts) |
|
| [Stagehand](https://github.com/browserbase/stagehand) | 21K | TypeScript | [`stagehand.ts`](js/examples/stagehand.ts) |
|
||||||
| [LangChain](https://github.com/langchain-ai/langchain) | 100K+ | Python | [`langchain_loader.py`](examples/integrations/langchain_loader.py) |
|
| [LangChain](https://github.com/langchain-ai/langchain) | 100K+ | Python | [`langchain_loader.py`](examples/integrations/langchain_loader.py) |
|
||||||
|
|||||||
@@ -33,6 +33,9 @@ chrome_args = [
|
|||||||
"--disable-popup-blocking",
|
"--disable-popup-blocking",
|
||||||
"--disable-background-networking",
|
"--disable-background-networking",
|
||||||
"--metrics-recording-only",
|
"--metrics-recording-only",
|
||||||
|
# GPU blocklist bypass: Chromium blocks WebGL on software GPUs in
|
||||||
|
# Docker/Xvfb. Without this, WebGL vendor/renderer spoofing fails. #58
|
||||||
|
"--ignore-gpu-blocklist",
|
||||||
] + get_default_stealth_args() + sys.argv[1:]
|
] + get_default_stealth_args() + sys.argv[1:]
|
||||||
|
|
||||||
chrome = subprocess.Popen(chrome_args)
|
chrome = subprocess.Popen(chrome_args)
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
__version__ = "0.3.17"
|
__version__ = "0.3.18"
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import os
|
|||||||
import platform
|
import platform
|
||||||
import stat
|
import stat
|
||||||
import subprocess
|
import subprocess
|
||||||
|
import sys
|
||||||
import tarfile
|
import tarfile
|
||||||
import tempfile
|
import tempfile
|
||||||
import threading
|
import threading
|
||||||
@@ -55,14 +56,14 @@ def _show_welcome() -> None:
|
|||||||
marker = get_cache_dir() / ".welcome_shown"
|
marker = get_cache_dir() / ".welcome_shown"
|
||||||
if marker.exists():
|
if marker.exists():
|
||||||
return
|
return
|
||||||
print()
|
sys.stderr.write("\n")
|
||||||
print(" CloakBrowser — stealth Chromium for automation")
|
sys.stderr.write(" CloakBrowser — stealth Chromium for automation\n")
|
||||||
print(" https://github.com/CloakHQ/CloakBrowser")
|
sys.stderr.write(" https://github.com/CloakHQ/CloakBrowser\n")
|
||||||
print()
|
sys.stderr.write("\n")
|
||||||
print(" Issues? https://github.com/CloakHQ/CloakBrowser/issues")
|
sys.stderr.write(" Issues? https://github.com/CloakHQ/CloakBrowser/issues\n")
|
||||||
print(" Donate? https://ko-fi.com/cloakhq")
|
sys.stderr.write(" Donate? https://ko-fi.com/cloakhq\n")
|
||||||
print(" Star us if CloakBrowser helps your project!")
|
sys.stderr.write(" Star us if CloakBrowser helps your project!\n")
|
||||||
print()
|
sys.stderr.write("\n")
|
||||||
try:
|
try:
|
||||||
marker.parent.mkdir(parents=True, exist_ok=True)
|
marker.parent.mkdir(parents=True, exist_ok=True)
|
||||||
marker.write_text("")
|
marker.write_text("")
|
||||||
|
|||||||
@@ -0,0 +1,72 @@
|
|||||||
|
"""Crawlee + CloakBrowser: stealth web crawling with PlaywrightCrawler.
|
||||||
|
|
||||||
|
Uses a custom BrowserPlugin to swap Crawlee's default Chromium
|
||||||
|
for CloakBrowser's patched binary with source-level fingerprint patches.
|
||||||
|
|
||||||
|
Requires: pip install cloakbrowser "crawlee[playwright]"
|
||||||
|
"""
|
||||||
|
|
||||||
|
import asyncio
|
||||||
|
|
||||||
|
from cloakbrowser.config import IGNORE_DEFAULT_ARGS, get_default_stealth_args
|
||||||
|
from cloakbrowser.download import ensure_binary
|
||||||
|
from typing_extensions import override
|
||||||
|
|
||||||
|
from crawlee.browsers import (
|
||||||
|
BrowserPool,
|
||||||
|
PlaywrightBrowserController,
|
||||||
|
PlaywrightBrowserPlugin,
|
||||||
|
)
|
||||||
|
from crawlee.crawlers import PlaywrightCrawler, PlaywrightCrawlingContext
|
||||||
|
|
||||||
|
|
||||||
|
class CloakBrowserPlugin(PlaywrightBrowserPlugin):
|
||||||
|
"""Browser plugin that uses CloakBrowser's patched Chromium,
|
||||||
|
but otherwise keeps the functionality of PlaywrightBrowserPlugin.
|
||||||
|
"""
|
||||||
|
|
||||||
|
@override
|
||||||
|
async def new_browser(self) -> PlaywrightBrowserController:
|
||||||
|
if not self._playwright:
|
||||||
|
raise RuntimeError('Playwright browser plugin is not initialized.')
|
||||||
|
|
||||||
|
binary_path = ensure_binary()
|
||||||
|
stealth_args = get_default_stealth_args()
|
||||||
|
|
||||||
|
# Merge CloakBrowser stealth args with any user-provided launch options.
|
||||||
|
launch_options = dict(self._browser_launch_options)
|
||||||
|
launch_options.pop('executable_path', None)
|
||||||
|
launch_options.pop('chromium_sandbox', None)
|
||||||
|
existing_args = list(launch_options.pop('args', []))
|
||||||
|
launch_options['args'] = [*existing_args, *stealth_args]
|
||||||
|
|
||||||
|
return PlaywrightBrowserController(
|
||||||
|
browser=await self._playwright.chromium.launch(
|
||||||
|
executable_path=binary_path,
|
||||||
|
ignore_default_args=IGNORE_DEFAULT_ARGS,
|
||||||
|
**launch_options,
|
||||||
|
),
|
||||||
|
max_open_pages_per_browser=1,
|
||||||
|
# CloakBrowser handles fingerprints at the binary level.
|
||||||
|
header_generator=None,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
async def main() -> None:
|
||||||
|
crawler = PlaywrightCrawler(
|
||||||
|
max_requests_per_crawl=10,
|
||||||
|
browser_pool=BrowserPool(plugins=[CloakBrowserPlugin()]),
|
||||||
|
)
|
||||||
|
|
||||||
|
@crawler.router.default_handler
|
||||||
|
async def request_handler(context: PlaywrightCrawlingContext) -> None:
|
||||||
|
context.log.info(f'Processing {context.request.url} ...')
|
||||||
|
title = await context.page.title()
|
||||||
|
await context.push_data({'url': context.request.url, 'title': title})
|
||||||
|
await context.enqueue_links()
|
||||||
|
|
||||||
|
await crawler.run(['https://example.com'])
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
asyncio.run(main())
|
||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "cloakbrowser",
|
"name": "cloakbrowser",
|
||||||
"version": "0.3.17",
|
"version": "0.3.18",
|
||||||
"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",
|
||||||
|
|||||||
+8
-8
@@ -146,14 +146,14 @@ export async function checkForUpdate(): Promise<string | null> {
|
|||||||
function showWelcome(): void {
|
function showWelcome(): void {
|
||||||
const marker = path.join(getCacheDir(), ".welcome_shown");
|
const marker = path.join(getCacheDir(), ".welcome_shown");
|
||||||
if (fs.existsSync(marker)) return;
|
if (fs.existsSync(marker)) return;
|
||||||
console.log();
|
console.error();
|
||||||
console.log(" CloakBrowser — stealth Chromium for automation");
|
console.error(" CloakBrowser — stealth Chromium for automation");
|
||||||
console.log(" https://github.com/CloakHQ/CloakBrowser");
|
console.error(" https://github.com/CloakHQ/CloakBrowser");
|
||||||
console.log();
|
console.error();
|
||||||
console.log(" Issues? https://github.com/CloakHQ/CloakBrowser/issues");
|
console.error(" Issues? https://github.com/CloakHQ/CloakBrowser/issues");
|
||||||
console.log(" Donate? https://ko-fi.com/cloakhq");
|
console.error(" Donate? https://ko-fi.com/cloakhq");
|
||||||
console.log(" Star us if CloakBrowser helps your project!");
|
console.error(" Star us if CloakBrowser helps your project!");
|
||||||
console.log();
|
console.error();
|
||||||
try {
|
try {
|
||||||
fs.mkdirSync(getCacheDir(), { recursive: true });
|
fs.mkdirSync(getCacheDir(), { recursive: true });
|
||||||
fs.writeFileSync(marker, "");
|
fs.writeFileSync(marker, "");
|
||||||
|
|||||||
Reference in New Issue
Block a user