Start with a comparison: separate traffic use, idle drain, and battery attribution
A phone getting warm while Clash is running does not necessarily mean the proxy core is constantly maxing out the CPU. Video downloads, cloud photo uploads, and cellular retransmissions in a weak-signal area can all happen at the same time. Android's local VPN receives traffic from other apps, so the system battery screen may attribute some network activity to the VPN client. Battery reporting also varies by system. Check total battery drain first, then the app rankings; do not focus only on the top entry.
Run two tests, each for at least 60 minutes
- Keep conditions consistent: Use the same Wi-Fi network, a similar starting battery level, and the same room temperature. Pause downloads and system updates, and do not test while charging.
- Test once with the proxy off: Lock the screen for 60 minutes and record the starting and ending battery levels, any heat, background apps, and signal conditions.
- Test once with the proxy on: Use the same node and configuration, then lock the screen for 60 minutes. Repeat two or three times, alternating the test order when possible.
- Add a cellular test: If the problem is clearly worse only on mobile data, check signal strength, network switching, and connection retries before changing the TUN stack.
For example, if the battery drops from 80% to 77%, record that as “a 3-percentage-point drop in one hour”; do not use it to estimate precise power consumption. The fields below are for tracking, not results from tests conducted by this site. Battery readings are rounded, so when the difference is small, testing for 3–6 hours will give you a more useful comparison.
| What to record | Details | Why it matters |
|---|---|---|
| Software environment | Client version, core version, Android version | Keep results before and after upgrades separate |
| Network conditions | Wi-Fi or cellular, node, test duration | Rule out differences in the connection |
| Battery and temperature | Starting and ending percentages, noticeable heat | Track changes across the whole device |
| Runtime status | Whether the service restarted or the network reconnected | Identify repeated background launches |
Background activity: keep necessary permissions and prevent repeated restarts
Android clients typically use VpnService to create a local VPN interface, then pass traffic to the core for processing. A persistent system notification does not mean the app is under constant heavy load. On the other hand, hiding the notification by force or restricting background activity can stop the service, which may then restart automatically and cause disconnections or repeated initialization.
Check these three Android settings
- Battery restrictions: Common paths on Android 13–15 include “Settings” → “Apps” → “See all apps” → select the client → “App battery usage.” Some systems show “Battery” → “Unrestricted / Optimized / Restricted.” Exact labels vary by phone.
- VPN settings: On stock Android, try “Settings” → “Network & internet” → “VPN” → the settings icon next to the client. Check “Always-on VPN” and “Block connections without VPN.” The latter blocks traffic when disconnected; it is not a battery-saving switch.
- Manufacturer background controls: On the app info page, check options such as “Autostart” and “Run in background.” Adjust only the client first; do not exempt every background app at once.
If the connection remains stable with the screen locked and there are no records of the service stopping, you do not need to enable scheduled restarts, third-party keep-alive tools, or periodic network requests just to “keep it alive.” If the connection drops when the screen locks, first allow the client to run normally in the background, then compare battery drain. Test power use and connection stability separately rather than repeatedly changing permissions and hoping for the best.
Routing only the apps that need it through the VPN can reduce the number of connections the core handles, but it does not guarantee lower battery use across the whole device: excluded apps may still download data in the background. After each change, check your browser, message notifications, maps, and local network access so that missing functionality is not mistaken for a successful battery fix.
Scheduled tasks: check health checks before subscription updates
Periodic network activity while idle often comes from node health checks, automatic selection policies, or subscription and rule updates. These are different kinds of scheduled tasks: node probes test availability, subscription updates download configuration or node lists, and rule updates refresh matching data. Setting all three to run every few dozen seconds can easily create unnecessary requests.
Consider the interval and number of nodes together
Suppose a node group contains 80 nodes and runs a full probe every 60 seconds. Based on scheduling alone, that is 4,800 probe attempts per hour; increasing the interval to 600 seconds brings it to 480. Actual counts also depend on lazy checks, failure handling, and the client implementation. This is an example of configuration scale, not a battery test, and it does not mean all nodes connect at once.
- While troubleshooting, turn off unnecessary automatic speed tests or change a 60-second interval to 600–1800 seconds.
- Temporarily use a manual selection policy and observe screen-locked battery use with the same node to rule out frequent automatic switching.
- For a typical subscription, start with an update every 24 hours. Shorten the interval if you need changes sooner.
- Avoid multiple groups running frequent probes against the same nodes. Health checks and proxy-group tests may each send their own requests.
Example mihomo provider settings
The snippet below is only for replacing the corresponding fields of an existing HTTP provider under proxy-providers. Keep its existing name, subscription URL, and path; do not paste this directly at the YAML top level. Both interval values here are in seconds, while timeout is in milliseconds.
interval: 86400
health-check:
enable: true
url: https://www.gstatic.com/generate_204
interval: 600
timeout: 5000
lazy: true
lazy: true reduces periodic checks for providers that are not in use; it does not disable all probes for nodes currently in use. The test URL must be reachable through the relevant node. If the current network cannot reach it, an address problem may be mistaken for a node failure. Some fields may not be supported by older Clash cores. Confirm the core type before importing, then check for configuration errors after saving.
A client's “automatic subscription updates” may run independently of provider updates in YAML. Check both places; changing one interval is not enough. A hosted configuration may also overwrite manual edits on its next update, so use the client's override or merge feature if available.
DNS polling: use logs to find repeated requests instead of changing resolvers blindly
Normal DNS queries are usually triggered when apps resolve domain names. Enabling fake-ip does not by itself make a phone query every domain at fixed intervals; it mainly changes domain mapping and connection handling. What looks like “DNS polling draining the battery” may actually be app retries, health checks, encrypted DNS connection resets, or a loop in the DNS configuration.
Enable logs briefly and look for three patterns
- The same domain appears every few seconds: Check whether it comes from messaging, ad requests, sync tasks, or a speed-test URL. If needed, pause the relevant app and see whether the requests stop.
- Many timeouts are followed by immediate retries: Check whether the upstream DNS server is reachable, whether it depends on a proxy connection that is not yet established, and which bootstrap resolver is used for the upstream hostname.
- Local addresses repeatedly forward to each other: Check whether the client's DNS is pointing back to an entry it intercepts. Do not use a
127.0.0.1listening port as an upstream at the same time; that creates a loop.
During troubleshooting, keep one verified reachable DNS upstream, pause redundant overrides, then restore settings one at a time. Do not clear all DNS rules to save power or force cache expiration times to be much longer; doing so can delay updates when a domain's address changes. nameserver-policy selects resolvers by domain; it is not a master switch for reducing scheduled tasks.
Also note the Android setting under “Settings” → “Network & internet” → “Private DNS.” System Private DNS, browser Secure DNS, and a client's built-in DNS may all be active. The exact behavior depends on VPN routing and app implementation. Intercepting port 53 in TUN does not mean that all encrypted DNS can be intercepted. When comparing settings, change only one thing at a time, then restore the option that meets your privacy needs.
Log level and connection screen: reduce overhead after troubleshooting
Debug logs add formatting, writing, and screen-refresh overhead. You can enable them temporarily while diagnosing a problem, but they are not ideal to leave running with a live log screen open. A connection list that refreshes every second also adds frontend work. When testing battery drain with the screen locked, leave the dashboard rather than keeping it lit.
For everyday use, start with the mihomo log level below. It belongs at the top level of the configuration, alongside dns and tun. The correct value here is warning, not warn.
log-level: warning
- When reproducing an issue, temporarily switch to
infoand capture just 5–10 minutes. - Enable
debugonly when you need more detailed diagnosis; avoid continuously exporting large logs during testing. - Before sharing logs, redact tokens in subscription URLs, node credentials, and personal browsing records.
- If the client has a separate setting for interface logs, check it too; the core log level may not control every frontend log.
Reducing the log level mainly cuts logging overhead; it will not fix packet loss on a node or a DNS loop. If errors continue to appear frequently, address their cause instead of merely hiding them in the logs.
TUN stack and node protocol: choose based on results from your device
On Android, VpnService provides a virtual network interface, and the client decides how to process the packets it receives. TUN switches in desktop guides do not map directly to Android implementations. Some mobile clients create the interface themselves, so the YAML tun field may not control all of their behavior.
Check available options, then change one variable at a time
Common mihomo stack options include system, gvisor, and mixed, but which options a mobile client exposes and how it integrates them depends on the version. There is no “most battery-efficient stack” that works for every phone. Keep the default if it is stable; test another supported stack only if there is sustained CPU use, UDP trouble, or a known compatibility issue.
- Record the full client and core version numbers, and back up a working configuration.
- Change only the stack; keep the node, rules, DNS, and test network the same.
- Re-establish the VPN as prompted by the client, then test both idle time with the screen locked and normal use.
- Check web browsing, voice calls, game UDP, IPv6, and local network access. Revert if anything regresses.
Packet loss, congestion, and protocol implementation on the node side can also affect battery use. Repeated reconnects on a weak network are more concerning than a single successful handshake. First try a stable node using the same protocol, then compare protocols. Do not change nodes, disable IPv6, and switch stacks all at once, or you will not know which change helped.
Battery-saving checklist: work from low-risk changes to higher-risk ones
| Order | Change | How to verify |
|---|---|---|
| 1 | Close the live log screen and use warning for everyday logging | Errors no longer flood the screen and features work normally |
| 2 | Set the health-check interval to 600 seconds to reduce repeated tests | Nodes remain usable and probes run less often |
| 3 | Set subscription updates to every 24 hours to start | Configuration updates normally without repeated downloads |
| 4 | Fix DNS timeouts and retry loops | The same errors stop appearing and domains resolve normally |
| 5 | Adjust background permissions and app lists as needed | Connections, notifications, and necessary traffic work with the screen locked |
| 6 | Compare nodes and TUN stacks | Repeated tests show improvement with no loss of functionality |
iPhone users should also compare results under the same network conditions, but should not copy Android battery-exemption lists or VpnService menu steps. iOS clients usually rely on Network Extension; check subscription updates, speed tests, and logging in the specific app. The mihomo YAML examples in this article apply only when the client explicitly supports the corresponding settings.
Still draining battery? Submit a reproducible issue report
If the phone still gets hot after these steps, a minimal reproduction report is more useful than simply saying “background activity drains the battery.” When submitting an issue to the client project, include at least the following:
- Phone model, OS version, client version, core version, and whether the issue first appeared after an upgrade.
- Wi-Fi or cellular conditions, whether the screen was locked, test start and end times, and total battery drain in both proxy-on and proxy-off tests.
- Health-check and update intervals, log level, TUN stack, and whether per-app proxying is enabled.
- Brief logs with sensitive information removed, the time of the first unusual event, and whether it coincided with a service restart or network change.
If battery drain is still significant with the proxy off, investigate signal strength, background sync, battery health, and system update tasks instead. The troubleshooting order is always to measure first, reduce unnecessary wakeups next, and adjust lower-level implementation last. Change one setting at a time and keep a rollback configuration so results remain comparable. For more basic instructions, see the setup guide. For connection issues, continue with the full troubleshooting guide.