[DOCS/BUG] Browser automation tools (Playwright/Puppeteer) incompatible with web sandbox proxy
Summary
Browser automation tools like Playwright, Puppeteer, and Selenium cannot run in the Claude Code web sandbox due to the security proxy not supporting HTTPS CONNECT tunneling. This is a fundamental architectural limitation that should be documented to save users time.
Environment
- Claude Code: Web sandbox (claude.ai/code)
- Tool: Playwright v1.49.1 with Chromium v140.0.7339.16
- Test Date: 2025-11-16
Problem Description
The web sandbox's security proxy provides network isolation by mediating all outbound traffic through an HTTP proxy (visible as HTTPS_PROXY environment variable with JWT-based authentication). However, this proxy does not support the HTTP CONNECT method required by browsers for HTTPS tunneling.
Why This Matters
- Browser automation tools (Playwright, Puppeteer, Selenium) require CONNECT tunneling to access HTTPS sites
- The current proxy architecture only supports direct HTTP requests (e.g., curl, requests library)
- Users may waste significant time trying to configure browser automation in the sandbox
Reproduction Steps
- Install Playwright in web sandbox:
``bash``
uv run playwright install chromium
- Run any Playwright script accessing HTTPS sites:
```python
from playwright.sync_api import sync_playwright
with sync_playwright() as p:
browser = p.chromium.launch(headless=True)
page = browser.new_page()
page.goto('https://example.com') # Fails here
browser.close()
```
- Result:
ERR_TUNNEL_CONNECTION_FAILED
Error Messages Encountered
net::ERR_TUNNEL_CONNECTION_FAILED- Most common (HTTPS sites)net::ERR_NO_SUPPORTED_PROXIES- When credentials in proxy URL- HTTP 401 - When testing HTTP (not HTTPS) sites with JWT auth
Technical Analysis
What Works ✅
- HTTP tools like curl, requests, httpx (direct requests)
- Playwright installation
- All non-browser automation
What Doesn't Work ❌
- Any browser (Chromium, Firefox, WebKit) accessing HTTPS sites
- Playwright, Puppeteer, Selenium browser automation
- Any tool requiring CONNECT tunneling
Root Cause
From Anthropic's sandboxing docs:
"Network isolation: All outbound internet traffic passes through a proxy for security and abuse prevention purposes."
The security proxy:
- Uses JWT-based authentication in URL format
- Supports direct HTTP/HTTPS requests (standard proxy behavior)
- Does NOT support HTTP CONNECT method (browser tunneling)
This is by design for security, but creates incompatibility with browser automation.
Proposed Solutions
Option 1: Documentation (Immediate) ⭐
Add to sandbox documentation:
Browser Automation Limitations: Browser automation tools (Playwright, Puppeteer, Selenium) are not supported in the web sandbox environment. The security proxy does not support HTTPS CONNECT tunneling required by browsers. For web scraping, use HTTP libraries (requests, httpx) with HTML parsing (BeautifulSoup, lxml) instead, or run browser automation locally.
Option 2: Feature Enhancement (Future)
- Add CONNECT support to sandbox proxy (security implications to evaluate)
- Provide alternative browser automation pathway
- Offer Playwright MCP integration that works within sandbox constraints
Option 3: Workaround Guidance
Document recommended alternatives:
- Use
requests+ BeautifulSoup for HTML scraping - Use
httpxwith async support - Run browser automation locally, import results to sandbox
Impact
User Experience:
- Users attempting browser automation waste hours debugging
- No clear error message indicating architectural limitation
- Documentation doesn't mention this restriction
Use Cases Affected:
- Web scraping jobs
- End-to-end testing
- Screenshot/PDF generation
- Form automation
Related Issues
- #2256 - Tunnel proxy issues (corporate proxies)
- #1383 - Playwright MCP failures
- #5636 - Browser automation tools failing to launch
Recommendation
At minimum, update documentation to clearly state browser automation tools won't work in web sandbox and suggest alternatives. This would save users significant debugging time and set proper expectations.
---
Category: Documentation / Known Limitation
Priority: Medium (affects user experience, not a critical bug)
Effort: Low (documentation update) to High (architectural change)
Showing cached comments. Read the full discussion on GitHub ↗
9 Comments
Adding my use case: I want cloud agents to test preview deployments (e.g., Vercel previews) using Browserbase/Stagehand before committing. Even though Browserbase runs browsers remotely, agents still need WebSocket/CDP connections to control them - which gets blocked by the current proxy. This workflow works locally but not in web sessions, which defeats the purpose of autonomous cloud agents.
In fact very important issue. Does anyone has an elegant workaround?
I'm unable to run my automated Playwright tests in the sandbox, despite excluding the commands used.
I'm going to have to stop using the sandbox for this atm, which means my alternatives are either more dangerous, or more annoying.
This issue has been inactive for 30 days. If the issue is still occurring, please comment to let us know. Otherwise, this issue will be automatically closed in 30 days for housekeeping purposes.
It's a critical issue we need a fix or a workaround or get it documented atleast.
Would be great to have this.
We hit this exact problem running Playwright E2E tests in Claude Code's web sandbox and found a working set of workarounds. Sharing the strategy and key discoveries — the specifics will vary by framework, but the pattern is universal.
My main motivation was to allow Claude Code to build, and validate E2E tests when running in the cloud to make it easier to run 10s of high quality concurrent sessions. I also have it take screenshots with read file to inline into the chat, and post images to embed into the PRs for quick review.
After a lot of trial and error, Claude found a workaround that lets Playwright tests run against a localhost dev server, including loading external resources (fonts, CDNs, APIs). This also installs Chromium since I needed the latest version to match my Playwright version vs the pre-installed versions.
While it fixed my issue, _the facts may not be completely right, as Claude cooked up the summary below_ of its own workaround. Initially it did brute force a ton of options in, but I then had it test all combinations to figure out what was really needed to reduce the noise on flags that weren't impactful.
-----
The Core Insight
The browser can't reach the internet, but Node.js can (via the egress proxy). Playwright's
page.route()API lets you intercept requests at the network layer before Chromium tries to resolve DNS. So the strategy is: intercept external requests in Playwright, re-fetch them through Node.js usingundici.ProxyAgent, and hand the response back to the browser.This means your tests run against a localhost dev server, with external resources (fonts, CDN scripts, API calls) transparently proxied through Node.js.
The Three Things You Need
1. A Playwright route interceptor
Use
page.route()to match all non-localhost URLs. In the handler, fetch the URL usingundici.ProxyAgentpointed atprocess.env.HTTPS_PROXY, strip hop-by-hop headers, androute.fulfill()with the response. Wire this into a custom Playwright fixture so every test gets it automatically.2. A Node.js proxy bootstrap for your dev server
Node 22's built-in
fetch()(undici) does not honorHTTP_PROXY/HTTPS_PROXYenv vars by default. If your dev server makes any server-side fetches (SSR, API routes, font loading), they'll fail withEAI_AGAIN. Fix this with a small preload script that callsundici.setGlobalDispatcher(new EnvHttpProxyAgent()), loaded viaNODE_OPTIONS="--require ./proxy-bootstrap.cjs"in your Playwright config'swebServer.env.3. A
no_proxyoverride forplaywright installThe container sets
no_proxy=*.googleapis.com,*.google.com,...by default, which tells Node.js "bypass the proxy for these domains and connect directly." But DNS is completely broken without the proxy, so "connect directly" =EAI_AGAIN.Playwright downloads Chromium from
cdn.playwright.dev→ redirects tostorage.googleapis.com→ matches the*.googleapis.comexclusion → bypasses proxy → DNS fails.The fix: override
no_proxyto justlocalhostwhen installing:Important details:
no_proxymatters. Both undici andproxy-from-env(Playwright's library) prefer lowercase over uppercaseNO_PROXY. Setting only uppercase does nothing when lowercase is already set.no_proxy="localhost"is sufficient — no need for127.0.0.1.no_proxy=""doesn't work — empty string is falsy in JS, sono_proxy || NO_PROXYfalls through to the uppercase default which still has*.googleapis.com.npx playwright testmay not need this override if your Playwright config injects the proxy bootstrap viaNODE_OPTIONSinto the dev server process (it setsno_proxyinternally).Playwright Config Tips
args: ['--no-proxy-server']so the browser doesn't try to use the proxy itself (your route interceptor handles it at the application level).webServerconfig, keep proxy env vars for the dev server process (it needs them to reach external APIs), but inject the proxy bootstrap viaNODE_OPTIONS.pnpm exec playwright(ornpx playwright) — never the bareplaywrightcommand. The container has a globally installed version that may not match your project's@playwright/test, causing "browser not found" errors.Google Fonts Gotcha
If your app uses Google Fonts, they'll 403 from this environment — Google blocks requests from datacenter/proxy IPs. Bunny Fonts is a privacy-focused, open-source font CDN that mirrors the Google Fonts API with identical URL structure — same query params, same CSS format, same font files. It's a one-line URL rewrite away: swap
fonts.googleapis.com→fonts.bunny.netin your route interceptor. Also rewrite URLs inside CSS response bodies, since Google Fonts CSS contains embeddedurl()references pointing back tofonts.gstatic.comfor the actual font files.Quick Start
Limitations
page.goto('https://example.com')directly — the interceptor proxies sub-resources loaded by the page.playwright screenshotof external URLs won't work without additional plumbing.This pattern —
page.route()+undici.ProxyAgent+no_proxyoverride — has been reliable for us running a full Nuxt + Playwright E2E suite in the sandbox. Hope it unblocks others hitting this wall.Weirdly this was working on June 19 and 22. It was working earlier today, then suddenly stopped and Chrome started hitting
net::ERR_CONNECTION_CLOSED.This is one of three issues documenting the same underlying gap (with #15583 and #73564): there's no way to run a browser in Claude Code cloud sessions, DIY or otherwise.
I've filed the feature-level ask at #75632. It proposes an opt-in, pre-installed headless Chromium scoped to localhost first, which sidesteps the CONNECT tunneling limitation described here entirely: verifying a dev server inside the sandbox never touches the egress proxy. External browsing is framed as a separate phase 2 given the security trade-offs you'd rightly flag with CONNECT support.
If browser verification in cloud sessions matters to your workflow, a 👍 over there helps it get triaged.