9 min read

System Proxy Is On But Not Working? Debug Browser and Terminal Separately

You flip on the system proxy switch, but traffic still goes direct — or the browser works while the terminal doesn't, or vice versa. The root cause is rarely Clash itself; it's usually whether the system proxy layer is actually wired up correctly. This guide splits the browser path from the terminal path and walks through both in the order you should check them.

Split "System Proxy" Into Two Separate Paths

The term "system proxy" makes it sound like a single unified switch, but on the OS level, proxy settings only apply to apps that actually honor the system proxy config — and "honoring" it splits into two completely independent paths:

  • Browser path: mainstream browsers (Chrome, Edge, Firefox, etc.) read the system's proxy settings by default on Windows/macOS. This path is controlled by the OS network settings panel.
  • Terminal/CLI path: tools like curl, git, and package managers don't read the system panel at all — they rely on environment variables like http_proxy and https_proxy. The system proxy toggle has zero effect on them.

This is exactly why so many people report "Clash is on but it's not working" — the setting simply never covers the terminal, and the real problem is that the terminal path was never configured. On the flip side, some people find the terminal works fine while the browser still goes direct — that usually means the system proxy setting itself wasn't written correctly, or it's being blocked by an exceptions list.

Once launched, a Clash client only does two things: listen on a local proxy port (HTTP/SOCKS/mixed), and route traffic to different nodes based on rules. Whether other programs on the system actually send their traffic to that port depends on whether the system proxy setting or environment variables are configured correctly — that part is the OS's job, not the Clash core's.

Step One: Confirm Clash Is Actually Listening

Before suspecting the system proxy setting or environment variables, confirm the port itself is reachable — this alone rules out half of all "false failures."

  1. Open the client's connection/port settings page and note the current HTTP port (7890 is the common default) and whether mixed port is enabled.
  2. Test the port directly from the command line, bypassing the system proxy switch entirely, just to confirm the listener exists:
    curl -x http://127.0.0.1:7890 https://www.google.com -I
    If you get back an HTTP response header (even a 301/302), the port itself is fine and the problem lies in the system proxy layer. If the connection is refused outright, the client isn't running or the port has been changed — fix that first before moving on.
  3. On Windows, use netstat -ano | findstr 7890; on macOS/Linux, use lsof -i :7890 to confirm the process holding that port is actually Clash and not something else that grabbed it first.
Port TypeCommon DefaultTypical Use
HTTP port7890Browser system proxy, most terminal tools
SOCKS port7891Clients that specifically require SOCKS5
Mixed port (mixed-port)Depends on configAccepts both HTTP and SOCKS requests on the same port
Control panel port9090RESTful API, unrelated to traffic forwarding

The Browser Path: Why the System Proxy Setting Isn't Taking Effect

Browser path failures usually come down to three spots — check them in this order:

  1. The system proxy switch isn't actually on — "Set as system proxy" in the client is a linked toggle, and some versions don't restore their last state after a restart. Manually confirm it's currently enabled rather than assuming from memory.
  2. The browser has its own independent proxy setting — most browsers follow the system by default, but if you've previously set "manual proxy configuration" or installed a proxy-management extension, the browser will prioritize its own config and ignore the system setting. Switch the browser's proxy mode back to "system proxy" or disable the extension.
  3. Group policy overrides on corporate/school networks — some managed machines control network settings via group policy; the system proxy checkbox may show as enabled while actual browsing behavior is still overridden at the policy level. In this environment, switching to TUN mode to bypass the system proxy setting entirely is the more reliable option (see the end of this article).

Browser incognito/private windows sometimes maintain their own separate network settings cache — a proxy working in a regular window doesn't guarantee it's synced in an incognito window. If "some windows work, some don't," reopen a fresh incognito window before drawing conclusions.

The Terminal Path: Environment Variables and Shell Config

Terminals don't read the system proxy panel — they read environment variables. The most common ones are http_proxy, https_proxy, and all_proxy (lowercase is the standard convention; uppercase support varies by tool). For a quick test, export them directly in the current terminal session:

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"

This only applies to the current terminal window and is lost when you close it. To make it persist every time you open a terminal, add these lines to your shell's startup config file — bash users edit ~/.bashrc or ~/.bash_profile, zsh users (macOS's default shell) edit ~/.zshrc. After saving, run source ~/.zshrc to apply it immediately without restarting the terminal.

Three common pitfalls:

  • Editing the wrong config file — macOS switched its default shell to zsh a while back, but plenty of people still follow old tutorials and edit .bashrc, which a newly opened terminal never reads. Run echo $SHELL first to confirm which shell you're actually using.
  • Port number is out of date — after changing the client's port or reinstalling with a new config, people forget to update the hardcoded port number in their environment variables. This shows up only in the terminal, while the browser (which follows the system proxy setting) works fine — if behavior differs between the two, compare port numbers first.
  • Some tools read their own separate config instead— Git, for example, prioritizes the proxy address set in git config --global http.proxy over environment variables. Even with correct env vars, Git still follows its own config, so you need to run this separately:
    git config --global http.proxy http://127.0.0.1:7890
    git config --global https.proxy http://127.0.0.1:7890

After setting the environment variables, verify with curl -v https://ipinfo.io/ip and check whether the returned IP matches the node's region — don't just check whether the command errors out. No error doesn't mean it went through the proxy; a direct connection can succeed just as easily.

Leftover PAC Scripts and Proxy Exception Lists

If you previously used a PAC-based proxy tool (auto-config script mode), uninstalling it or switching to Clash may leave the old PAC address behind in the system, causing the system proxy panel to show "use setup script" instead of a manually specified IP+port. This leftover setting typically takes priority over manual proxy config, showing up as the system proxy being on while traffic still goes direct or behaves abnormally. How to check:

  1. Windows: open "Settings → Network & Internet → Proxy" and check whether "Use setup script" is enabled. If so, turn it off first, then separately enable "Use a proxy server" with manual settings.
  2. macOS: System Settings → Network → Details for your network service → Proxies, check whether "Automatic Proxy Configuration" still has an old PAC address checked, and confirm that both "Web Proxy (HTTP)" and "Secure Web Proxy (HTTPS)" are set to Clash's port.

Another spot people often overlook is the proxy exception list (no_proxy / bypass list). The system proxy setting usually has a field like "Bypass proxy server for these addresses," which by default includes local addresses like localhost and 127.* — that's normal. But some installers or leftover configs stuff broad wildcard rules in there, causing a large number of legitimate sites to get lumped into the exception list and go direct instead of through the proxy. Check whether this field has domain patterns beyond what you expect; the equivalent terminal environment variable is no_proxy, which is worth checking separately too:

echo $no_proxy

If no_proxy contains * or an overly broad wildcard (like an entire top-level domain), it effectively disables the terminal proxy — every request gets treated as an exception and goes direct. In this case, clear it out and rewrite it with only the necessary local addresses.

Checklist and Fallback Option

Here's the whole thing condensed into a checklist you can follow top to bottom whenever "system proxy is on but not working":

  1. Test the port directly with curl -x to confirm Clash is listening and the port number is correct.
  2. Check whether the client's "Set as system proxy" switch is actually enabled.
  3. Check whether the browser has a separate manual proxy setting or a proxy-management extension installed, and switch it back to following the system.
  4. Check whether the system proxy panel still has a leftover PAC script address, and clear it in favor of a manually specified IP and port.
  5. Check the system proxy exception list and the terminal no_proxy variable, and clean up any overly broad wildcard rules.
  6. Write terminal environment variables into the config file matching your current shell (bash/zsh), keeping the port number in sync with the client's actual setting.
  7. Separately check tools like Git that maintain their own proxy config, so they don't end up reading a stale address.

If, after all this, a handful of apps still refuse to respect the system proxy setting or environment variables — this isn't unusual. Some standalone processes never check the system proxy panel or read shell environment variables at all; they only follow their own hardcoded direct-connection logic. For these stubborn apps, the simpler fix is switching to TUN mode: the client sets up a virtual network adapter at the system network layer, taking over all outbound traffic uniformly, without depending on whether any given app actively "cooperates" with the system proxy setting. Browser, terminal, and other standalone processes all get handled together. TUN mode's coverage is far more thorough, but it also has stricter requirements around DNS handling and network adapter permissions, requiring one extra authorization step compared to a system proxy setup. Check the tutorial page for platform-specific setup steps.

Download the Clash Client

Confirming the client itself is listening correctly first, then checking the system proxy and environment variables item by item, is the fastest way through this kind of issue.

Download Clash