C1 / No Internet at All
No Internet: Three Cuts to Isolate the Layer
If no site loads after turning on Clash, don't rush to switch nodes. The cause is almost always one of three things: your local connection is down, every node is dead, or a rule is routing traffic to the wrong place. Three cuts, and within ten minutes you'll know exactly which layer is at fault.
Cut One: Turn Off the Proxy, Test Your Local Connection
Turn off the system proxy or quit the client entirely, then visit a site in mainland China that normally loads instantly. If it doesn't load, the problem is your local network—nothing to do with Clash. Fix your Wi-Fi, router, or broadband first. If it loads fine, your connection is healthy; move to cut two.
This step gets skipped constantly, leading to an entire afternoon spent tweaking the client only to discover the router needed a reboot after a billing lapse. Switching to direct connection first is always the opening move when troubleshooting proxy issues.
Cut Two: Switch to Global Mode, Rule Out Rules
Switch the client to Global mode, manually pick a node that's usually stable, and try to reach a site that needs the proxy. If it works, the node is fine and the problem is in rule-based routing—switch back to Rule mode and move to cut three. If it still doesn't work, the issue is on the node side or local inbound traffic; skip ahead to C2 Node Timeouts.
Global mode is a diagnostic tool, not a permanent setting
Once you've pinpointed the issue, switch back to Rule mode. Staying on Global sends even mainland China traffic on a round trip through overseas nodes, wasting both speed and data. The
Troubleshooting FAQ has a dedicated entry on choosing between Global and Rule mode.
Cut Three: Turn Up Logging, Check Rule Matches
Raise the log level in your config, then watch the client's Connections/Logs panel: which rule matched the target domain, which proxy group it was sent to, and which node that group currently has selected. Two common failure patterns: the catch-all MATCH rule points to DIRECT, sending traffic that should be proxied straight out unproxied; or a DOMAIN-SUFFIX rule is written too broadly and hijacks domains that shouldn't be direct.
# config.yaml: raise logging while troubleshooting, revert once done
log-level: debug
mode: rule
Suspect the core isn't running at all? Poke the local inbound port directly with a command (use the port from your mixed-port setting):
curl -x http://127.0.0.1:7890 -I https://www.gstatic.com/generate_204
You should get 204 back. If even curl fails, the core isn't listening at all—either the port in your config is wrong, or the process never started. Jump to C7 Crashes on Launch.
C2 / Node Timeouts
Node Timeouts: All-Red and Scattered-Red Are Different Problems
When the latency test is all red, classify first: every node timing out and just a few nodes timing out have completely different causes. All-red is usually a problem on your end; scattered red points to the nodes themselves.
All Timeouts: Check Your Own Side First
- Subscription expired or out of data. Log into your provider's dashboard to check plan status. This is the single most common cause of an all-red list, and checking it takes ten seconds—do it first.
- The test URL itself is blocked. If the URL used for latency tests (commonly something like
generate_204) is blocked on your current network, every node will show a timeout even though they all actually work. Swap in a different test URL and re-run the test; if the numbers all come back, this was the cause.
- Your local firewall is blocking the core. If you clicked "Deny" on Windows' firewall prompt the first time the client launched, the core can't send packets and everything times out. Add the core process to the firewall's allowed-apps list.
- System clock is off. Some encrypted protocols are sensitive to your machine's clock; if the drift exceeds the tolerance, the handshake fails outright. Turn on automatic time sync, then re-test after it corrects.
Scattered Timeouts: A Node-Side Problem
A single node that's consistently red usually means the server is down or the route has degraded—just switch nodes. If every node in a given region turns red, that international route is likely down for maintenance or a fault; wait it out or switch regions. Scattered timeouts aren't worth fixing—they're worth swapping.
| Symptom | Likely Cause | Fix |
| All nodes time out, dashboard shows plan is active | Test URL blocked, or firewall blocking the core | Swap test URL; allow the core process through the firewall |
| All timeouts, browser also shows certificate errors | System clock drift | Turn on automatic time sync |
| Every node in one region is red | Route outage | Switch regions, or wait for the route to recover |
| Numbers look fine, but it still won't connect | Rules are routing to the wrong exit | Go back to C1, cut three, and check the logs |
How to Read Latency Numbers
A latency test measures the round-trip time of a single HTTP request, not bandwidth. An 80ms node might not even saturate 10Mbps, while a 200ms node could run at full speed—latency governs "how fast it responds," bandwidth governs "how fast it downloads." These are separate things. To make latency comparable across different protocols, turn on unified delay:
# config.yaml
unified-delay: true
tcp-concurrent: true
For what the url, interval, and tolerance parameters in an auto-test proxy group actually control, the blog has a hands-on breakdown: Differences Between url-test, fallback, and load-balance Groups.
C3 / Subscription Failures
Subscription Failures: The Error Message Is the Diagnosis
When a subscription won't download, the keyword in the client's error message usually tells you exactly what's wrong. Match it against the table below, then verify by hand.
| Error Keyword | Meaning | Fix |
404 / not found | The subscription URL is dead, or was reset by the provider | Copy a fresh subscription link from the provider's dashboard |
timeout | The subscription domain is blocked on this network, or the endpoint is slow to respond | Connect through a working node first, then update the subscription |
403 / forbidden | The provider restricts the requester's user agent | Fetch it using the client type the provider requires |
| invalid / yaml decode error | What was downloaded isn't a valid config | Verify the content manually using the method below |
Manually Check What the Subscription Actually Returns
Client error messages can be vague. Pulling the subscription down locally with a command makes everything clear:
curl -sSL -A "clash.meta" "https://your-subscription-url" -o sub.yaml
head -n 20 sub.yaml
The first few lines should look like YAML (fields like proxies:, port:, proxy-groups:). If you instead see something starting with <html>, you've pulled the provider's error or block page. If it's one long string with no spaces, that's a base64-encoded generic subscription, which needs to go through a subscription converter before Clash can use it.
Weighing Subscription Conversion
A conversion service handles your subscription URL, and that URL is effectively an account credential. If your provider offers a native Clash subscription, skip conversion entirely. If you must convert, self-hosting the converter is the safest option; failing that, only use an instance you actually trust. If nodes disappear or proxy groups come out garbled after conversion, the template usually doesn't match your subscription format—try a different template.
Subscription URL = Account Credential
Don't paste it into group chats, don't feed it to a converter of unknown origin, and don't post screenshots that include it. If it leaks, reset the subscription in your dashboard immediately—the old link is invalidated right away.
C4 / Slow Speeds
Slow Speeds: Establish a Baseline Before Optimizing
"Slow" is the symptom most likely to get blamed on the wrong thing. Without a baseline, every optimization is guesswork. Run two speed tests: one on a direct connection, one through the proxy. The gap between the two numbers is the actual overhead the proxy chain introduces.
Reading the Baseline
If proxy speed is below 30% of direct-connection speed, it's worth investigating further. If it's only 10-20% lower, that's basically the node's physical ceiling—international bandwidth is inherently more expensive than local broadband, so don't expect proxy speeds to match direct ones.
Three Common Bottlenecks, Ruled Out in Order
- Node side: Low bandwidth, or the route is congested during peak evening hours. Re-test at a different time of day—fast during the day, slow at night is a solid sign of route congestion. Switch nodes or plans; no local tweak will fix this.
- Protocol side: Different transport protocols vary widely in overhead and resistance to interference. When UDP is throttled by a node or route, video calls and QUIC-dependent apps degrade noticeably. Compare protocols on the same server, or confirm whether the node supports UDP forwarding.
- Local side: Running a proxy layer on the router and another on the computer doubles the encryption overhead. On older hardware, heavy encryption protocols can hit the CPU bottleneck first. One layer is enough—don't stack them.
There are two free switches on the core side worth flipping: concurrent handshakes cut connection-setup time, and unified delay makes test results closer to real-world experience:
# config.yaml
tcp-concurrent: true
unified-delay: true
An Engineering Fix for Peak-Hour Slowdowns
Manually switching nodes is a tactic; proxy groups are the strategy. Group a handful of nodes from your usual regions into an auto-test group, and set tolerance as a debounce threshold so it doesn't flip back and forth when two nodes have similar latency:
proxy-groups:
- name: AUTO
type: url-test
url: https://www.gstatic.com/generate_204
interval: 300
tolerance: 50
proxies: [NodeA, NodeB, NodeC]
For heavy-download scenarios, consider a load-balance group to spread traffic across multiple nodes. For how to choose among the three group types, see the blog's hands-on comparison: Differences Between url-test, fallback, and load-balance.
C5 / DNS Issues
DNS Issues: Where Half of All "Mystery Bugs" Come From
DNS trouble has a distinctive signature: some sites load instantly while others spin forever; the proxy is clearly connected, yet a leak-test site shows your resolution exit is still your local ISP; switching nodes fixes some sites and breaks others. These seemingly random symptoms almost always trace back to the resolution layer.
Two Resolution Modes—Understand Before You Tune
Clash-family cores support two enhanced resolution modes. redir-host takes the traditional route: resolve the domain to a real IP first, then match rules—the resolution path is longer and prone to leaking at the local hop. fake-ip has the core return a "fake address" from a reserved range instead (default 198.18.0.0/16), leaving the real resolution to happen at the proxy exit—connections establish faster, no plaintext query is ever made locally, and it's the more recommended default today.
A DNS Config You Can Copy Directly
dns:
enable: true
enhanced-mode: fake-ip
fake-ip-range: 198.18.0.1/16
fake-ip-filter:
- "*.lan"
- "+.local"
nameserver:
- https://doh.pub/dns-query
fallback:
- https://1.1.1.1/dns-query
Line by line: fake-ip-filter is an exemption list—domains listed there never get a fake address, reserved for cases like LAN device discovery and printers that genuinely need a real address. nameserver handles routine resolution over encrypted DNS. fallback covers domains outside mainland China as a backup. The two groups split the work—don't dump every domain onto a single upstream.
Two Ways to Check for Leaks Yourself
A working proxy connection doesn't mean DNS isn't leaking. The quick way: open an online leak-test site and check whether the resolution exit still traces back to your local ISP. The thorough way: capture local traffic and check whether port 53 sends plaintext queries straight out. For full steps on both methods, plus leak-proof config, see the blog: Clash DNS Leak Testing and fake-ip Leak Prevention.
The Side Effect of fake-ip, and How to Fix It
fake-ip isn't free of tradeoffs: some apps cache the fake address, and after you turn off Clash and switch to direct connection, they keep hammering an address starting with 198.18 and hitting a wall—showing up as "turning off the proxy broke the internet." The fix is flushing your system's DNS cache:
# Windows
ipconfig /flushdns
# macOS
sudo dscacheutil -flushcache; sudo killall -HUP mDNSResponder
Rule of Thumb
Add domains sensitive to real IPs—gaming platforms, LAN casting, NAS devices—to fake-ip-filter. Err on the side of a broader exemption list; don't make your printer ask the proxy for an address.
C6 / System Proxy Not Working
System Proxy Not Working: A Notice Isn't an Order
The core principle: a "system proxy" is nothing more than a notice the OS posts—"everyone please route through this port on 127.0.0.1." Applications can read it, or pretend not to see it. Browsers generally comply, terminals never do, and some client software has its own opinion. So this chapter has to be diagnosed app by app.
Browser Not Using the Proxy
- Check that the browser's proxy setting is actually "use system proxy." Firefox defaults to its own proxy settings and ignores the system's—point it manually to
127.0.0.1 and the matching port.
- Proxy-management extensions override the system setting. If you've installed something like SwitchyOmega, disable it and re-test first—leftover old rules in the extension are the number-one suspect for this symptom.
- Cross-check with a different browser: if browser A works and browser B doesn't, the problem is definitely in B's own settings—stop tweaking the client.
Terminal Not Using the Proxy
Terminal programs only recognize environment variables, not the OS's notice. With Clash running, curl, git, and package managers connecting directly is normal, not a bug. Set it manually for the current session:
# macOS / Linux (applies to the current session; use the port from your config)
export https_proxy=http://127.0.0.1:7890 http_proxy=http://127.0.0.1:7890 all_proxy=socks5://127.0.0.1:7890
# Windows PowerShell
$env:HTTP_PROXY = "http://127.0.0.1:7890"
$env:HTTPS_PROXY = "http://127.0.0.1:7890"
Note that tools like git and docker have their own separate proxy settings—environment variables don't always cover everything. If it still won't connect, check each tool's own config file as well.
TUN Mode: Take Over All Traffic at Once
If you don't want to babysit every app individually, use TUN mode: the core creates a virtual network adapter and takes over all traffic at the network layer, so nothing can pretend not to see the notice. The tradeoff is needing admin rights or system authorization, plus a one-time confirmation step to install the virtual adapter. Once TUN is on, turn off the system proxy switch to avoid processing traffic twice. For a full browser-and-terminal troubleshooting log, see the blog: Troubleshooting System Proxy Failures in Browsers vs. Terminals.
C7 / Crashes on Launch
Crashes on Launch: Four Steps Fix Nine Out of Ten Cases
When the client won't open or crashes immediately on launch, nine times out of ten it's one of three things: config parsing failure, a port already in use, or a leftover core process from a previous crash. Follow the four steps below in order—don't skip any.
Step One: Check the Logs
A crash isn't silent—the last words are always in the log. Find "Open Log Directory" or "Open App Directory" in the client's settings and check the last few lines. A YAML parsing failure will point straight to a line number and field name; a port conflict will say address already in use. Following the error message is ten times faster than guessing.
Step Two: Validate the Config
Launch once using the client's "Create Blank Config" or "Restore Default Config" feature. If it starts, the problem is in your config file—go back to the line number the log flagged and fix the YAML. There are three usual suspects: mixed tabs and spaces in indentation, full-width quotation marks sneaking in from a copy-paste, or a field value that needed quotes but didn't get them. If you can't fix it, re-import the subscription and let the provider's original config overwrite your local edits.
Step Three: Check the Port
If another program is already holding the port the core listens on, startup fails outright. Check who's occupying it (swap in the port number from your config):
# Windows
netstat -ano | findstr 7890
# macOS / Linux
lsof -i :7890
Once you find the process holding the port, either end it or move Clash to a different port—change mixed-port in your config to an open value, save, and restart.
Step Four: Clear Leftover Processes
If the core process didn't die along with the last crash, it may still be holding the port and the TUN virtual adapter, causing the new instance to collide on startup. Clear it manually:
# Windows (use the process name as shown in Task Manager)
taskkill /f /im mihomo*
# macOS / Linux
pkill -f mihomo
If all four steps fail, there's one last option: uninstall completely and reinstall the latest version from the Download Center, letting the installer replace the corrupted runtime environment entirely. For a side-by-side look at the most common crash scenarios on Windows vs. macOS, the blog has a dedicated writeup: Locating and Fixing Launch Crashes via Logs.
C8 / Mobile-Specific Issues
Mobile-Specific Issues: Android and iOS Each Have Their Own Quirks
Mobile issues don't follow the same logic as desktop ones: Android's pitfalls cluster around permissions and background management, iOS's around state syncing with the system VPN framework. Let's take them one at a time.
Android: Three Things Handle Nine Out of Ten Problems
- VpnService authorization. Clash on Android relies on the system's VpnService to build a local tunnel; the first connection always triggers a "connection request" prompt that you must tap Allow on. If you accidentally tapped Deny, go to the system's VPN settings page, delete that app's VPN profile, then reconnect from the client—the prompt will reappear.
- Battery whitelist. Custom Android skins are aggressive about killing background processes—if the core gets killed, the connection dies, showing up as "internet drops a few minutes after locking the screen." Adding the client to the battery whitelist and allowing autostart is mandatory on Android. The blog has settings paths for each major manufacturer's system: VpnService Authorization and Battery Whitelisting.
- Per-app proxy. Route only selected apps through the tunnel and let everything else connect directly. This saves battery and sidesteps compatibility issues between specific apps and the VPN tunnel—if an app goes haywire the moment the proxy is on, try kicking it out of the tunnel first.
Grab the Android installer from the Download Center's Android section; Clash Plus is the top pick.
iOS: The System Settings Are the Source of Truth
iOS goes through the system's Network Extension framework, and the client is installed from the App Store—Clash Plus is the top pick. Two frequent pitfalls:
- Toggle state out of sync. The app shows connected, but there's no VPN icon in the status bar—trust the system. Go to Settings → VPN and manually flip the switch for the matching profile.
- Old profiles conflicting. Devices that have had multiple proxy apps installed accumulate several profiles in the system's VPN list, and they fight each other for control. Delete the profiles you no longer use and keep only the one currently in use.
General Note for Mobile
When a phone switches between Wi-Fi and cellular, the tunnel rebuilds, and a few seconds of disconnection is normal. Only persistent drops need the troubleshooting in this chapter.