Troubleshooting system proxy issues

Browser extensions can override proxy settings, terminals may ignore the system proxy, and environment variables may be missing. Find the cause and verify the fix for each case.

First, distinguish the proxy toggle, the app's connection path, and the rule-selected route

When a Clash client says “System proxy enabled,” it usually means the client has tried to set the local proxy address in your operating system. It doesn’t mean every app is routed through the core, or that every request uses a remote node. Browsers may use system settings or defer to an extension; command-line tools such as curl, Git, and package managers may use their own environment variables or config files.

A request passes through three stages: the app connects to a local listening port, the core selects a policy based on its rules, and the selected egress establishes the connection. For troubleshooting, keep the test URL and port fixed, then check the client’s Connections page or logs. Don’t change nodes, DNS, and TUN settings all at once—you won’t know which change made a difference.

SymptomCheck firstHow to verify
Browser works, terminal failsTerminal proxy variables and tool settingsDoes curl work when you specify the proxy explicitly?
Terminal works, browser failsExtensions, browser proxy settings, launch argumentsDisable proxy extensions and retry the request
Both browser and terminal failLocal listener, core status, egress connectionPort check and core logs
Connection appears, but shows DIRECTRule mode, matched rule, policy groupRule and full policy chain in connection details

Step 1: Confirm the core is listening on a local port

Understand mixed-port, port, and socks-port

In a mihomo config, mixed-port accepts both HTTP and SOCKS proxy requests on the same port. port is the HTTP proxy listener, and socks-port is the SOCKS listener. Sending an HTTP request to a SOCKS-only port can result in a protocol error or a dropped connection. A desktop client may also override the port in your subscription, so its runtime settings are more reliable than the original subscription text.

# Example of a local mihomo listener; do not replace the entire subscription config
mixed-port: 7890
allow-lan: false
mode: rule

You don’t need allow-lan for a browser and terminal running on the same computer. It controls LAN access; it doesn’t make local apps use the system proxy. When checking a local connection, use the explicit IPv4 loopback address 127.0.0.1 to avoid ambiguity if localhost resolves to ::1 while the core listens only on IPv4.

Check the listener, then send an explicit proxy request

# Windows PowerShell: check whether port 7890 is listening
Get-NetTCPConnection -LocalPort 7890 -State Listen

# Linux: check TCP listeners
ss -lntp 'sport = :7890'

# macOS: check TCP listeners and processes
lsof -nP -iTCP:7890 -sTCP:LISTEN

Run the command for your operating system. If nothing is listening, check whether the client core is running, the config parsed successfully, and the port is available. If a listener appears, verify which process owns it—another app may be using port 7890.

# macOS / Linux
curl -q -v --noproxy "" --proxy http://127.0.0.1:7890 \
  --connect-timeout 7 --max-time 20 -I https://example.com/

# Windows PowerShell: explicitly use curl.exe
curl.exe -q -v --noproxy "" --proxy http://127.0.0.1:7890 --connect-timeout 7 --max-time 20 -I https://example.com/

Put -q first to skip the default curl config file. --noproxy "" clears the bypass list in shells that pass empty arguments correctly, while --proxy specifies the listener explicitly. Older Windows PowerShell versions handle empty-string arguments differently. If the request still bypasses the proxy, temporarily remove NO_PROXY from the current session and try again.

Seeing Connected to 127.0.0.1 confirms only that the local proxy listener is reachable. If an HTTPS request then shows 200 Connection established, the HTTP CONNECT tunnel has been created. Also check the destination’s response and the core’s connection log. This test uses example.com; success doesn’t mean every destination is reachable.

Step 2: Troubleshoot browser settings and extensions separately

Chrome and Edge: rule out extension overrides first

  1. Open chrome://extensions/ in Chrome or edge://extensions/ in Edge, then temporarily disable extensions that manage proxies, PAC, or network switching.
  2. In Chrome, go to “Settings” → “System” → “Open your computer’s proxy settings.” In Edge, go to “Settings” → “System and performance” → “System” and look for the proxy settings. Labels and sections may vary slightly by version.
  3. Check the address, port, and bypass list on the system proxy page. If the system uses PAC, confirm whether PAC or a manual proxy is active. Don’t rely on a single toggle to determine the actual route.
  4. Quit the browser completely, restart it, and revisit the test URL while watching the client’s connection log.

On Windows 11, go to “Settings” → “Network & internet” → “Proxy.” On macOS, go to “System Settings” → “Network” → your current network service → “Details” → “Proxies.” Manual HTTP proxy and secure web proxy may be separate entries; check the relevant setting when testing an HTTPS site.

If the settings page says a proxy is managed by an extension or organization, find out what manages it first. Enterprise policies and browser launch arguments can override ordinary settings; repeatedly toggling Clash’s system proxy usually won’t remove that override. Private browsing isn’t a reliable isolation test either, since some extensions are allowed to run in private windows.

Firefox: check whether it uses a separate proxy

In desktop Firefox, go to “Settings” → “General” → scroll to “Network Settings” at the bottom of the page → “Settings.” Choose “Use system proxy settings” to follow the operating system’s proxy. “Manual proxy configuration” and “Automatic proxy configuration URL” use Firefox’s own settings instead.

  • Manual HTTP proxy: enter 127.0.0.1 as the address and the actual HTTP or mixed port; check the HTTPS proxy entry too.
  • Manual SOCKS: select SOCKS v5 and use a SOCKS or mixed port. If you want the proxy to resolve destination hostnames, check the SOCKS v5 remote DNS option.
  • “No proxy for” list: check whether the test hostname or its domain suffix is listed, so a bypass rule isn’t mistaken for a client issue.

Step 3: Set proxy variables for the current terminal session

The terminal window itself doesn’t proxy network requests; programs running inside it make the connections. Many command-line tools don’t automatically use the desktop system proxy. If an explicit proxy test succeeds but a regular command fails, first set the environment variables supported by that tool instead of switching nodes.

macOS and Linux: start with a temporary export

export http_proxy=http://127.0.0.1:7890
export https_proxy=http://127.0.0.1:7890
export no_proxy=localhost,127.0.0.1,::1

curl -v --connect-timeout 7 --max-time 20 -I https://example.com/

The name https_proxy indicates that the variable applies to HTTPS destinations; it doesn’t mean its value must use https://. A typical Clash local HTTP proxy carries HTTPS over HTTP CONNECT, so the value is still http://127.0.0.1:7890. Changing it to https:// makes the tool try to establish TLS with the local proxy, which may fail if the listener doesn’t support it.

These variables affect only the current shell and processes started from it. Once you’ve confirmed they work, add them to ~/.zshrc or ~/.bashrc, depending on your shell. Don’t add them to multiple startup files at once. An IDE launched from the desktop may not read these files, so check its environment or terminal settings separately.

Windows PowerShell: use session environment variables

$env:http_proxy = "http://127.0.0.1:7890"
$env:https_proxy = "http://127.0.0.1:7890"
$env:no_proxy = "localhost,127.0.0.1,::1"

curl.exe -v --connect-timeout 7 --max-time 20 -I https://example.com/

In Windows PowerShell 5.1, curl may be an alias for Invoke-WebRequest. Use curl.exe to run curl explicitly and avoid confusing the two tools’ arguments and proxy behavior. Session variables don’t change programs that are already running; new processes inherit the current environment when they start.

Using SOCKS? Specify where DNS resolution happens

curl -q -v --noproxy "" --proxy socks5h://127.0.0.1:7890 \
  --connect-timeout 7 --max-time 20 -I https://example.com/

With curl, socks5:// usually resolves the destination hostname locally, while socks5h:// passes it to the SOCKS proxy for resolution. This difference can help pinpoint DNS issues, but other tools may not support the same URL syntax. Check the tool’s documentation before setting ALL_PROXY; don’t assume it works for every program.

Step 4: Check NO_PROXY and tool-specific settings

If the environment variables look right but traffic still goes direct, check the bypass list and tool-specific settings. NO_PROXY and no_proxy list hosts that should bypass the proxy. Support for uppercase and lowercase names, domain suffixes, and CIDR notation varies across tools. In particular, look for *, which means bypass all destinations in many tools.

# macOS / Linux: inspect proxy variables locally only
env | grep -i proxy

# Windows PowerShell
Get-ChildItem Env: | Where-Object Name -Match 'proxy'

# Show where Git settings come from, including system, global, and current repository config
git config --show-origin --get-regexp '.*proxy.*'

Git’s http.proxy, URL-specific proxy settings, or a package manager’s own proxy config can send commands in the same terminal along different routes. If Git points to an old 127.0.0.1:7891 and the current client listens only on port 7890, curl may work while Git fails.

  • Git: use --show-origin to find the config file and scope, then change only the setting you’ve confirmed is wrong. Repository-level config can override global settings.
  • npm: use npm config get proxy and npm config get https-proxy to check npm’s own proxy settings, and inspect the project’s .npmrc.
  • WSL and containers: 127.0.0.1 usually refers to their own network environment, not Windows or the host machine. WSL networking mode and container network settings can change which routes are reachable.

If a VM or container needs to reach the host’s proxy, check the host address it can access, the client’s listening interface, and firewall rules. Expose access only to the local network that needs it; don’t open the proxy port to the public internet for troubleshooting.

Step 5: Once the listener works, check rules, DNS, and TUN

A connection appears, but it doesn’t use the expected node

Find the test hostname in the client’s connection details and check the matched rule and policy chain. In rule mode, DIRECT means the core selected a direct connection based on its rules; it doesn’t mean the app bypassed the core. If the policy group currently selects DIRECT or the destination matches a direct rule, enabling the system proxy alone won’t change the outcome.

After recording the original settings, briefly switch to Global mode and explicitly select a known working proxy egress, then retest the same URL. If Global mode works but rule mode doesn’t, check rule order, domain matching, and policy group selections, then restore the original mode. Don’t treat a Global mode test as a recommendation for your permanent setup.

Narrow it down by the stage where the error occurs

What you seeWhat it means and what to check next
Connection to 127.0.0.1:7890 refusedCheck the local listener, whether the process exited, and the port value first. Don’t start by changing remote nodes.
Local connection established, then timed outCheck node connectivity, destination DNS, and egress in the core logs. A timeout alone doesn’t identify which layer failed.
Logs report destination hostname resolution failedCheck the core’s DNS settings, whether upstream resolvers are reachable, and where SOCKS resolves the hostname.
Destination returns HTTP 403 or 429The request may have reached the destination. Check its access policy or rate limits; this doesn’t mean the local proxy failed.

When do you need TUN mode?

TUN uses a virtual network interface and routes to capture eligible traffic. It’s useful for programs that can’t be configured to use a proxy and don’t read the system proxy settings. It won’t fix a wrong port or a dead node, and capturing traffic doesn’t mean every connection will use a remote node—the rules still determine the egress.

If curl is missing environment variables, fixing them is usually easier to verify. Use TUN only when you need it; follow the client’s instructions to install its service or grant administrator privileges, then check routes and DNS and watch for conflicts with other VPNs. When comparing system proxy and TUN, change one traffic-capture method at a time so overlapping routes don’t hide the cause.

Restore settings and verify the fix

Test all three: the browser, curl with an explicit proxy, and regular curl. Check the connection log for the same destination each time. If the browser works but regular curl fails, keep checking terminal settings; if curl with an explicit proxy also fails, return to the listener and core logs. Don’t call it fixed based only on the client toggle’s color or a node latency number.

  1. Record the final port, proxy listener type, and source of the active settings—for example, “mixed port 7890, current PowerShell session environment variables.”
  2. Re-enable any extensions you temporarily disabled, one at a time, and retest. If the issue returns, you’ve found the conflicting extension.
  3. Remove any temporary Global mode, broad bypass entries, and duplicate proxy variables added during troubleshooting to avoid different results next time.
# macOS / Linux: unset these only if you added them for this test
unset http_proxy https_proxy all_proxy no_proxy

# Windows PowerShell: remove temporary settings from this session
Remove-Item Env:http_proxy, Env:https_proxy, Env:all_proxy, Env:no_proxy -ErrorAction SilentlyContinue

Cleanup commands don’t remove persistent settings from startup files or tool configs. If you added settings there, update the relevant files too. After closing the client, check whether the system proxy settings are restored, so the system isn’t left pointing to a local port that is no longer listening.

Download ClashBrowse platforms and clients