Clash On But Browser/Terminal Still Direct? Proxy Not Working Guide
System proxy toggle is on, yet traffic still bypasses it — this usually isn't a Clash problem itself, but the fact that browsers and terminals each maintain their own separate proxy-detection logic. This article breaks the diagnosis into three lines: registry/network settings, browser plugin conflicts, and terminal environment variables, ending with a TUN mode fallback that doesn't depend on any single switch.
What the system proxy toggle actually changes
The "system proxy" toggle in the Clash client interface essentially writes an HTTP/HTTPS proxy configuration at the operating-system level — on Windows it writes the ProxyServer key in the registry, on macOS it writes the proxy settings for a network service, and on Linux desktop environments it writes GSettings or environment variables. This configuration only takes effect for **programs that respect the system proxy setting**, and whether an app respects it is entirely up to the app itself — the OS does not forcibly intercept every outbound connection to enforce this rule.
In other words, the system proxy is a "suggestion," not mandatory forwarding. Mainstream browsers (Chrome, Edge, Firefox in default mode) read this suggestion, while most command-line tools and some older software ignore it entirely, making connections directly through their own network stack. That's why, on the same machine, a browser may already be routed through the proxy while curl in a terminal still fails to connect directly, or connects fine but bypasses the proxy entirely.
Line one: system-level registry and network settings
This is the most fundamental layer. If it isn't configured correctly, nothing downstream — browser or terminal — will work either.
Windows: check Internet Options and the registry
After enabling the system proxy toggle, Clash writes to the current user's HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Internet Settings. The key fields are ProxyEnable (should be 1) and ProxyServer (should point to the address and port Clash is listening on, usually 127.0.0.1:7890). You can go directly to Settings → Network & Internet → Proxy and check whether the manual proxy settings match Clash's HTTP port.
- If the address/port field here is empty or holds an old value written by another piece of software, it means Clash never properly took over the system proxy — click the system proxy toggle in Clash again to reset it.
- If the address and port are correct but traffic still connects directly, the problem is most likely not at the system layer — move on to checking the specific program.
- Corporate domain policies and some security software forcibly lock proxy settings and reset them to empty on every restart. In that case, contact your administrator to allow write access to that registry key, or simply use TUN mode to bypass the issue.
macOS: check the network service's proxy configuration
On macOS, proxy settings live under each individual network service (Wi-Fi, Ethernet, etc.), not in one global location. Open System Settings → Network → the service you're using → Details → Proxies, and confirm that "Web Proxy (HTTP)" and "Secure Web Proxy (HTTPS)" are both checked, pointing to Clash's local listening port. With multiple network interfaces or services, it's easy to miss one — especially when both Ethernet and Wi-Fi are active, and only one service's proxy got updated while the other didn't.
Line two: why browsers ignore the system proxy
Browsers bypassing the proxy usually falls into one of four scenarios, listed in order of debugging priority:
- The browser has its own independent proxy mode. Firefox does not follow the system proxy by default — it uses its own manual configuration under "Network Settings." You need to manually select "Use system proxy settings" in
about:preferences, otherwise it makes no difference whether Clash is on or off. - A proxy-management extension is installed. Extensions like SwitchyOmega take over the browser's proxy decisions. Even if the system proxy already points to Clash, if the extension is set to "direct connection" or another address, the browser actually uses the extension's configuration, not the system's. This is the easiest conflict to overlook — temporarily disable all proxy-related extensions first to confirm whether traffic routes through the proxy at all, then decide whether the extension needs separate configuration.
- The browser has a built-in VPN or "secure browsing" acceleration feature. Some browsers (especially certain regional builds) include a network-acceleration toggle that bypasses the system proxy and connects directly. If nothing seems to work no matter what you configure, check the browser's own settings for such a feature and turn it off.
- Misconfigured PAC script mode. If Clash is using an auto-configuration script (PAC) instead of a fixed HTTP proxy, the browser needs to be able to fetch that PAC file successfully. Try visiting the PAC address directly in the browser (typically
http://127.0.0.1:<port>/proxy.pac) — if it fails to load, the PAC service isn't running, and switching to a fixed HTTP proxy mode is more reliable.
Suggested order: use the browser's built-in "network diagnostics" or visit a domain known to be hit by a rule, and watch whether that connection appears in Clash's connection panel. If it appears but is marked as direct, the issue is in the rules or proxy group; if it doesn't appear at all, the browser never sent the request to Clash — go back through the four points above.
Line three: why terminals ignore the system proxy
The terminal environment is the most commonly misunderstood layer — many people assume that turning on the system proxy automatically makes command-line tools follow it, but Linux and macOS terminal toolchains generally don't read GUI proxy settings at all. They look at **environment variables** instead.
Standard environment variable checklist
Most command-line tools that follow Unix conventions (curl, wget, git, package managers, etc.) read the following environment variables:
export http_proxy="http://127.0.0.1:7890"
export https_proxy="http://127.0.0.1:7890"
export all_proxy="socks5://127.0.0.1:7891"
export no_proxy="localhost,127.0.0.1,.local"
These lines only take effect in the current terminal session and disappear once the window closes. For persistence, add them to ~/.zshrc, ~/.bashrc, or your shell's startup script, and run source once to apply them immediately. Windows Command Prompt and PowerShell work similarly — use $env:HTTP_PROXY / $env:HTTPS_PROXY for the current session, or set them permanently through system environment variables.
Common pitfalls
- Inconsistent casing. A few programs only read the uppercase
HTTP_PROXY, others only the lowercasehttp_proxy— the safest approach is to set both. - Mixing up SOCKS and HTTP ports. Clash usually listens on an HTTP port and a SOCKS5 port simultaneously (or a single mixed port in mixed-port mode). The protocol prefix in the environment variable needs to match the actual port type — using the wrong protocol prefix causes the connection to fail outright rather than simply bypassing the proxy.
- Environment variables in Docker containers or SSH sessions are independent. Setting a proxy on the host doesn't get inherited by containers or remote SSH sessions by default — you need to configure it separately inside the container/remote environment, or pass it explicitly with the
-eflag. - Package managers have their own config files. For example, npm requires
npm config set proxyset separately, and git requiresgit config --global http.proxy. Even with environment variables set correctly, these tools may override them with a different value stored in their own config file.
| Tool | Reads env vars | Extra config needed |
|---|---|---|
| curl / wget | Yes | None |
| git | No (by default) | http.proxy setting |
| npm / yarn | No (by default) | proxy / https-proxy setting |
| docker CLI | Yes (needs per-container setup) | Container env vars or daemon.json |
| Python requests | Yes | None (follows standard env vars) |
TUN mode: a fallback that doesn't depend on any single switch
If, after checking all three lines above, a handful of programs still stubbornly refuse to use the proxy — or you'd simply rather not configure environment variables and browser extensions one by one — the more thorough approach is switching to TUN mode. TUN mode creates a virtual network adapter on the system and intercepts all outbound traffic at the network layer, no longer relying on whether an application reads the system proxy setting or environment variables. In theory it covers almost every network request, including background services and game clients.
Enabling TUN mode generally requires: running the client with administrator/root privileges, enabling the tun field in the config, and confirming that stack (e.g. gvisor or system) is compatible with your local network environment. Once enabled, the system proxy toggle can stay off, since traffic is already intercepted at a lower level — having both on at the same time usually doesn't conflict, but there's no need to stack them.
tun:
enable: true
stack: gvisor
auto-route: true
auto-detect-interface: true
Troubleshooting flow summary
When you run into "system proxy is on but not working," work through the following order instead of poking at random settings:
- First check Clash's connection panel to see whether the relevant request shows up at all — if it doesn't, traffic never reached Clash in the first place, so check whether the system proxy configuration was actually written correctly.
- For browser issues, check proxy-management extensions and built-in network-acceleration features first — these two are the most commonly overlooked.
- For terminal issues, first confirm the environment variables actually took effect in the current session, then check whether the specific tool follows environment variables or needs its own config file.
- When checking each program individually gets too costly, or when many programs don't follow standard proxy logic, just switch to TUN mode as a fallback instead of adapting each one separately.
System proxy, browser extensions, environment variables, and TUN mode are essentially four independent yet stackable ways of taking over traffic. Figuring out which layer the problem is actually in will get you to a fix far faster than blindly restarting the client.