Slow Clash Speeds
Troubleshooting by Layer
Troubleshoot slow speeds in three layers: node load, route quality, and local settings. Check from your device outward before switching nodes.
First, identify the problem: slow connections, slow downloads, or slow access to specific sites
The latency number in the Clash dashboard reflects a probe to one specified address. It is not a measure of download bandwidth or the quality of access to every website. A node showing 80 ms may deliver very low speeds if its exit is congested; one showing 180 ms may sustain downloads more reliably. Describe the symptoms first, then decide what to check.
| Symptom | Check first | How to verify |
|---|---|---|
| Long wait after clicking; download speed is normal once it starts | DNS, connection setup, target response | Record time to first byte and total time separately |
| Starts quickly, then stays slow | Node load, exit bandwidth limits, packet loss | Repeat the test with the same file and node |
| Browser is fine, but terminal or games are slow | Whether the traffic is actually going through the proxy | Check connection logs and the app's proxy settings |
| Only one website or download source is slow | Site throttling, CDN, exit location | Cross-check with a separate download source |
| All apps slow down when TUN is enabled | Routing, DNS, conflicts with other VPNs | Turn off TUN and compare using an explicit proxy |
Before testing, pause cloud sync, game updates, and other bandwidth-heavy tasks. Use one device, one network connection, and one target address; run each test at least three times. Record the time, rule mode, actual node, download speed, and any errors. Switching nodes repeatedly during a test can send different connections through different exits, making the results hard to compare.
Layer 1: Check the local listener and actual traffic path
Don't assume the example port is your current port
Open the client's port settings and check the active HTTP, SOCKS, or mixed port. A common example is 7890, but some clients use a different value. An HTTP port cannot be used as a SOCKS port; mixed-port accepts both HTTP and SOCKS proxy requests on the same listening port.
This mihomo configuration snippet illustrates the listener setup; it is not a complete subscription with nodes, proxy groups, and rules. A GUI client may generate its own runtime configuration, so make changes in the client settings first to avoid having them overwritten when the subscription updates.
mixed-port: 7890
allow-lan: false
mode: rule
log-level: info
mixed-port: 7890: Local apps can connect to127.0.0.1:7890to use the proxy.allow-lan: false: Does not expose the proxy to your local network; you don't need to enable it when troubleshooting on this device.mode: rule: Rules choose the policy; this does not mean every connection uses the proxy.log-level: info: Keeps routine troubleshooting details without generating excessive debug logs over time.
Start with an explicit proxy request
In Windows PowerShell, use curl.exe to avoid environments that interpret curl as a different command. This request checks whether the HTTP proxy listener and HTTPS tunnel work; it does not measure large-file download speed. If your port isn't 7890, replace the port in the command first.
curl.exe --noproxy "" --proxy http://127.0.0.1:7890 --connect-timeout 10 --max-time 30 -I https://example.com/
On macOS or Linux, replace curl.exe in the command with curl. In the client's Connections page, filter for example.com and check the matched rule, proxy group, and final exit. Specifying a local proxy only confirms that the request reaches the core; the rules may still route the destination to DIRECT.
If you can't connect to the local port, first check whether the core is running and whether the port is already in use; don't switch remote nodes. On Windows, run the command below to check the listening port and PID. No output usually means nothing is listening on that TCP port. If a PID appears, find the corresponding process in Task Manager under Details.
netstat -ano | findstr LISTENING | findstr :7890
Layer 2: Check node load and proxy group selection
Node names are usually labels assigned by the provider; they don't prove the physical location or actual route. For troubleshooting, select a specific node in the proxy group and check the connection details. If the test group uses url-test, fallback, or load-balance, new connections may switch nodes or be assigned to different exits automatically. Don't assume a proxy group name identifies a fixed node.
- Select node A in the proxy group currently handling the connection. For an automatic group, you can temporarily use an existing manual selection group. Back up your configuration first; don't overwrite the entire subscription.
- Stop the current download and start a new connection. Switching nodes usually won't move an established TCP connection to a new exit.
- Run the same download from the same source three times, observing each run for about 30 seconds. Record the sustained speed, not just the initial peak.
- Repeat the same steps with node B. Prefer a node on a different route or from a different provider, rather than one with a similar name.
- Run the test again at a different time. Slow speeds in the evening but normal speeds during the day may point to capacity or route congestion, but don't prove the server is overloaded on their own.
How to tell whether the node is slow or the test source is
If node A is slow with two independent download sources but node B works normally on the same device and network, first suspect A's ingress, exit, or resource limits. If every node is slow with just one download source, check that site's per-connection speed limits, account restrictions, and CDN routing. Results from public multi-connection speed tests also aren't a substitute for a browser's single-file download speed.
Layer 3: Separate your local network from the remote route
“Direct works, proxy is slow” can have several causes: congestion between your ISP and the node's ingress, poor quality between the node's exit and the target site, or restrictions on connections using the proxy protocol. Switching networks on the same device is an effective way to distinguish between them.
| Comparison | Keep constant | What it can reveal |
|---|---|---|
| Wi-Fi vs. Ethernet | Device, node, target file | Wireless interference, signal strength, and local network contention |
| Home broadband vs. mobile hotspot | Device, node, target file | Differences in the routes from each carrier to the node ingress |
| Two devices on the same network | Node, target file, test time | Differences in local software, permissions, and device performance |
| Two target sites through the same node | Device, network connection | Routing from the exit to the target and site restrictions |
On Windows, use ipconfig to find the current default gateway, then run ping -n 30 against the actual gateway address. On macOS or Linux, use ping -c 30. Don't assume an example gateway address is your router's address. If latency on your local network fluctuates significantly even when idle, or you see persistent packet loss, check the Wi-Fi channel, distance, Ethernet cable, and router load first.
Pinging or tracing the route to a node's ingress can provide supporting evidence, but it's not conclusive. Some servers don't respond to ICMP, and intermediate routers may limit probes. Packet loss shown at one hop doesn't mean forwarded traffic is being lost if later hops and the final destination are fine. Don't diagnose a node failure from a single traceroute screenshot.
Slow only during uploads or downloads
If things are fine when idle but web pages and voice calls become sluggish after you start uploading, your upstream may be saturated and causing queueing. Limit uploads to about 80%–90% of available upstream bandwidth, then test again. This range is a starting point, not a universal optimum; routers with queue management support can be tuned further. Don't change the client, router, and node at the same time, or you won't know which change helped.
Use curl to compare wait time and transfer speed
Testing an HTTPS file with a known size that allows sustained downloading makes comparisons more useful than repeatedly refreshing a web page. Don't estimate bandwidth from a page that's only a few kilobytes, and avoid URLs that require a browser login, CAPTCHA, or short-lived signature. The following command works in common macOS and Linux shells. Enter a download URL you've verified; the file won't be saved to disk.
printf 'Enter the HTTPS URL of the test file: '
IFS= read -r test_url
curl --noproxy "" \
--proxy http://127.0.0.1:7890 \
--location \
--connect-timeout 10 \
--max-time 30 \
--output /dev/null \
--write-out '\nhttp=%{http_code}\nfirst_byte=%{time_starttransfer}s\ntotal=%{time_total}s\nbytes=%{size_download}\nspeed=%{speed_download} B/s\n' \
"$test_url"
http: First check that the response contains valid content, not a 403, 429, or error page. A 206 response may mean the server returned partial content.first_byte: Time from the start of the request until the first byte arrives. This includes connection setup and handshakes; it's not DNS time alone.total: Total time for the request. Redirects, server response time, and the transfer itself all affect it.speed: Average download bytes per second reported for this transfer. Consider it alongside the amount of valid content and the test duration.
If a large file isn't transferred within 30 seconds, the command may exit with a timeout error. That's expected with the --max-time 30 limit. Check how many bytes were downloaded rather than treating every timeout as a connection failure. If the test file finishes in seconds, choose a larger file or note that the result is only a short sample.
When using an HTTP proxy to reach an HTTPS destination, the proxy route usually handles DNS resolution for the target domain. curl's local DNS timing does not directly measure how long mihomo takes to resolve the destination. If time to first byte is high, check the core logs, matched rules, and active DNS configuration; don't rely on a single timing field.
Local settings: Test system proxy, TUN, and DNS separately
Start with one traffic interception method as your baseline
The system proxy mainly affects apps that read the system settings. Terminals, some games, and apps with their own network stack may ignore it. TUN uses a virtual network interface and routing to capture eligible IP traffic, but it is still affected by rules, exclusions, permissions, and platform-specific implementation. It doesn't mean every connection goes through the remote proxy.
- Pause other VPNs, accelerators, and proxy apps. Check for duplicate system proxy settings or virtual network interfaces intercepting traffic.
- Turn off TUN first and establish a baseline with the explicit proxy curl command above; this does not depend on apps reading the system proxy settings.
- Then enable the system proxy and check your browser. In Windows 11, go to Settings → Network & internet → Proxy to check the system settings, and see whether a browser proxy extension is overriding them.
- Enable TUN only when you need to capture traffic from apps that don't support proxies. Confirm the client service is installed, grant the required permissions, and compare using new connections.
If speeds drop only when TUN is enabled, focus on routing conflicts, DNS hijacking settings, and the virtual network interface status. Don't start by changing the MTU. Check the path MTU only if you can reproduce symptoms such as small requests working while large responses or specific connections repeatedly stall, and you've ruled out other causes. Record the original value before making changes, and change one thing at a time.
Don't assume adding more DNS servers makes DNS faster
mihomo's dns.nameserver, dns.proxy-server-nameserver, and dns.nameserver-policy handle different things. Resolving a node server's hostname is also different from resolving a target website's domain. Follow the current core documentation and subscription design when making changes. Avoid making the DNS needed to resolve a node depend on a proxy route that hasn't been established yet.
With fake-ip, a mapped address returned to the client may be normal; don't assume it's a DNS error. If only a few apps have compatibility issues, consider using fake-ip-filter for the affected domains instead of disabling the entire DNS module. Test with and without IPv6 to identify IPv6-related issues; disabling IPv6 is not a universal fix for slow speeds.
If the configuration won't load, check the core error before running speed tests. If you use the mihomo command line, run the check below from the configuration directory. GUI clients have their own configuration validation and log tools. Passing syntax validation only means the configuration can be parsed; it doesn't guarantee that nodes work or rules behave as intended.
mihomo -t -f config.yaml
Wrap up: Reach reproducible conclusions with minimal changes
A useful troubleshooting round should show which metric changed when a specific condition changed. For example, if the same device, node, and file are slow on home broadband but fine on a mobile hotspot, investigate the route from the access network to the node's ingress first. If node A is slow for two targets and node B works on the same network, ask the provider to check A's route and resources.
- Only the browser is slow: Check proxy extensions, the site's cache, and which rule the site actually matches. There's no need to reinstall the entire client first.
- Every node is slow: Check the direct-connection baseline, local listener, background traffic, and other networking software; then investigate any restrictions shared by the provider.
- Only automatic proxy groups are slow: Test with a fixed node and check the probe URL, switching behavior, and the actual exit used for new connections.
- Speeds dropped after a subscription update: Compare proxy groups, rule order, and node changes, and keep a backup. Don't compare subscription file sizes alone.
- Asking for help: Include your OS version, client version, core version, time of test, network connection, reproduction steps, and redacted logs.