First, distinguish the core, system proxy, and app requests

When a client shows “Running,” that usually means only that the proxy core has started—not that your browser is using it. A successful node latency test confirms that the route used for that test is available; it doesn’t prove that a web request used the same node. Break troubleshooting into three parts: Is a local port listening? Is the app sending requests to it? How does the core forward those requests?

The Clash and Clash Meta (now called mihomo) cores accept and forward connections. A desktop client’s “System Proxy” switch typically changes the operating system’s proxy settings. These are separate controls. Chrome and Edge generally use the system proxy; Firefox can be configured independently; terminal tools often rely on environment variables or their own settings.

  1. Note the client and core names, current mode, and local listening port.
  2. Use a consistent test URL, such as https://example.com/, rather than changing the target each time.
  3. Open the client’s connection list and logs, then make a request. Compare its timestamp, domain, rule, and outbound policy.
  4. Change one setting at a time. Restore temporary changes after testing, and record the results before and after.

Step 1: Verify that the local proxy port accepts connections

Know the difference between HTTP, SOCKS, and mixed ports

In the client’s settings or active configuration, look for port, socks-port, and mixed-port. Menu names vary by client, so use the active configuration as your source of truth. The fields below are examples; you don’t need to add all three ports to your existing config, and you should never overwrite subscribed nodes or rules.

# Field examples: use the settings active in the current core
port: 7890
socks-port: 7891
mixed-port: 7892
allow-lan: false
  • port: HTTP proxy endpoint. HTTPS sites typically use HTTP CONNECT to establish a tunnel.
  • socks-port: SOCKS proxy endpoint. Don’t enter this as an HTTP proxy port.
  • mixed-port: A single endpoint that accepts both HTTP and SOCKS proxy connections.

For local use, set the address to 127.0.0.1. A common port mismatch is when the system proxy points to 7890, but the core listens on 7892. Don’t enable “Allow LAN” just to fix a local connection; that setting doesn’t start the local port.

Check the listening port and the process using it

On Windows, open PowerShell and test the port, then identify the listening process. A successful TCP test only means a program accepts connections; confirm that it’s the proxy core you’re using.

Test-NetConnection 127.0.0.1 -Port 7890
Get-NetTCPConnection -LocalPort 7890 -State Listen |
  Select-Object LocalAddress, LocalPort, OwningProcess
# Replace with the process ID you find; 1234 is only an example
Get-Process -Id 1234

On macOS, run the command below. On Linux, run ss -lntp and look for the relevant port. You may need elevated permissions to see some process details.

lsof -nP -iTCP:7890 -sTCP:LISTEN

If the logs show address already in use, quit other proxy clients before restarting the current core. If you change the listening port, update the system proxy, browser’s manual proxy settings, and terminal variables too. Don’t kill processes you can’t identify, or run two clients that compete for the same port.

Step 2: Use an explicit proxy test to narrow down the problem

Bypass the system proxy settings and tell curl exactly which local port to use. This helps distinguish “the app isn’t using the proxy” from “the proxy can’t forward traffic.” On Windows, use curl.exe to avoid differences caused by the curl alias in Windows PowerShell 5.1. On macOS and Linux, use curl.

# Windows PowerShell: explicitly use the HTTP or mixed proxy port
curl.exe -v --connect-timeout 5 --max-time 20 --noproxy "" --proxy http://127.0.0.1:7890 https://example.com/

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

# Use this only if 7891 is the actual SOCKS port
curl -v --connect-timeout 5 --max-time 20 --noproxy "" --proxy socks5h://127.0.0.1:7891 https://example.com/

--noproxy "" clears the bypass list for this request so an existing NO_PROXY value won’t interfere. With socks5h, the proxy resolves the target hostname; with socks5, the local machine usually resolves it first. Differences can help investigate DNS, but a single test doesn’t prove that a particular DNS service is at fault.

Test resultWhat it means and what to check next
Connection to 127.0.0.1 refusedCheck the address, port, and core status first; there’s no need to switch nodes yet.
Local port connects, then times outCheck the request’s policy group, node, DNS, and remote connection logs.
Explicit proxy works, browser doesn’tCheck system proxy settings, the browser’s proxy mode, and extensions first.
Browser works, regular terminal requests failCheck environment variables, tool-specific settings, and when the process was started.
Only some domains failCheck the matched rule, bypass list, target site response, and DNS route.

Seeing 200 Connection established during an HTTPS test usually means only that the CONNECT tunnel was established. Check the subsequent TLS handshake and webpage response too. A 403 doesn’t necessarily mean the system proxy failed; it may be the target site’s access policy. The full response is more useful than a single status code.

Step 3: If the browser isn’t using the proxy, check system settings and extensions separately

Windows: Check the active system proxy, not just the client switch

  1. On Windows 11, go to Settings → Network & internet → Proxy → Manual proxy setup. On Windows 10, go to Settings → Network & Internet → Proxy.
  2. Check that the proxy address matches the local endpoint, such as 127.0.0.1, and that the port matches the core.
  3. Check whether “Use setup script” is enabled. A script URL points to a PAC configuration, which may send some domains directly according to its rules. Don’t confuse it with a manual proxy setting when troubleshooting.
  4. Check the proxy exceptions list. The browser may bypass the proxy if the target domain is listed there.

First turn off automatic proxy control in other proxy tools. Then toggle the current client’s system proxy switch and check whether the OS setting changes. Work-managed devices may be controlled by organizational policies. If settings revert automatically, contact your administrator instead of repeatedly editing the registry.

netsh winhttp show proxy displays the WinHTTP proxy configuration; it doesn’t show whether Chrome or Edge is using the system proxy. If WinHTTP shows a direct connection, that doesn’t mean browser proxying is disabled. You don’t need to blindly import or reset settings to make a browser work.

macOS: Check the network service currently in use

On macOS 13 and later, go to System Settings → Network → select the connected Wi-Fi or Ethernet service → Details → Proxies. Make sure you’re changing the active network service, not a disconnected interface. Check both Web Proxy (HTTP) and Secure Web Proxy (HTTPS). If both point to the local HTTP endpoint, their ports should match the client.

Using a local HTTP proxy endpoint for HTTPS websites is normal; there’s no need to change the address to https://127.0.0.1. With common Clash local HTTP endpoints, the connection between the client and local proxy usually isn’t encrypted with TLS. HTTPS encryption takes place inside the tunnel.

Firefox and proxy extensions: Use one source of proxy settings at a time

In Firefox, go to Settings → General → Network Settings → Settings and check whether “Use system proxy settings” is selected. If you’re using a manual proxy, verify the address, port, and “No proxy for” list. In Chrome and Edge, also check the active profile in any proxy-switching extension and whether the extension is managed by your organization.

  • Temporarily disable proxy-switching extensions and test again. Private browsing doesn’t necessarily disable every extension.
  • Quit the browser completely and reopen it so existing connections don’t mask configuration changes.
  • Watch the client’s connection list while making a test request. If there’s no entry, the request may be bypassing the proxy or missing the entry point. Also rule out page caching, a request that never went out, and active log filters.
  • Linux desktop environments don’t provide a system proxy that every app follows. Once an explicit proxy test succeeds, configure each app according to its own proxy support.

Step 4: If terminal apps aren’t using the proxy, check environment variables and tool settings

A system proxy isn’t a forwarding layer forced onto every process. Terminal tools such as curl, Git, and package managers may use environment variables or their own proxy settings. Terminals and IDEs that were already open may not pick up environment variables added later. Test in the current session first; don’t start by changing global settings.

macOS and Linux: Set variables in the current shell

# Check existing proxy variables; don't share output that contains credentials
env | grep -iE '^(http|https|all|no)_proxy='

# Applies to this terminal session; change the port to match your setup
export http_proxy=http://127.0.0.1:7890
export https_proxy=http://127.0.0.1:7890

# This request should use the variables set above
curl -v --connect-timeout 5 --max-time 20 https://example.com/

# Remove the variables added for this test when you're done
unset http_proxy https_proxy

Using http:// as the value of https_proxy is correct: the variable name refers to HTTPS target URLs, while the value specifies how to connect to the proxy server. curl has case-sensitive rules for HTTP proxy variables, so prefer the lowercase form shown here. Check each tool’s documentation to see which variables it supports.

Windows PowerShell: Use process-level variables

# Check proxy environment variables already set in this process
Get-ChildItem Env: | Where-Object Name -Match '^(HTTP|HTTPS|ALL|NO)_PROXY$'

# Applies to this PowerShell session and processes started from it
$env:http_proxy = "http://127.0.0.1:7890"
$env:https_proxy = "http://127.0.0.1:7890"
curl.exe -v --connect-timeout 5 --max-time 20 https://example.com/

# Remove these only if you added them temporarily for this test
Remove-Item Env:http_proxy, Env:https_proxy -ErrorAction SilentlyContinue

If a variable already had a value, record it and restore it after testing instead of deleting it. Check whether NO_PROXY includes the target domain or is set to *; a wildcard bypass may make tools that support it connect directly to every target. If ALL_PROXY is set, check that it doesn’t point to an old SOCKS port.

Git, WSL, and containers: Don’t assume they share the same endpoint

Use the commands below to check Git’s proxy settings and where they’re set. The source may be system, user, or repository configuration. Change the relevant level when troubleshooting; deleting a user setting alone won’t remove an override in the current repository. Redact usernames, passwords, and internal addresses before sharing the output.

git config --show-origin --get-regexp 'http\..*proxy'
git config --show-origin --get-regexp 'remote\..*proxy'

Inside WSL, a container, or a virtual machine, 127.0.0.1 may not point to the host. WSL behaves differently in NAT and mirrored networking modes, and containers typically have their own network namespace. Identify the environment and an address reachable from the host before changing the listening address or firewall. Don’t expose the proxy on every network interface. Git remotes using SSH also won’t automatically use the same route just because an HTTP proxy is configured.

Step 5: If requests reach Clash, check rules, DNS, and TUN

If the connection is listed, check the actual outbound route

Once the client logs the target domain, shift your focus from the system proxy switch to the forwarding path. Rules are matched in order, and a matching DIRECT rule sends traffic directly. A policy group may also have selected a direct connection instead of the expected proxy node. Check the connection details for the matched rule, policy chain, and destination; this is more useful than repeatedly toggling switches.

  1. Keep the target URL unchanged and note the matched rule and selected outbound route.
  2. Temporarily switch to Global mode, select a specific proxy node, and request the same URL again.
  3. If only Global mode works, switch back to Rule mode and check the domain-specific rules, rule sets, and final fallback rule.
  4. Restore the original mode after testing. Global mode is useful for comparison, not a long-term fix for every issue.

You can temporarily set the log level to debug, reproduce the issue once, then restore it to info. For connection refused, identify whether the refused connection was to the local endpoint or a remote service. For i/o timeout, check whether the timeout occurred during DNS lookup, node connection, or the destination connection. Don’t rely on the last two words of an error message.

DNS and TUN: Test them separately

Explicit HTTP proxy, SOCKS, direct local connections, browser Secure DNS, and TUN DNS interception may use different resolution paths. A successful nslookup only confirms that the path used by that command can resolve the name; it doesn’t prove the core gets the same result. If a request fails with a DNS error, check the core logs and dns settings. See the DNS configuration guide, and don’t replace every upstream server at once.

TUN uses a virtual network interface to capture matching traffic. It can help with apps that ignore explicit proxy settings, but it isn’t an “enhanced system proxy switch.” It also involves permissions, routing, DNS, and compatibility with other VPNs. If both the system proxy and TUN are enabled, a test may be using a different entry point than you expect.

Wrap up: Save evidence and restore temporary settings

When reporting an issue, include the smallest set of details needed to reproduce it: operating system, client and core versions, HTTP/mixed port, whether TUN is enabled, browser name, explicit curl test results, and connection details from the same moment. Get version numbers from the client itself instead of writing “latest.”

  • Record comparisons such as “explicit proxy works, browser fails” instead of just saying “it won’t connect.”
  • Include the exact time and target domain so the same request can be found in the logs.
  • Redact subscription URLs, node credentials, request cookies, authorization headers, and sensitive query parameters.
  • Restore any temporary changes to the mode, log level, browser extension state, and environment variables.

Keep the same troubleshooting order: confirm the port is listening, then test the explicit proxy; if that works, configure the browser and terminal separately; once requests reach the core, check rules, nodes, and DNS. Each step gives you something observable to verify, so reinstalling the client doesn’t need to be your first move.