Codex CLI Behind a Corporate Proxy: PAC/WPAD, CA Certs & HTTPS_PROXY (2026)
Codex CLI ignores PAC/WPAD proxies and hangs on connect. Fix it in 4 steps: resolve the PAC, set HTTPS_PROXY, add your CA cert. 8 common errors + a Node note.
If your laptop can open ChatGPT in a browser but codex sits there doing nothing on the first request, the network is not broken and neither is Codex. Codex CLI doesn’t read your PAC file or discover WPAD the way your browser does, so a machine that browses the web fine can still leave codex hanging on the first request. This guide gets you from that dead terminal to a working agent, and it explains why the fix is a manual HTTPS_PROXY even in 2026.
The 30-Second Answer
| What you can do | Route Codex CLI through an HTTP/HTTPS corporate proxy, trust a TLS-inspecting proxy’s private CA, and keep internal hosts off the proxy |
| What you can’t | Make Codex auto-discover the proxy from PAC/WPAD, or rely on SOCKS5 for streaming traffic |
| Time required | 10-15 minutes once you know your proxy host and CA path |
| What you need | @openai/codex installed, Node.js 16+, your proxy’s host:port, and (if TLS is inspected) the corporate root CA in PEM format |
The whole job is four moves: find the real proxy the PAC points to, export HTTPS_PROXY/HTTP_PROXY/NO_PROXY, hand Codex the corporate CA with CODEX_CA_CERTIFICATE, then verify with RUST_LOG=debug. The rest of this page is the detail behind each move and the errors you hit along the way.
What You Can Do After This Setup (And What You Can’t)
After you finish, Codex will send its API calls out through the same proxy your browser uses, survive a TLS-inspecting middlebox, and skip the proxy for internal Git servers and package registries. That covers the large majority of locked-down enterprise networks.
It will not turn Codex into a browser. Codex still won’t parse a PAC script, still won’t answer a WPAD broadcast, and still won’t reliably stream over SOCKS5. If your security team only ever hands out proxy settings through group policy and a PAC URL, you are the one who has to translate that into an environment variable. That translation is the actual work, and it is the part every “just set HTTPS_PROXY” answer skips.
Decision Frame: When to Use This Setup (and When NOT)
When to use it
- Your org pushes proxy config through PAC/WPAD or group policy, and CLI tools are on their own.
- The proxy does TLS inspection, so you see certificate errors from any tool that isn’t in the system trust store.
- You have five or more developers hitting the same proxy and want one shared, documented config instead of everyone guessing.
When NOT to use it
- You are on a home or coffee-shop network with no proxy at all. Setting
HTTPS_PROXYto a dead address will only break Codex. Unset it. - Your proxy is transparent (intercepts at the network layer with no client config). Then there is nothing to set, and a manual proxy variable can double-proxy the request.
- You only need to change your API key or endpoint. That is a one-line
config.tomledit, not a proxy project. Jump to the advanced section.
There is a clean stop rule for the proxy value itself. If curl -x http://your-proxy:port https://api.openai.com/v1/models returns an HTTP status instead of hanging, your proxy address is correct and you can stop tuning it. Everything after that is CA trust and authentication, which are separate problems with separate fixes.
Why Codex Ignores Your PAC/WPAD Proxy
Codex ignores PAC and WPAD because it is a CLI built on an HTTP client that only understands proxy environment variables, not the browser proxy stack. This one design fact causes most of the confusion, so it is worth being precise.
A PAC file (Proxy Auto-Config) is a small JavaScript program with a FindProxyForURL(url, host) function. Your browser runs that function for every request and gets back an answer like PROXY proxy.corp.example.com:8080 or DIRECT. WPAD (Web Proxy Auto-Discovery) is the protocol that tells the browser where that PAC file lives, usually through a DHCP option or a wpad.<yourdomain> DNS record. Browsers, Office apps, and the Windows networking stack all speak this. Per the PyPAC project’s overview of PAC files, almost no command-line tool does.
Codex’s HTTP client honors HTTPS_PROXY, HTTP_PROXY, ALL_PROXY, and NO_PROXY, which is the standard Unix convention shared by curl, git, and most language runtimes. There is an open request to make every Codex HTTP client honor the proxy environment variables consistently, but as of Codex 0.142.x setting those variables yourself is the supported path. So the chain that works for your browser (WPAD finds PAC, PAC returns a proxy, browser uses it) has no equivalent inside Codex. With no HTTPS_PROXY set, Codex attempts a direct connection, the firewall drops it, and you get a hang instead of a clean error. That silent drop is why this looks like a Codex bug when it is really a missing translation step.
| How it finds the proxy | Browser | Codex CLI |
|---|---|---|
Reads a PAC file (FindProxyForURL) | Yes | No |
| Auto-discovers via WPAD (DHCP/DNS) | Yes | No |
| Per-host proxy decision | Yes | No, one setting per session |
Reads HTTPS_PROXY / NO_PROXY env vars | Sometimes | Yes, this is the only path |
| Uses a custom CA from the system store automatically | Usually | No, needs CODEX_CA_CERTIFICATE |
It helps to see the two discovery paths side by side. Your browser, at startup, either reads a PAC URL your admin pushed through group policy, or it broadcasts a WPAD query over DHCP and DNS to find one. It then runs FindProxyForURL for every single URL, so different hosts can get different answers: the intranet returns DIRECT, the public internet returns PROXY. Codex does none of that. It reads four strings from the environment once, at launch, and applies them for the whole session. There is no per-host script, no auto-discovery broadcast, and no re-evaluation. This is why “my other tools work” is not evidence that Codex will: your other tools are almost certainly reading the same environment variables you are about to set, not the PAC file.
System Requirements
Before you touch proxy settings, confirm the basics, because a proxy will happily hide an unrelated install problem.
- Codex CLI installed with the correct package.
npm install -g @openai/codex. The unscopedcodexon npm is a different project, and installing it is the most common reasoncommand not foundor strange behavior shows up later. - Node.js 16 or newer for the npm install path (
@openai/codexdeclaresengines: node >=16). Older Node will fail the install before you ever reach the network. - Your proxy endpoint as
host:port. If you only have a PAC URL, the next step resolves it. - The corporate root CA in PEM format if your proxy inspects TLS. Ask your platform team for the “root CA bundle” or export it from the system keychain.
Step-by-Step: Point Codex at Your Corporate Proxy
Work through these in order. Each step has a check so you know it landed before moving on.
Step 1: Confirm the browser works but Codex doesn’t
Open your API host in a browser and watch it load, then run a bare request from the terminal.
# In a browser: https://api.openai.com/v1/models loads (401 JSON is fine)
# In the terminal, this should hang or fail fast if there's a proxy:
curl -sS --max-time 10 https://api.openai.com/v1/models ; echo "exit=$?"
If the browser reaches the host and the curl times out, you have the classic PAC-only setup. That gap is your whole problem, and the next step closes it.
Step 2: Resolve the PAC file to find the real proxy
You need the actual host:port the PAC would return for the API host. On macOS, read the auto-config URL, then test it. pactester ships with the pacparser package.
# macOS: find the PAC URL your system is configured with
scutil --proxy | grep -i ProxyAutoConfig
# Download it and ask which proxy serves the API host
curl -s "$PAC_URL" -o wpad.dat
pactester -p wpad.dat -u https://api.openai.com
# → PROXY proxy.corp.example.com:8080; DIRECT
On Windows, PowerShell reads the same auto-config URL and the effective WinHTTP proxy:
Get-ItemProperty 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Internet Settings' AutoConfigURL
netsh winhttp show proxy
Take the first PROXY host:port the resolver prints. That is the value you hard-code next. The pactester manual covers the flags if your PAC has multiple rules.
Step 3: Set HTTPS_PROXY, HTTP_PROXY, and NO_PROXY
Export the proxy for HTTPS and HTTP, and list every internal host that must skip the proxy in NO_PROXY.
export HTTPS_PROXY="http://proxy.corp.example.com:8080"
export HTTP_PROXY="http://proxy.corp.example.com:8080"
export NO_PROXY="localhost,127.0.0.1,.corp.example.com,.internal"
Note the proxy URL scheme is http:// even though it carries HTTPS traffic. That is correct; the scheme describes how you talk to the proxy, not what it forwards. If the proxy needs credentials, inline them:
export HTTPS_PROXY="http://alice:[email protected]:8080"
Put these lines in ~/.zshrc or ~/.bashrc so new shells inherit them. Missing NO_PROXY is a frequent cause of internal Git or registry calls breaking after the proxy goes in, so do not skip it.
Step 4: Trust the TLS-inspecting proxy’s CA
If your proxy inspects TLS, it re-signs every certificate with a private root CA. Codex will reject that until you tell it to trust the CA. Point CODEX_CA_CERTIFICATE at the PEM bundle before you log in.
export CODEX_CA_CERTIFICATE="/etc/pki/tls/certs/corporate-root-ca.pem"
# Fallback that also covers curl, git, and other tools:
export SSL_CERT_FILE="/etc/pki/tls/certs/corporate-root-ca.pem"
codex login
CODEX_CA_CERTIFICATE takes precedence and only affects Codex; when it is unset, Codex falls back to SSL_CERT_FILE, which most enterprise images already set. Codex’s advanced configuration docs describe the model-provider and endpoint options you will use in the advanced section below.
Step 5: Verify with RUST_LOG=debug
Confirm the variables are visible to Codex and watch the proxy negotiation.
env | grep -i proxy
RUST_LOG=debug codex exec "print the current date" 2>&1 | grep -i proxy
If the debug output shows your proxy host and the command returns a result, you are done. If it still fails, the error message tells you which layer broke, and the next section maps each message to a fix.
Common Errors During Setup (and Fixes)
Most proxy failures produce one of a handful of messages. Match yours here before you start changing random settings.
| Symptom | Likely cause | Fix |
|---|---|---|
codex hangs on the first request, browser works fine | No proxy env var; Codex can’t read PAC/WPAD | Resolve the PAC (Step 2), set HTTPS_PROXY |
error sending request ... connection refused/timed out | Wrong proxy host:port, or an internal host not in NO_PROXY | Recheck the value; add internal domains to NO_PROXY |
invalid peer certificate / unable to get local issuer certificate | TLS-inspecting proxy with a private root CA | Set CODEX_CA_CERTIFICATE to the corporate CA PEM |
407 Proxy Authentication Required | Proxy needs credentials | Add user:pass@ to the proxy URL, or use a relay for NTLM |
| UI stalls or streaming cuts out with a SOCKS5 proxy | SOCKS5 path is incomplete for streaming/websocket | Switch to an HTTP proxy via HTTPS_PROXY |
Sandboxed npm install fails with a cert error mid-run | CA not passed into the sandboxed subprocess | Also export NODE_EXTRA_CA_CERTS and SSL_CERT_FILE |
command not found: codex after install | Wrong package (codex vs @openai/codex) or PATH | Install @openai/codex; add npm global bin to PATH |
| Works in the terminal, fails when launched from an IDE | GUI apps don’t inherit your shell environment | Set the proxy vars in the app’s own launch environment |
Two of these deserve a note. The certificate error is the single most common blocker on inspected networks, and it is fixed by CA trust, not by disabling verification. Turning off TLS verification to “make it work” hands your traffic to whatever is on the wire, so do not do it. And the SOCKS5 stall is real: SOCKS5 works for some Codex paths but is inconsistent for the streaming responses the agent leans on, so prefer an HTTP proxy on a corporate network.
The Diagnosis Flow at a Glance
flowchart TD
A[Browser reaches internet, codex hangs] --> B{Proxy env vars set?}
B -->|No| C[Resolve PAC, set HTTPS_PROXY + NO_PROXY]
B -->|Yes| D{SSL / certificate error?}
C --> D
D -->|Yes| E[Set CODEX_CA_CERTIFICATE to corporate CA]
D -->|No| F{407 auth error?}
E --> F
F -->|Yes| G[Add user:pass@ or run a cntlm/px relay]
F -->|No| H[Run RUST_LOG=debug codex exec to trace]
When You Still Need HTTPS_PROXY (Even If the PAC Says DIRECT)
You still need HTTPS_PROXY whenever Codex has to reach a host that your PAC routes through a proxy, which on most corporate networks is every external API host. The PAC being clever does not help Codex, because Codex never runs the PAC. This trips people up in three specific situations worth calling out.
The first is split routing. Your PAC returns DIRECT for internal hosts and PROXY for the public internet. Everything internal works from the terminal without any variable, so you assume the network is open, then the first external API call hangs. The fix is to set HTTPS_PROXY for the external hosts and list the internal ones in NO_PROXY so they stay direct.
The second is the VPN with split tunneling. On the VPN, the PAC may send corporate traffic through a proxy and everything else direct, or the reverse. When you connect or disconnect, the effective proxy changes, but your exported variable does not. If Codex starts failing right after you toggle the VPN, re-resolve the PAC and update HTTPS_PROXY.
The third is the transparent-proxy assumption. Some networks intercept traffic at the router with no client config, so browsers need nothing. If yours does that, you may not need HTTPS_PROXY at all, and setting it to a nonexistent host will only break Codex. The curl test in the decision frame tells you which world you are in: if a bare curl to the API host works, you are transparent and should leave the variable unset.
The short version: set HTTPS_PROXY when the API host is proxied and unset it when the network proxies transparently. There is no in-between where Codex reads the PAC for you.
Team / Multi-Developer Configuration
Once one machine works, the goal is that the next developer does not repeat your afternoon. The pattern that scales is to separate the shared, non-secret config from the per-user secret.
Keep the proxy and CA values in a versioned profile fragment your team sources from their shell rc file:
# proxy.env — committed to the team dotfiles repo (no secrets here)
export HTTPS_PROXY="http://proxy.corp.example.com:8080"
export HTTP_PROXY="$HTTPS_PROXY"
export NO_PROXY="localhost,127.0.0.1,.corp.example.com,.internal"
export CODEX_CA_CERTIFICATE="/etc/pki/tls/certs/corporate-root-ca.pem"
Keep every API key out of that file and in a per-user variable each developer sets once. For proxies that need credentials, do not commit anyone’s password into HTTPS_PROXY; have each person add their own user:pass@ locally, or run a local auth relay so no credentials live in shared config at all.
| Config item | Where it lives | Shared or per-user |
|---|---|---|
Proxy host/port, NO_PROXY | proxy.env in dotfiles repo | Shared |
| Corporate CA path | proxy.env in dotfiles repo | Shared |
API key (OPENAI_API_KEY / OFOX_API_KEY) | Shell env, set once per machine | Per-user |
| Proxy credentials | Local user:pass@ or a relay | Per-user, never committed |
config.toml provider block | Dotfiles repo | Shared |
On NTLM or Kerberos proxies, the whole team needs a local relay because Codex cannot do that handshake. Run a per-machine relay such as cntlm or px, and point everyone’s HTTPS_PROXY at it:
# px handles enterprise NTLM auth; Codex talks plain HTTP to localhost
px --proxy=proxy.corp.example.com:8080 --port=3128 &
export HTTPS_PROXY="http://localhost:3128"
One rollout detail catches teams every time: a developer who runs Codex from an IDE terminal or a launcher instead of a login shell. GUI apps on macOS and Windows do not inherit the variables you set in ~/.zshrc, so the exact setup that works in Terminal fails inside the editor. Document this in your onboarding note. On macOS, set the variables in a launchd user agent or the app’s own environment; on Windows, use the system environment variables dialog so every process inherits them, not just new shells. Verify a fresh checkout works by opening a brand-new terminal and running RUST_LOG=debug codex exec "print ok" before you tell anyone the config is done.
Advanced: Custom base_url and Multi-Provider Routing
With the proxy and CA in place, Codex can now reach any OpenAI-compatible endpoint through that same corporate egress, not only api.openai.com. This is where a custom model provider in config.toml earns its keep.
Define a provider block pointing at an OpenAI-compatible gateway. The config reference documents each key:
# ~/.codex/config.toml
model_provider = "ofox"
model = "openai/gpt-5.4"
[model_providers.ofox]
name = "ofox OpenAI-compatible gateway"
base_url = "https://api.ofox.ai/v1"
env_key = "OFOX_API_KEY"
If you only want to move the built-in OpenAI provider to a different endpoint, set openai_base_url instead of writing a whole provider block. Either way, the request still leaves your machine through the HTTPS_PROXY you configured and still trusts the CA you set, so the proxy work carries over unchanged.
The reason a team reaches for this on a locked-down network is consolidation. Instead of asking the firewall team to allowlist several vendor API hosts and maintain several keys, you point Codex at one OpenAI-compatible gateway and swap models by changing a string. On ofox that means one endpoint and one key covering models like openai/gpt-5.4 alongside Claude, Gemini, and others, which keeps the proxy allowlist short. If you want to try a specific model first, the openai/gpt-5.4 model page has its current details. Traffic still flows through your corporate proxy; nothing here bypasses it.
FAQ
Does Codex CLI support PAC or WPAD proxy auto-config?
No. Codex reads HTTP_PROXY, HTTPS_PROXY, ALL_PROXY, and NO_PROXY, but it does not evaluate PAC files or discover a proxy over WPAD. You resolve the PAC yourself and put the result in HTTPS_PROXY.
Why does Codex hang when my browser can reach the internet? Your browser gets its proxy from a PAC file over WPAD, and Codex does not. With no proxy variable set, Codex opens a direct connection the firewall drops, so the request hangs until timeout.
How do I set a proxy for Codex CLI?
Export HTTPS_PROXY and HTTP_PROXY pointing at your proxy host and port, and set NO_PROXY for internal hosts. There is no proxy key in config.toml, so the environment variable is the path.
How do I fix an SSL certificate error in Codex behind a proxy?
A TLS-inspecting proxy presents a certificate signed by a private root CA that Codex does not trust. Point CODEX_CA_CERTIFICATE at your corporate root CA PEM before codex login. If unset, Codex falls back to SSL_CERT_FILE.
Does Codex CLI support SOCKS5 proxies?
Partly. SOCKS5 works for some paths but is inconsistent for streaming and websocket traffic, which Codex uses heavily. An HTTP proxy via HTTPS_PROXY is more reliable on a corporate network.
How do I configure a Codex proxy for a whole team?
Put the proxy and CA variables in a shared, non-secret profile fragment, and check a config.toml provider block into your dotfiles repo. Keep API keys and proxy credentials per-user, never committed.
What is the difference between HTTP_PROXY and HTTPS_PROXY for Codex?
HTTP_PROXY applies to plain http:// requests and HTTPS_PROXY to https:// requests. Codex API traffic is all HTTPS, so HTTPS_PROXY is the one that matters, but set both to the same value.
How do I authenticate through an NTLM or Kerberos proxy with Codex?
Codex cannot do NTLM or Kerberos auth directly. Run a local relay such as cntlm or px, then point HTTPS_PROXY at http://localhost:<relay-port>.
References
The corporate proxy problem is almost never Codex being broken; it is Codex being honest about speaking the one proxy dialect nobody configured for it, which is plain environment variables. Everything above was checked against these sources on 2026-07-05:- OpenAI Codex advanced configuration and config reference: https://developers.openai.com/codex/config-advanced
- OpenAI Codex proxy environment variable issue: https://github.com/openai/codex/issues/4242
- PyPAC “About PAC files” on PAC/WPAD behavior: https://pypac.readthedocs.io/en/latest/about_pac.html
pactestermanual page: https://manpages.ubuntu.com/manpages/focal/man1/pactester.1.html- ofox model catalog and docs snapshot: https://ofox.ai/models


