Start by testing the proxy directly to isolate the problem
Turning on “System Proxy” only tells the client to try to write the proxy address to your operating system settings. It doesn't mean every app will use it. Whether the mihomo core is running, whether an app connects to the local port, and whether a rule selects a proxy node are three separate questions. First, test an explicit proxy request that bypasses browser settings, then troubleshoot the browser and terminal separately.
The examples below use 7890 as the local mixed port. Check the actual value in your client's port settings or active configuration first; the example isn't a default for every Clash client. In Windows PowerShell, use curl.exe to avoid older versions interpreting curl as a different command.
# macOS / Linux
curl --noproxy "" -x http://127.0.0.1:7890 -I --connect-timeout 10 --max-time 20 https://example.com
# Windows PowerShell
curl.exe --noproxy "" -x http://127.0.0.1:7890 -I --connect-timeout 10 --max-time 20 https://example.com
- Connection refused: Check the core, listening port, and process using it first. Don't start by changing DNS.
- Connected to the local proxy, but the request timed out: Check the client's connection log, matched rule, policy group, and node.
- Received an HTTP response from the site: The explicit proxy request completed for that destination. Confirm it used a proxy outbound, not DIRECT from a rule.
Check the port, core, and process using it
Successfully importing a subscription doesn't mean the local proxy is listening. The client interface may open normally while the core exits because of a configuration error; another proxy app may also have claimed the port first. Confirm the active configuration, then check the core startup log for its listening address.
Verify the configuration fields
# Local listener example; not a complete, ready-to-use configuration
mixed-port: 7890
allow-lan: false
mode: rule
mixed-port accepts HTTP and SOCKS proxy requests on the same port. With separate ports, port is for HTTP and socks-port is for SOCKS; don't mix them up. The snippet above has no nodes, policy groups, or rules, so it isn't a substitute for a subscription. Desktop clients may also generate the runtime configuration through overrides; check the values that are actually in effect.
Find out what's listening on port 7890
# Windows PowerShell: find the listening PID
Get-NetTCPConnection -LocalPort 7890 -State Listen |
Select-Object LocalAddress, LocalPort, OwningProcess
# macOS: find the process name and PID
lsof -nP -iTCP:7890 -sTCP:LISTEN
# Linux: find the listening address and process details; some information requires elevated privileges
ss -lntp 'sport = :7890'
On Windows, pass the PID you found to Get-Process -Id 1234; 1234 is just an example. If the listener belongs to an old client, exit that app normally before starting the current core. Don't terminate a system process unless you're sure what it does. If nothing is listening, check the logs for configuration parsing errors, port binding failures, and why the core exited.
If your local request uses localhost, note that it may resolve to the IPv6 loopback address ::1 while the core listens only on IPv4. For troubleshooting, use 127.0.0.1 first so the address matches the listener.
Browser troubleshooting: system settings, extensions, and PAC
If an explicit proxy request works but the browser doesn't, check which proxy settings the browser is using. Behavior varies across browsers, desktop environments, and enterprise policies, so the client's toggle color alone doesn't tell you much.
- Windows 11: Go to Settings → Network & internet → Proxy. Check the address and port under “Use a proxy server,” and note whether “Use setup script” is enabled.
- macOS: Go to System Settings → Network → your current network service → Details → Proxies. Check the web proxy, secure web proxy, and automatic proxy configuration.
- Chrome: Enter
chrome://settings/systemin the address bar to open your computer's proxy settings. Then go tochrome://extensionsand check for extensions that can control the proxy. - Firefox: Go to Settings → General → Network Settings → Settings. Select “Use system proxy settings” or enter HTTP and HTTPS proxy addresses that match the core.
Remove competing controls before checking PAC
A proxy-switching extension can override system settings. Temporarily disable related extensions, fully quit the browser, and reopen it; then check the client's connection list. Incognito mode doesn't necessarily rule out extensions, since they may be allowed to run in private windows.
PAC is a script that chooses whether to proxy or bypass each request based on its URL; it isn't a “proxy all traffic” switch. For example, if the script returns DIRECT, the browser won't connect to the local proxy. Note the original settings, then temporarily use just one proxy control while troubleshooting. Avoid stacking an automatic script, manual proxy, and extension rules. If your device is managed by your organization, contact your administrator instead of removing organization-mandated settings.
In Windows PowerShell, run the command below to view some proxy settings for the current user. Use the result to identify where the settings come from; it doesn't prove that every browser uses them:
Get-ItemProperty 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Internet Settings' |
Select-Object ProxyEnable, ProxyServer, AutoConfigURL
netsh winhttp show proxy displays the WinHTTP proxy configuration. It doesn't tell you whether Chrome's system proxy is enabled. Confusing the two can lead to the false conclusion that the browser is using a proxy just because the command reports a direct connection—or vice versa.
Terminal troubleshooting: set proxy environment variables explicitly
Most command-line tools don't automatically use your desktop's system proxy. There's no contradiction if your browser can reach a site while curl, Git, or a package manager in the terminal can't. Start with temporary environment variables rather than changing global settings; once you've confirmed they work, decide whether to add them to your shell startup file.
macOS and Linux: current shell session
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 -I --connect-timeout 10 --max-time 20 https://example.com
# Check for leftover settings
env | grep -iE '^(http|https|all|no)_proxy='
https_proxy describes the protocol of the destination URL; its value doesn't have to start with https://. To connect to a local HTTP proxy, use http://127.0.0.1:7890. HTTPS requests use CONNECT to establish a tunnel. Changing the scheme to HTTPS may instead ask the local port to provide a TLS proxy service that it doesn't support.
For security reasons, curl doesn't use uppercase HTTP_PROXY as its HTTP proxy variable; lowercase is the safer choice. Other programs may handle capitalization differently. Check for an existing uppercase variable or all_proxy too, so an old port doesn't remain in use.
Windows PowerShell: current process and child processes
$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 -I --connect-timeout 10 --max-time 20 https://example.com
Get-ChildItem Env: | Where-Object Name -Match 'proxy'
These settings affect only the current PowerShell process and child processes started from it; they don't automatically change an editor or another terminal that's already running. Don't assume another tab that was already open in Windows Terminal has picked up the changes. WSL, containers, and remote SSH sessions are separate environments, where 127.0.0.1 may not point to the host's proxy. Don't expose the proxy on every network interface just to work around this.
Undo temporary environment changes
# macOS / Linux
unset http_proxy https_proxy all_proxy no_proxy
unset HTTP_PROXY HTTPS_PROXY ALL_PROXY NO_PROXY
# Windows PowerShell
Remove-Item Env:http_proxy, Env:https_proxy, Env:all_proxy, Env:no_proxy -ErrorAction SilentlyContinue
If you had a company proxy configured, restore the saved values instead of simply clearing them. Closing the current shell also discards these temporary changes. Settings added to ~/.zshrc, ~/.bashrc, or a PowerShell profile must be removed separately.
If only one tool fails, check its own proxy settings
If the environment variables are set but one tool still fails, check that tool's own proxy configuration. App-level options may override environment variables, and background services may not inherit the current shell's environment at all. For Git, check where the setting comes from before changing anything:
git config --show-origin --get-regexp '.*proxy.*'
# Set a proxy for this command only; don't change the global configuration
git -c http.proxy=http://127.0.0.1:7890 ls-remote https://github.com/git/git.git HEAD
The command uses a public repository. When testing a private repository, an authentication error doesn't automatically mean the proxy is at fault. Git's HTTPS transport can use an HTTP proxy, but SSH remote URLs starting with git@ use a different transport and won't automatically use the same proxy just because http.proxy is set.
Similarly, npm, Python package managers, Java apps, and container builds may each read a configuration file, command-line options, or service environment variables. Verify the connection with curl first, then troubleshoot the specific tool. Don't disable TLS certificate verification to troubleshoot networking. If you see a certificate error, check the system clock, trust chain, and certificate configuration on your organization's network.
Once a request reaches mihomo: check the rules and node
Seeing a destination domain in the client's connection list only confirms that the request reached the core; it doesn't prove that the expected node was used. Rules are matched in order. An earlier DIRECT rule, a policy group currently set to DIRECT, or the final MATCH rule can all change the outbound route.
- Check the mode: Confirm that Rule mode is active. If you temporarily switch to Global mode for comparison, make sure the global policy actually selects a proxy node, then restore the original mode.
- Check the matched rule: Note the destination domain, matched rule, and final policy chain. Policy group names referenced in a subscription must match their actual definitions.
- Check the node: A successful latency test only shows that its test URL was reachable at that time. It doesn't guarantee that every domain, port, and protocol will work.
- Identify where it fails: Handle local connection failures, node connection timeouts, DNS resolution failures, and TLS handshake errors separately. Don't lump them all together as “proxy not working.”
To compare your public IP, make direct and proxied requests to the same IP lookup service, then compare the results with the connection log. The same public IP in both tests doesn't necessarily mean the system proxy failed: a rule may send that lookup domain DIRECT, or TUN may intercept a request that appears to be direct. Record the TUN status and policy, and avoid changing multiple variables at once.
# Bypasses curl's application-level proxy; TUN may still intercept this request when enabled
curl --proxy "" --noproxy "*" --max-time 20 https://api.ipify.org
# Explicitly use the local HTTP proxy
curl --noproxy "" -x http://127.0.0.1:7890 --max-time 20 https://api.ipify.org
When to use TUN—and when to keep troubleshooting the system proxy
If the problem only affects a browser and an explicit proxy request succeeds, fix the browser settings first. For terminal tools that support proxy variables, configuring the tool directly is usually easier to troubleshoot. TUN is useful for apps that don't read system proxy settings or when you need to route more IP traffic, but it isn't the first step for every problem.
TUN mode routes traffic through a virtual network interface and typically involves permissions, DNS, and routing settings. It won't fix a broken node, invalid subscription, or incorrect rule, and it can't guarantee that traffic will bypass policies enforced by other VPNs or security software. First disable other apps that intercept network traffic, note the current routes and DNS settings, then enable TUN using your client's instructions.
If you need to report the issue, include your operating system and client versions, mihomo core version, actual listening port, failed command, and approximate time of the error. Remove subscription URLs, access tokens, and node credentials before sharing logs. See the full configuration guide for all options, or the setup guide for basic import and traffic routing steps.