Skip to content

Commit b22ef4b

Browse files
authored
Merge pull request #35 from HaiNick/feat/cloakbrowser-v2
docs: update README for v2.0.0 (CloakBrowser, fetch_feed, Scrapling 0…
2 parents d2ef1b6 + 59504bb commit b22ef4b

1 file changed

Lines changed: 73 additions & 10 deletions

File tree

README.md

Lines changed: 73 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
**Remote MCP server for web scraping with anti-bot evasion**
66

7-
Stealth HTTP fetching · Headless browser · Cloudflare bypass · CSS selectors · YouTube transcripts · Markdown conversion
7+
Stealth HTTP fetching · Headless browser · CloakBrowser CDP · Cloudflare bypass · CSS selectors · RSS/Atom feeds · YouTube transcripts · Markdown conversion
88

99
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
1010
[![Python 3.12+](https://img.shields.io/badge/Python-3.12%2B-3776AB?logo=python&logoColor=white)](https://python.org)
@@ -43,6 +43,7 @@ _Claude's built-in `web_fetch` fails on GitHub blob URLs, Cloudflare-protected s
4343
- [Tech Stack](#tech-stack)
4444
- [Project Structure](#project-structure)
4545
- [How It Works](#how-it-works)
46+
- [CloakBrowser Stealth Engine (Optional)](#cloakbrowser-stealth-engine-optional)
4647
- [Configuration](#configuration)
4748
- [Local Development](#local-development)
4849
- [Docker](#docker)
@@ -58,8 +59,9 @@ _Claude's built-in `web_fetch` fails on GitHub blob URLs, Cloudflare-protected s
5859
| Tool | Description | Speed |
5960
| --------------------- | ---------------------------------------------------------------------------- | -------- |
6061
| **`fetch_page`** | Fast HTTP request with stealth headers. Works for GitHub, docs, static pages | ~1-2s |
61-
| **`stealth_fetch_page`** | Real headless browser with anti-bot evasion. Bypasses Cloudflare, renders JS | ~5-15s |
62+
| **`stealth_fetch_page`** | Real headless browser with anti-bot evasion. Bypasses Cloudflare, renders JS. Uses CloakBrowser CDP when `COMPOSE_PROFILES=cloakbrowser`, Camoufox otherwise | ~5-15s |
6263
| **`extract_elements`** | Fetch a page and extract multiple elements via CSS selectors as structured JSON | ~1-2s |
64+
| **`fetch_feed`** | Fetch an RSS/Atom feed, filter by cutoff date and skip terms, return compact JSON | ~1-2s |
6365
| **`get_youtube_transcript`** | Fetch YouTube video transcripts/captions with language fallback | ~1-3s |
6466

6567
`fetch_page` and `stealth_fetch_page` support:
@@ -68,6 +70,13 @@ _Claude's built-in `web_fetch` fails on GitHub blob URLs, Cloudflare-protected s
6870
- **`to_markdown`** — convert HTML to readable Markdown (default: `true`)
6971
- Automatic truncation at 80,000 characters
7072

73+
`fetch_feed` supports:
74+
75+
- RSS 2.0 and Atom feeds
76+
- ISO 8601 cutoff datetime — only items newer than the cutoff are returned
77+
- `skip_terms` list to filter out sponsored posts or unwanted authors (case-insensitive)
78+
- HTML stripping from summaries, truncated to 400 characters per item
79+
7180
`get_youtube_transcript` supports:
7281

7382
- Standard watch URLs, `youtu.be` short links, and `/shorts/` URLs
@@ -310,6 +319,7 @@ If the third check produces no output, the server is not returning a `WWW-Authen
310319
| --------------- | ---------------------------------------------------------------- | --------------------------------------------- |
311320
| **MCP Server** | [FastMCP](https://gofastmcp.com) (PrefectHQ) | MCP SDK with built-in OAuth 2.1 / OIDCProxy |
312321
| **Scraping** | [Scrapling](https://github.com/D4Vinci/Scrapling) | Stealth headers + headless browser (Camoufox) |
322+
| **Stealth engine (opt.)** | [CloakBrowser](https://cloakbrowser.com) (`cloakhq/cloakbrowser`) | Chromium CDP backend for `stealth_fetch_page`; stronger Cloudflare bypass |
313323
| **HTML→MD** | [html2text](https://github.com/Alir3z4/html2text) | Clean Markdown conversion |
314324
| **ASGI Server** | [uvicorn](https://www.uvicorn.org) | Fast async Python server |
315325
| **Reverse Proxy** | [Caddy](https://caddyserver.com) | Auto HTTPS, IP allowlisting, OAuth path pass-through |
@@ -358,8 +368,9 @@ Shark-no-Kari/
358368
│ shark-no-kari │ FastMCP server (uvicorn :8000)
359369
│ │
360370
│ fetch_page() │ → Scrapling Fetcher (stealth HTTP)
361-
│ stealth_fetch() │ → Scrapling StealthyFetcher (headless browser)
371+
│ stealth_fetch() │ → Camoufox (default) or CloakBrowser CDP (optional)
362372
│ extract_elems() │ → Multi-selector structured extraction
373+
│ fetch_feed() │ → Scrapling Fetcher + feedparser (RSS/Atom)
363374
│ yt_transcript() │ → YouTube transcript API
364375
│ │
365376
│ html2text │ → Markdown conversion + truncation
@@ -374,13 +385,62 @@ Shark-no-Kari/
374385

375386
---
376387

388+
## CloakBrowser Stealth Engine (Optional)
389+
390+
`stealth_fetch_page` supports two interchangeable backends:
391+
392+
| Mode | Engine | When to use |
393+
|------|--------|-------------|
394+
| **Camoufox** (default) | Scrapling's `StealthyFetcher` — headless Firefox | Works out of the box, no extra services |
395+
| **CloakBrowser** | Dedicated Chromium instance reached via Chrome DevTools Protocol | Stronger bypass for sites that detect Camoufox |
396+
397+
### Enabling CloakBrowser
398+
399+
Set `COMPOSE_PROFILES=cloakbrowser` before starting the stack:
400+
401+
```bash
402+
# One-off
403+
COMPOSE_PROFILES=cloakbrowser docker compose up -d
404+
405+
# Or add to .env
406+
COMPOSE_PROFILES=cloakbrowser
407+
```
408+
409+
This starts the `kari-cloakbrowser` sidecar. Shark-no-Kari automatically detects the profile via `COMPOSE_PROFILES` and routes all `stealth_fetch_page` calls through CloakBrowser's CDP endpoint. When the profile is unset, the `kari-cloakbrowser` container never starts and Camoufox is used transparently — no caller-side changes needed.
410+
411+
### How It Works
412+
413+
```
414+
stealth_fetch_page()
415+
416+
├─ COMPOSE_PROFILES=cloakbrowser
417+
│ │
418+
│ ▼
419+
│ GET /json/version (timeout=5s)
420+
│ kari-cloakbrowser:9222
421+
│ │
422+
│ ▼
423+
│ StealthyFetcher.async_fetch(cdp_url=ws_url, block_ads=True)
424+
│ → Chromium via CloakBrowser + NordLynx SOCKS5 proxy
425+
426+
└─ (default)
427+
428+
429+
StealthyFetcher.fetch(block_ads=True)
430+
→ Camoufox headless Firefox
431+
```
432+
433+
---
434+
377435
## Configuration
378436

379437
### Environment Variables
380438

381439
| Variable | Default | Description |
382440
| ------------- | ------- | ------------------------------------------------------------------- |
383441
| `MCP_API_KEY` | _(empty)_ | Bearer token for auth. Empty = disabled (use Caddy IP allowlist). Cannot be set together with `OIDC_ENABLED=true`. |
442+
| `COMPOSE_PROFILES` | _(empty)_ | Set to `cloakbrowser` to start the CloakBrowser sidecar and enable the CDP stealth backend in `stealth_fetch_page`. |
443+
| `CLOAKBROWSER_CDP_URL` | `http://kari-cloakbrowser:9222` | CDP base URL of the CloakBrowser container. Override if running CloakBrowser on a different host or port. |
384444
| `PROXY_URL` | `socks5h://kari-nordlynx:1080` | SOCKS5 proxy fallback — retries via proxy when direct requests fail. Defaults to the bundled `nordlynx-proxy` sidecar container |
385445
| `NORDVPN_TOKEN` | _(empty)_ | NordVPN access token from [Nord Account > Manual setup](https://my.nordaccount.com/dashboard/nordvpn/manual-configuration/). Required for proxy fallback via `nordlynx-proxy` |
386446
| `NORDVPN_COUNTRY` | `Germany` | NordVPN server country used by `nordlynx-proxy` for the WireGuard tunnel |
@@ -420,7 +480,7 @@ source .venv/bin/activate
420480

421481
# Install dependencies
422482
pip install -r requirements.txt
423-
scrapling install # Downloads browser binaries (Camoufox, Playwright)
483+
scrapling install --force # Downloads/refreshes browser binaries (Camoufox, Playwright)
424484

425485
# Run the server (no auth for local dev)
426486
python src/server.py
@@ -453,16 +513,18 @@ Images are built automatically by CI and pushed to `ghcr.io/hainick/shark-no-kar
453513
| ---------------- | ------------------ | --------- | -------------------------------- |
454514
| `shark-no-kari` | `ghcr.io/hainick/shark-no-kari:latest` | 8000 (internal) | MCP server |
455515
| `nordlynx-proxy` | `edgd1er/nordlynx-proxy:latest` | 1080, 8888 (internal) | NordVPN WireGuard tunnel + local SOCKS5/HTTP proxy |
516+
| `kari-cloakbrowser` | `cloakhq/cloakbrowser` | 9222 (internal, `kari-internal` net) | Optional Chromium CDP stealth engine — only starts when `COMPOSE_PROFILES=cloakbrowser` |
456517
| `caddy` | `caddy:2-alpine` | 80, 443 | Reverse proxy, auto HTTPS, ACL |
457518

458519
### Dockerfile
459520

460521
Multi-step build:
461522

462-
1. Install system libraries required by headless browsers (NSS, GTK, etc.)
463-
2. Install Python dependencies from `requirements.txt`
464-
3. Run `scrapling install` to download browser binaries (Camoufox, Playwright)
465-
4. Copy `src/` and start with `python src/server.py`
523+
1. Install system libraries required by headless browsers (NSS, GTK, Unicode/CJK fonts, etc.)
524+
2. Install Python dependencies from `requirements.txt` (includes `scrapling>=0.4.9` and `cloakbrowser`)
525+
3. Run `scrapling install --force` to download/refresh browser binaries (Camoufox, Playwright)
526+
4. Run `python -m cloakbrowser install` to pre-download the CloakBrowser binary
527+
5. Copy `src/` and start with `python src/server.py`
466528

467529
The container uses `shm_size: 512mb` for headless browser shared memory.
468530

@@ -498,7 +560,7 @@ The test suite covers all four tools with mocked external calls (no network requ
498560

499561
### Build fails downloading browser binaries
500562

501-
The `scrapling install` step downloads ~200 MB of browser binaries. If it times out, retry:
563+
The `scrapling install --force` and `python -m cloakbrowser install` steps download browser binaries at build time. If either times out, retry:
502564

503565
```bash
504566
docker compose build --no-cache
@@ -552,7 +614,8 @@ Use `socks5h://` (not `socks5://`) so the proxy handles DNS resolution. If you d
552614

553615
## Acknowledgements
554616

555-
- [Scrapling](https://github.com/D4Vinci/Scrapling) — the scraping engine that powers both tools (stealth HTTP + headless browser via Camoufox)
617+
- [Scrapling](https://github.com/D4Vinci/Scrapling) — the scraping engine powering all fetch tools (stealth HTTP + headless browser via Camoufox)
618+
- [CloakBrowser](https://cloakbrowser.com) (`cloakhq/cloakbrowser`) — optional Chromium CDP stealth backend for `stealth_fetch_page`
556619
- [FastMCP](https://github.com/modelcontextprotocol/python-sdk) — official Python MCP SDK that makes building MCP servers painless
557620
- [Caddy](https://caddyserver.com) — automatic HTTPS and dead-simple reverse proxy config
558621
- [html2text](https://github.com/Alir3z4/html2text) — clean HTML-to-Markdown conversion

0 commit comments

Comments
 (0)