When Your Build Script Just Won’t Connect
So you’re happily coding away in Claude Code for Web, everything’s going great, and then you run npm run build—and it fails with a cryptic getaddrinfo EAI_AGAIN error. Sound familiar?
Here’s the thing: Claude Code for Web runs in a sandboxed container where all internet traffic flows through an authenticated proxy. Most languages handle this gracefully. Node.js… well, Node.js marches to its own drum.
The good news? There’s a simple fix. Actually, there are a few.
First Things First: Internet Access Requires Configuration
Before we dive in, there’s something important to know: Claude Code for Web only allows access to a whitelist of URLs by default—mostly package repositories like npm, PyPI, and crates.io. The broader internet is locked down.
Unlike the CLI version of Claude Code, which prompts you for permission when it needs to access a new URL, Claude Code for Web doesn’t ask. You need to configure the right network access settings before starting your session. If your build process needs to reach APIs or external services that aren’t on the default whitelist, you’ll need to enable broader internet access in your project settings. See the official documentation for more details on networking restrictions.
But here’s the catch: even after you’ve configured internet access correctly, Node.js will still fail with those same getaddrinfo EAI_AGAIN errors. That’s because Node.js doesn’t respect the proxy environment variables that the sandbox sets up. So you’ve done everything right on the permissions side—the problem is Node.js itself.
That’s what the rest of this post is about: getting Node.js to actually use the proxy that’s already there and waiting.
Why Node.js Is the Odd One Out
Claude Code sets up all the standard proxy environment variables:
HTTP_PROXY=http://...
HTTPS_PROXY=http://...
Python reads these automatically. So does Go. Ruby, Rust, PHP’s curl—they all just work. Even Bun (Node’s speedy cousin) handles it out of the box.
But Node.js? Nope. Neither the built-in https module nor the native fetch() API respects these environment variables. It’s a historical design decision that predates the container era, and it means your build tools, API calls, and anything else that touches the network might fail in the sandbox.
// This fails in Claude Code for Web:
await fetch('https://example.com');
// Error: getaddrinfo EAI_AGAIN example.com
// This also fails:
const https = require('https');
https.get('https://example.com', callback);
// Same error
The Fix: A Simple Preload Script
Here’s a drop-in solution. Create a file called proxy-fix.cjs in your project root:
// proxy-fix.cjs - Proxy support for Claude Code for Web
// Just run: npm install global-agent undici
const isClaudeCodeWeb = process.env.CLAUDE_CODE_ENTRYPOINT === 'remote' ||
(process.env.CLAUDECODE === '1' && process.env.CLAUDE_CODE_REMOTE === 'true');
const proxyUrl = process.env.HTTPS_PROXY || process.env.https_proxy;
const needsFix = isClaudeCodeWeb && proxyUrl;
if (needsFix) {
// Fix fetch() using undici's ProxyAgent
try {
const { ProxyAgent, setGlobalDispatcher } = require('undici');
setGlobalDispatcher(new ProxyAgent(proxyUrl));
} catch (e) { /* undici not installed */ }
// Fix https/http modules using global-agent
try {
const { bootstrap } = require('global-agent');
bootstrap();
} catch (e) { /* global-agent not installed */ }
}
Then install the dependencies:
npm install global-agent undici
Now you can use it in a few ways:
Option 1: Preload for a single command
NODE_OPTIONS="--require ./proxy-fix.cjs" npm run build
Option 2: Add to your package.json scripts
{
"scripts": {
"build": "node --require ./proxy-fix.cjs ./node_modules/.bin/your-build-tool",
"build:web": "NODE_OPTIONS='--require ./proxy-fix.cjs' npm run build"
}
}
Option 3: Require it at the top of your entry file
require('./proxy-fix.cjs');
// ... rest of your code
The beauty of this approach is that it only activates when it detects the Claude Code environment. On your local machine or in other CI/CD systems, it does nothing.
What Actually Works (The Quick Reference)
Here’s the cheat sheet for HTTP requests in Claude Code for Web:
| Method | Works? | Notes |
|---|---|---|
fetch() with undici ProxyAgent | Yes | Tested and working |
https.get() with global-agent | Yes | Tested and working |
axios with https-proxy-agent | Yes | Works great |
Native fetch() | No | Ignores proxy |
Native https.get() | No | Ignores proxy |
npm install / npm run | Yes | npm handles proxy itself |
Wait, npm works? Yes! Here’s a pleasant surprise: npm and npx handle proxy configuration internally, so package installation and running npm scripts work fine. The problem is when your code tries to make HTTP requests during a build.
Detecting Claude Code for Web
Want to conditionally apply fixes only when running in the sandbox? Check for these environment variables:
const isClaudeCodeWeb = process.env.CLAUDECODE === '1';
// Or be more specific - check for remote/web mode:
const isClaudeCodeWeb = process.env.CLAUDE_CODE_ENTRYPOINT === 'remote';
// Or combine multiple checks:
const isClaudeCodeWeb = process.env.CLAUDECODE === '1' &&
process.env.CLAUDE_CODE_REMOTE === 'true';
Here’s the full set of Claude-specific environment variables available:
CLAUDECODE=1 # Simple flag - always set
CLAUDE_CODE_ENTRYPOINT=remote # "remote" for web, different for CLI
CLAUDE_CODE_REMOTE=true # Running in web/remote mode
CLAUDE_CODE_REMOTE_ENVIRONMENT_TYPE=cloud_default # Environment type
CLAUDE_CODE_VERSION=2.0.50 # Claude Code version
CLAUDE_CODE_SESSION_ID=session_xxx # Unique session identifier
CLAUDE_CODE_CONTAINER_ID=container_xxx # Container identifier
IS_SANDBOX=yes # Generic sandbox indicator
The CLAUDE_CODE_ENTRYPOINT variable is particularly useful—it’s set to remote when running in Claude Code for Web, which distinguishes it from the CLI version.
Alternative: Just Use Bun
Plot twist: if you can switch to Bun, you don’t need any of these workarounds. Bun’s fetch() respects proxy environment variables out of the box:
// This just works in Bun, even in Claude Code for Web:
const response = await fetch('https://example.com');
console.log(response.status); // 200
Bun 1.3.2 is pre-installed in the sandbox. If your project is compatible, it might be the path of least resistance.
Other Languages: The Scorecard
While we’re here, let’s see how other languages fare:
| Language | Version | Works Out of the Box? |
|---|---|---|
| Python (urllib/requests) | 3.11 | Yes |
| Ruby (net/http) | 3.3 | Yes |
| Go (net/http) | 1.24 | Yes |
| Rust (reqwest) | 1.91 | Yes |
| PHP (curl) | 8.4 | Yes |
| Bun (fetch) | 1.3 | Yes |
| Node.js (native) | 22.21 | No - needs fix |
| Java (HttpClient) | 21 | No - needs fix |
Python, Go, Ruby, Rust—they all respect the standard HTTP_PROXY/HTTPS_PROXY environment variables. Node.js remains the rebellious teenager of the bunch.
TL;DR
-
Your
npm run buildfails in Claude Code for Web? It’s probably your code making HTTP requests, not npm itself. -
Quick fix: Install
global-agentandundici, createproxy-fix.cjs, and preload it withNODE_OPTIONS. -
Even quicker fix: Use Bun instead of Node.js if your project allows it.
-
Conditional detection: Check
process.env.CLAUDECODE === '1'to only apply fixes in the sandbox. -
npm/npx themselves work fine—they handle proxy configuration internally.
Happy building!