How to Fix Clash System Proxy Not Working: Browser Works but Terminal Fails
Check the system proxy, browser-specific settings, terminal environment variables, and local listening port separately.
Confirm the proxy path used by the browser
“The browser works, but the terminal fails” does not by itself mean that Clash’s system proxy switch is broken. Browsers and command-line programs may use completely different network paths: a browser may read the operating system proxy, use a browser extension, apply its own proxy settings, or rely on its own secure DNS, while a terminal program may connect directly to the destination and ignore the system proxy entirely.
The first troubleshooting step is not to keep switching nodes, but to determine where the browser’s traffic enters Clash. Temporarily disable browser proxy extensions and browser-specific proxy options, leaving only Clash’s system proxy enabled, then revisit the test page. If the browser also loses connectivity after the extension is disabled, the previously working traffic likely came from the extension rather than the system proxy.
Next, check the connection log in the Clash client. Visit a domain you have not opened before and look for the domain, destination address, matched rule, and proxy group in the connection list. If the browser reports success but no new connection appears in Clash, the request did not enter the currently running Clash instance. Common causes include another browser proxy, a standalone browser VPN, multiple proxy clients running on the system, or a reused connection that the browser has not closed.
Also make sure the browser and terminal are testing the same domain and protocol. A regular web page, an HTTPS API request, a Git repository connection, and a package download may involve different domains, ports, and rules. One working webpage does not mean that Git, a package manager, or a remote API is being handled correctly by the same rule.
Check Clash Local Listening Ports and Protocols
For a terminal to send traffic through Clash, it must first connect to a local proxy port that is actively listening. Defaults vary between clients and may be overridden after importing a configuration, so do not assume the port is 7890. Confirm the actual value in the client’s port settings, runtime log, or currently active configuration.
Common configurations provide an HTTP port, a SOCKS port, or a mixed-port. A mixed-port accepts both HTTP and SOCKS proxy connections on one port, making it suitable for browsers, curl, and other tools at the same time. The following snippet is only a structural example; during troubleshooting, use the active configuration shown by the client:
mixed-port: 7890
socks-port: 7891
allow-lan: false
mode: rule
A port listed in the configuration does not mean that the process is actually listening. The port may be occupied by another program, or the Clash core may have failed to start because the configuration could not be loaded. On Windows, use netstat or PowerShell to check listening status; on macOS and Linux, use lsof or ss:
netstat -ano | findstr 7890
lsof -nP -iTCP:7890 -sTCP:LISTEN
ss -lntp | grep 7890
If there is no listening result, return to the Clash client and check the core status and logs instead of continuing to modify the terminal. If another process is using the port, close the conflicting program or change the Clash port, then update the proxy address in the terminal accordingly.
Once listening is confirmed, have curl specify the proxy explicitly. This bypasses the system proxy and environment variables, quickly testing whether both the “terminal to local port” and “Clash to destination” paths are working:
curl -I -x http://127.0.0.1:7890 https://example.com
curl -I --proxy socks5h://127.0.0.1:7891 https://example.com
The first command tests an HTTP proxy, while the second tests SOCKS5. In socks5h, the h means that the proxy resolves the destination domain, helping distinguish local DNS issues from proxy connection issues. If an explicitly specified proxy works, the Clash port and node are generally usable; the problem is usually how the system proxy is read or how terminal environment variables are configured.
For “connection refused,” check the port and core status first. For a long timeout, check the firewall, node connectivity, and rules. If the proxy returns an authentication error, verify whether the client in use has authentication configured for the local port. If the log shows that the request entered Clash but was handled by a DIRECT rule, also check the rule order and the final matched proxy group.
Set Proxy Environment Variables for Terminal Programs
Many command-line tools do not automatically read desktop system proxy settings. Instead, they look for environment variables such as http_proxy, https_proxy, and all_proxy. Variable names may be case-sensitive, and supported variables depend on the program. To improve compatibility, set both lowercase and uppercase forms, but avoid leaving conflicting addresses in the same session.
Temporary Settings on macOS and Linux
In Bash, Zsh, and other shells, export proxy variables for the current terminal session only:
export http_proxy=http://127.0.0.1:7890
export https_proxy=http://127.0.0.1:7890
export HTTP_PROXY=http://127.0.0.1:7890
export HTTPS_PROXY=http://127.0.0.1:7890
curl -I https://example.com
https_proxy specifies the proxy used for HTTPS destinations; it does not mean that the variable value must use the https:// scheme. A local Clash port usually provides an HTTP proxy, so the address is commonly written as http://127.0.0.1:7890. To use SOCKS consistently, set:
export all_proxy=socks5h://127.0.0.1:7891
export ALL_PROXY=socks5h://127.0.0.1:7891
Temporary Settings in Windows CMD and PowerShell
In CMD, use set to set environment variables for the current window:
set http_proxy=http://127.0.0.1:7890
set https_proxy=http://127.0.0.1:7890
curl.exe -I https://example.com
In PowerShell, write to the Env scope of the current process:
$Env:http_proxy = "http://127.0.0.1:7890"
$Env:https_proxy = "http://127.0.0.1:7890"
curl.exe -I https://example.com
In PowerShell, use curl.exe explicitly for testing to avoid ambiguity caused by command aliases in older environments. For Invoke-WebRequest, you can also specify the proxy directly:
Invoke-WebRequest -Uri "https://example.com" -Proxy "http://127.0.0.1:7890"
Check Stale Variables and Exclusion Lists
Before changing variables, print their current values to check for an old port, an invalid hostname, or an address belonging to another proxy client. On macOS and Linux, run env | grep -i proxy; in PowerShell, run Get-ChildItem Env: | Where-Object Name -Match 'proxy'.
no_proxy or NO_PROXY specifies addresses that should bypass the proxy. If the destination domain appears in the exclusion list by mistake, the program connects directly. Common legitimate exclusions include localhost, 127.0.0.1, and local network services, but overly broad suffix rules may also exclude external domains.
Handle System Proxies, Tool Settings, and Platform Differences
A system proxy is not a universal forwarding layer that every program must obey. It is better understood as a set of proxy parameters provided by the operating system. Whether an application reads them, when it reads them, and which protocols it supports are determined by the application itself. Browsers commonly read system settings, while Git, npm, Python package managers, container processes, and some Java programs often use their own configuration.
Windows System Proxy and WinHTTP
Windows desktop applications commonly read the user-level system proxy, while some system components and services use WinHTTP settings. The two configurations are not fully equivalent. As a result, it is common for a browser to work while a tool running under a service account fails. Use the following command to view the current WinHTTP status:
netsh winhttp show proxy
Do not import the user proxy into WinHTTP without confirming why it is needed, as this can affect system components that depend on it. A safer approach is to connect a specific command to Clash explicitly, establish the scope of the problem, and then decide whether to use the tool’s own configuration or change a system-wide setting.
Independent Proxy Settings for Git and Package Managers
Git can store separate HTTP and HTTPS proxy settings. If the environment variables are correct but Git still fails, check for an old configuration:
git config --global --get http.proxy
git config --global --get https.proxy
When the current Clash HTTP port is required, set:
git config --global http.proxy http://127.0.0.1:7890
git config --global https.proxy http://127.0.0.1:7890
If Git no longer needs an independent proxy, remove the relevant configuration entry instead of setting its value to an empty string. npm, pnpm, pip, Maven, and Gradle also have their own configuration sources. During troubleshooting, check the tool’s configuration files, environment variables, and IDE settings together to prevent multiple layers from overwriting the same request.
The Proxy Protocol Must Match the Port
Using a SOCKS port as an HTTP proxy, or writing an HTTP port as a SOCKS address, causes the handshake to fail. Confirm the port type in the Clash client, then use the corresponding URL scheme in the tool. An HTTP proxy is usually written as http://127.0.0.1:port; SOCKS5 uses socks5:// or socks5h://.
Also watch for resolution differences between 127.0.0.1 and localhost. In some environments, localhost resolves to the IPv6 address ::1 first, while Clash may listen only on IPv4. During troubleshooting, use 127.0.0.1 directly to eliminate this variable.
Check TUN Mode, DNS, and Isolated Environments
TUN mode takes over more traffic through a virtual network interface and generally does not require each terminal program to support system proxy settings separately. However, enabling TUN does not guarantee that every command will work automatically. Permission to create the virtual interface, route installation, DNS takeover, process bypass rules, and other VPN software can all affect the result.
If curl works with an explicitly specified port under a regular system proxy, but a direct request still fails after TUN is enabled, check whether the connection appears in the Clash log. No record at all usually means the route never entered TUN. If a connection appears but domain resolution fails, check the DNS configuration. If the connection is assigned to the wrong proxy group, review and correct the rule match result.
Clash Meta, also known as Mihomo, supports more complete TUN, DNS, and routing capabilities. However, whether a graphical client exposes these options and which permissions it uses depends on the client implementation. Before editing YAML, confirm whether the client regenerates the configuration at startup so that manual changes are not overwritten.
WSL, Docker, virtual machines, and remote development containers require special handling. The 127.0.0.1 they see usually points to themselves, not the host machine. Even if Clash is listening correctly on the host, accessing 127.0.0.1:7890 inside a container may be refused. Use the host address on the relevant virtual network, confirm that Clash permits LAN connections and listens on the required interface, and check the host firewall.
After connecting to a remote server over SSH, terminal commands run on the remote host. The remote host’s 127.0.0.1 is not your local computer either. To let remote commands use the local Clash instance, establish explicit SSH port forwarding or configure a reachable proxy in the remote environment; do not simply copy local environment variables.
Troubleshoot Clash Terminal Proxy Issues in Order
Effective troubleshooting means validating each layer separately instead of changing the system proxy, rules, DNS, and node at the same time. Each step should answer one question, and you should record the result:
- Confirm the core is running: Check the Clash client status and startup log to ensure the current configuration loaded successfully.
- Confirm the port is listening: Read the HTTP, SOCKS, or mixed-port from the active configuration, then use a system command to verify that the corresponding port is listening.
- Specify the proxy explicitly: Use
curl -xor--proxyto connect directly to the local port and rule out system proxy detection issues. - Review connection records: Confirm that the request entered Clash and inspect the matched rule, proxy group, node, and error message.
- Check terminal variables: Print all proxy-related variables, remove stale addresses and conflicting values, then set the correct port for the current session.
- Check independent tool settings: See whether Git, package managers, IDEs, or runtimes have saved a different proxy configuration.
- Identify the execution boundary: Determine whether the command runs on the host, WSL, a container, a virtual machine, or a remote server, and confirm what its local address actually points to.
- Check TUN and DNS last: Analyze the virtual interface, routes, and domain resolution only after the basic port test succeeds.
If an explicit proxy test succeeds and the environment-variable test also succeeds, but a particular tool still fails, the problem is most likely within that tool. Enable its verbose logging to inspect the domain it connects to, the proxy settings it reads, and any TLS errors instead of continuing to switch Clash nodes.
If every explicit proxy test fails, return to the Clash side and check the port, configuration, and node. Test several destination domains separately and compare their rule results in the connection log. If only some domains fail, focus on the rules, DNS, and destination service. If no domain can establish a connection, check local listening status, core logs, and the proxy node first.
After troubleshooting, remove temporary variables and duplicate settings that are no longer needed, leaving one clear proxy path. The system proxy suits desktop applications, environment variables suit terminal sessions, independent tool settings suit programs with fixed requirements, and TUN suits scenarios that need to capture more network traffic. Choose the layer that fits the current environment as the primary entry point to reduce failures caused by changing ports and configuration conflicts.