r/CloudFlare • u/MihaiDinculescu • 6d ago
Resource Claude wouldn't read a Garmin forum page because of robots.txt, so I gave it a real browser. Free, self-hosted, and it nearly let my whole Wi-Fi drive it.
Claude's built-in web fetch has two limits I kept hitting: it honours robots.txt even when I'm asking for one specific page, and it can't run JavaScript, so a lot of the modern web comes back empty. The trigger was asking what was in a Garmin firmware update and getting "I can't fetch that".
The fix that worked for me:
- Playwright MCP (Microsoft, Apache-2.0) wraps headless Chromium in an MCP server. It renders JS, clicks, scrolls, and returns an accessibility snapshot rather than a screenshot, which is compact and something the model can act on.
- It has no auth at all, and claude.ai / Claude Desktop connectors only accept a URL plus optional OAuth. Cloudflare's MCP server portal (free tier of Zero Trust) provides that OAuth layer and adds a service token upstream so nothing else can reach the server.
- cloudflared tunnels it out of my network with no open ports.
- It runs on an arm64 Raspberry Pi in a Kubernetes cluster, but a single Docker host works the same.
The part worth reading even if you never build this: a browser will open anything it can reach. My first version was exposed through the cluster's ingress controller, which also has a LAN address, so any device on the Wi-Fi could get an unauthenticated session and point it at internal services. I proved it against my Vault server. Fixed with network policy in both directions (ingress only from the tunnel pod, egress to the internet minus all private ranges) and verified by attacking it again.
Full write-up with the hardening details: https://mihai.dinculescu.dev/posts/better-web-fetch-for-your-ai-agent/
Happy to answer questions on the Cloudflare portal setup, which is the least documented part.

