using-webctl
Scannednpx machina-cli add skill oaustegard/claude-skills/using-webctl --openclawUsing webctl in Claude.ai Containers
Browser automation using webctl CLI with automatic proxy authentication handling for Claude.ai's egress-controlled environment.
When This Skill Applies
- User requests browser automation, web scraping, or page interaction
- webctl commands fail with
ERR_TUNNEL_CONNECTION_FAILED - Playwright/Chromium needs to work through authenticated HTTP proxy
Core Problem
Claude.ai containers route traffic through an authenticated egress proxy (HTTP_PROXY env var with JWT credentials). Chromium doesn't properly handle proxy authentication for HTTPS CONNECT tunnels, causing all HTTPS navigation to fail even though curl works.
Solution
A local forwarding proxy (port 18080) intercepts Chromium connections and injects Proxy-Authorization headers before forwarding to the real egress proxy.
Setup Procedure
1. Install webctl
pip install webctl --break-system-packages
webctl setup # Downloads Chromium if needed
2. Deploy Auth Proxy Module
Copy scripts/auth_proxy.py to webctl's daemon directory:
cp /mnt/skills/user/using-webctl/scripts/auth_proxy.py \
/usr/local/lib/python3.12/dist-packages/webctl/daemon/
3. Patch Session Manager
Apply this patch to /usr/local/lib/python3.12/dist-packages/webctl/daemon/session_manager.py:
Find the context creation block (around line 104):
# Create context
context = await browser.new_context(
storage_state=storage_state, viewport={"width": 1280, "height": 720}
)
Replace with:
# Create context with proxy from env (with auth handling)
from .auth_proxy import get_local_proxy_url
proxy_url = get_local_proxy_url()
proxy_config = {"server": proxy_url} if proxy_url else None
context = await browser.new_context(
storage_state=storage_state,
viewport={"width": 1280, "height": 720},
proxy=proxy_config
)
4. Verify
webctl start --mode unattended
webctl --quiet navigate "https://github.com"
webctl snapshot --interactive-only --limit 10
webctl stop --daemon
Quick Reference
Session Management
webctl start --mode unattended # Headless browser
webctl stop --daemon # Full shutdown
webctl status # Current state + console error counts
Navigation
webctl navigate "https://..."
webctl back / webctl forward / webctl reload
Observation
webctl snapshot --interactive-only --limit 30 # Buttons, links, inputs
webctl snapshot --within "role=main" # Scope to container
webctl query "role=button name~=Submit" # Debug queries
webctl screenshot --path shot.png
Interaction
webctl click 'role=button name~="Submit"'
webctl type 'role=textbox name~="Email"' "user@example.com"
webctl type 'role=textbox name~="Search"' "query" --submit
webctl select 'role=combobox name~="Country"' --label "Germany"
Query Syntax
role=button— By ARIA rolename~="partial"— Contains (preferred, more robust)name="exact"— Exact matchnth=0— Select first when multiple matches
Wait Conditions
webctl wait network-idle
webctl wait 'exists:role=button name~="Continue"'
webctl wait 'url-contains:"/dashboard"'
Troubleshooting
ERR_TUNNEL_CONNECTION_FAILED
Auth proxy not loaded. Verify:
auth_proxy.pyexists in webctl daemon directory- Session manager is patched
- Restart daemon:
webctl stop --daemon && webctl start --mode unattended
Multiple matches error
Add specificity or use nth=0:
webctl click 'role=link name="Sign in" nth=0'
Verify proxy is running
netstat -tlnp | grep 18080
Limitations
- Patch is session-local (container resets clear it)
- Only allowed domains in network config are accessible
- No Firefox support (download blocked by egress policy)
Domain Restrictions
Check <network_configuration> in system prompt for allowed domains. Common allowed: *.github.com, *.bsky.app, allowed API endpoints.
Output Filtering
Reduce context consumption:
webctl snapshot --interactive-only --limit 30 # Cap elements
webctl snapshot | grep -i "submit" # Unix filtering
webctl --quiet navigate "..." # Suppress events
Source
git clone https://github.com/oaustegard/claude-skills/blob/main/using-webctl/SKILL.mdView on GitHub Overview
This skill enables browser automation inside Claude.ai containers using webctl, with a local forwarding proxy that injects Proxy-Authorization headers to pass through the authenticated egress proxy. It supports Playwright/Chromium navigation and web scraping behind the container proxy. The setup intercepts Chromium connections on port 18080 and patches the session manager to route traffic through the proxy.
How This Skill Works
Install webctl and its Chromium runtime, then deploy a local auth proxy (auth_proxy.py) into webctl's daemon. Patch the session manager to obtain a local proxy URL from the auth proxy and pass it to the Chromium context as a proxy configuration. This enables authenticated proxy handling for HTTPS connections in Claude.ai containers, improving reliability when navigating through the egress proxy.
When to Use It
- User requests browser automation, web scraping, or page interaction inside Claude.ai containers.
- webctl commands fail with ERR_TUNNEL_CONNECTION_FAILED indicating missing or misloaded proxy auth.
- Playwright/Chromium must operate through an authenticated HTTP proxy in the container environment.
- Operating in an egress-controlled setup where direct browser traffic is blocked or filtered.
- Need reliable, headless browser tasks (navigation, interaction, and screenshots) behind the proxy.
Quick Start
- Step 1: Install webctl and set up Chromium: pip install webctl --break-system-packages; webctl setup
- Step 2: Deploy the auth proxy: copy scripts/auth_proxy.py to the webctl daemon directory
- Step 3: Patch the session manager to use the local proxy from auth_proxy and verify with webctl navigate
Best Practices
- Install webctl with --break-system-packages to ensure Chromium dependencies are available.
- Copy scripts/auth_proxy.py to the webctl daemon directory as instructed.
- Patch session_manager.py to use get_local_proxy_url() and set proxy in browser context.
- Verify setup by starting the daemon, navigating to a URL, and taking a snapshot.
- If ERR_TUNNEL_CONNECTION_FAILED persists, confirm the auth proxy is loaded and the daemon is restarted.
Example Use Cases
- Navigate to a public site (e.g., https://github.com) from within a Claude.ai container and verify via a snapshot.
- Perform a web scraping task behind the authenticated proxy and extract dynamic content.
- Use webctl query and click actions to interact with a SPA behind the proxy (e.g., login flow).
- Capture a visual test (screenshot) of a page to validate layout behind the egress proxy.
- Diagnose proxy loading issues by checking port 18080 and confirming auth_proxy.py presence in the daemon directory.