How to observe, intercept, and capture network traffic from the claw runtime using the Docker proxy setup.
- Docker or Podman with Compose support
- An
ANTHROPIC_API_KEYset in your environment or a.envfile
cd docker
export ANTHROPIC_API_KEY=sk-ant-...
podman-compose up --buildThis starts two services on a shared bridge network:
| Service | Port | Purpose |
|---|---|---|
mitmproxy |
8080 | HTTPS proxy (CONNECT-capable) |
mitmproxy |
8081 | Web UI for inspecting flows |
claw |
— | The runtime, routing all traffic through the proxy |
Open http://localhost:8081 in your browser. All intercepted HTTP/S requests and responses are displayed in real time.
podman logs -f docker_mitmproxy_1This streams every request/response to your terminal in mitmdump format.
The claw-net bridge network is visible to the host. Capture on the bridge interface:
# Find the interface name
IFACE=$(ip link | grep -oP 'br-\w+' | head -1)
# Capture all traffic on the bridge
sudo tcpdump -i "$IFACE" -w claw-traffic.pcap
# Or open it live in Wireshark
sudo wireshark -k -i "$IFACE"Note: traffic between claw and mitmproxy is unencrypted HTTP on the bridge (the TLS termination happens at mitmproxy). Traffic from mitmproxy to upstream servers is encrypted.
To decrypt mitmproxy's outbound TLS in Wireshark, export the SSLKEYLOGFILE from inside the mitmproxy container:
# Start mitmproxy with key logging
podman-compose run -e SSLKEYLOGFILE=/capture/sslkeys.log mitmproxy
# In Wireshark: Edit > Preferences > Protocols > TLS > (Pre)-Master-Secret log filename
# Point it at: ./capture/sslkeys.logFor offline analysis, enable built-in pcap capture:
ENABLE_PCAP=true podman-compose uppcap files are written to the capture/ directory (or wherever CAPTURE_DIR points):
capture/claw-20260401-142756.pcap
Open these with Wireshark or tshark:
tshark -r capture/claw-20260401-142756.pcap
wireshark capture/claw-20260401-142756.pcapmitmproxy generates a self-signed CA certificate on first start. The claw entrypoint automatically:
- Waits for the CA cert to appear at
/mitmproxy-data/mitmproxy-ca-cert.pem - Combines it with the system CA bundle
- Sets
SSL_CERT_FILE,NODE_EXTRA_CA_CERTS,REQUESTS_CA_BUNDLE,CURL_CA_BUNDLE,CCR_CA_BUNDLE_PATH, andCCR_SYSTEM_CA_BUNDLE
The CA cert persists in the mitmproxy-data Docker volume across restarts.
Mount your CA cert over the mitmproxy data directory:
# In docker-compose.yml, replace the mitmproxy-data volume with:
volumes:
- ./my-certs:/root/.mitmproxyPlace your mitmproxy-ca-cert.pem and mitmproxy-ca.pem (private key) in ./my-certs/.
| Variable | Value | Purpose |
|---|---|---|
HTTPS_PROXY |
http://mitmproxy:8080 |
Route HTTPS through proxy |
HTTP_PROXY |
http://mitmproxy:8080 |
Route HTTP through proxy |
NO_PROXY |
localhost,127.0.0.1,::1 |
Bypass list (minimal) |
CLAW_NO_PROXY_OVERRIDE |
localhost,127.0.0.1,::1 |
Overrides the hardcoded bypass list in the runtime so that anthropic.com, github.com, etc. are proxied |
| Variable | Value | Purpose |
|---|---|---|
CLAW_FORCE_HTTP_TRANSPORT |
true |
Downgrade WebSocket MCP transports to HTTP so they route through the proxy |
Set this in the claw service environment if you need to inspect MCP WebSocket traffic:
environment:
- CLAW_FORCE_HTTP_TRANSPORT=true| Variable | Default | Purpose |
|---|---|---|
ENABLE_PCAP |
false |
Write pcap files inside the mitmproxy container |
CAPTURE_DIR |
./capture |
Host directory for pcap output |
The claw container starts before mitmproxy has finished initializing. This usually resolves by restarting:
podman-compose restart clawIf it persists, check that the mitmproxy-data volume is shared correctly:
podman volume inspect docker_mitmproxy-dataCheck that CLAW_NO_PROXY_OVERRIDE is set. Without it, the runtime's hardcoded NO_PROXY list bypasses anthropic.com, github.com, and other common hosts.
WebSocket connections use CONNECT tunneling and upgrade to a persistent connection that mitmproxy can observe but not fully decode. Set CLAW_FORCE_HTTP_TRANSPORT=true to downgrade MCP WebSocket transports to HTTP for full request/response inspection.
The stack includes a LiteLLM proxy that sits between claw and upstream LLM providers. This lets you swap backends without changing claw's configuration.
claw --> litellm --> upstream provider (Anthropic, OpenAI, Ollama, etc.)
\ |
\ v
+--> mitmproxy (observes litellm's outbound traffic)
Edit docker/litellm-config.yaml to configure backends. The default config points at a local Ollama instance on the host.
To use a different backend, uncomment the relevant section and set the API key:
# Anthropic
ANTHROPIC_API_KEY=sk-ant-... podman-compose up
# GitHub Models
GITHUB_TOKEN=ghp_... podman-compose up
# Local Ollama (default, no key needed)
podman-compose upPass the model name as defined in litellm-config.yaml:
podman-compose run claw claw --model qwen2.5:32bLiteLLM exposes its API on port 4000. You can check available models:
curl http://localhost:4000/v1/models -H "Authorization: Bearer sk-litellm-dev"- claw -> litellm: Internal network, bypasses mitmproxy (litellm is in
NO_PROXY) - litellm -> upstream: Outbound HTTPS, visible in mitmproxy if litellm is configured to use the proxy
- claw -> mitmproxy: Only for claw's own non-LLM traffic (tool downloads, git, etc.)