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
422482pip 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)
426486python 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
460521Multi-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
467529The 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
504566docker 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