Proton VPN in one tap. No app to open.
LeanVPN for Android has no screens: it's a Quick Settings tile. It puts you on the fastest server that isn't overloaded, and quietly moves you when it fills up or stops answering. The whole thing is 3.4 MB.
Connected. The second line shows the server and its load.
The problem
Free servers fill up. Your connection shouldn't drop because of it.
A busy server means a stalling connection and a trip into the app to pick another one, again and again. LeanVPN does that job for you: it measures, picks, keeps watching, and switches before you notice. Everything else is gone, including the app itself.
How it picks
The nearest server isn't always the best one.
Every connect takes about a third of a second, measured over your real connection, never through the tunnel.
Shortlist
The 10 best servers by Proton's own score (distance and load from where you are), plus the 6 least-loaded of the 60 nearest. Your plan only; no Secure Core, Tor or maintenance.
Measure
Real latency to every candidate at the same time, with a TCP connect over your normal connection. No guesses from a map.
Score & verify
Lowest score wins. Then it needs a real answer from Proton's in-tunnel DNS, because overloaded servers often complete a handshake and then carry nothing.
With load from 0 to 1, it barely matters while it's low and takes over as a server nears saturation. Try it: drag the nearby server's load.
| Server | Latency | Load | Score |
|---|---|---|---|
| Nearby | 40 ms | 283 | |
| Farther | 90 ms | 117 |
LeanVPN picks Farther. It's 50 ms slower on paper, but it won't buckle.
Once connected
It keeps checking, so you don't have to.
Every 10 seconds, while the phone is awake, it reads two counters from WireGuard. It costs nothing until something looks wrong, and it never wakes the phone up.
- Stall detectionSending but nothing coming back for 20 s, or no handshake for 200 s, triggers a check through the tunnel. No answer and it moves to the next-best server, avoiding the dead one for 30 minutes.
- Load watchEvery 15 minutes it refreshes loads. At 85% or more, if a server at least 20 points lighter exists, it moves. A server going into maintenance is left right away.
- Wi-Fi ↔ mobile dataWireGuard roams between networks by itself; if traffic stalls anyway, the checks catch it. A failed attempt retries the moment a network comes back.
- Kill switch, Android's wayTurn on Always-on VPN and "Block connections without VPN" for LeanVPN in Settings. Android then keeps it running from boot and blocks anything outside the tunnel.
Install
Four taps and a code.
You need Android 10 or later on a 64-bit phone, and a Proton account. Free works.
Download and install the APK
Get LeanVPN-<version>.apk from GitHub Releases and open it. Allow installs from your browser when Android asks; if Play Protect warns about an unknown developer, choose Install anyway.
Open it once, add the tile
Android asks "Add LeanVPN tile to Quick Settings?"; tap Add tile. That's the only time you'll open the app.
Allow the VPN
Android's own prompt, once: "LeanVPN wants to set up a VPN connection". Tap OK.
Sign in with a code
Your browser opens account.protonvpn.com/appletv with an 8-character code already copied. Sign in to Proton, paste it and approve, then pull down Quick Settings: the tile shows your server. Your password never touches LeanVPN.
If the page doesn't load on your network, switch to mobile data for a moment, or open it on any other device and type the code shown on the tile.
Build it yourself instead
No Android Studio or Gradle: a Makefile drives the SDK tools directly. It takes about a minute.
$ brew install openjdk@21 && brew install --cask android-commandlinetools
$ sdkmanager --sdk_root="$HOME/Library/Android/sdk" "platforms;android-35" "build-tools;35.0.0" "platform-tools"
$ git clone https://github.com/ZephyrSai/LeanVPN-Android.git
$ cd LeanVPN-Android && make install
Long-press the tile any time for Switch server and Sign out. The full guide covers troubleshooting, battery settings on OnePlus, Xiaomi and Samsung phones, and logs.
Deliberately missing
Everything else.
Small is the feature. If you need any of these, the official app is excellent.
Honest status
Alpha: tested on one phone.
The server choice and failover logic is the same as in the Mac version, which is in daily use. The Android side is new. Please report anything odd, with logs.
Verified
- Install, adding the tile, the VPN permission
- Code sign-in and connecting automatically afterwards
- Keys byte-for-byte identical to the Mac version's
- Live HTTPS to Proton through a network that blocks it
Needs more testing
- Failover between servers on a phone, multi-day sessions
- Wi-Fi ↔ mobile data while connected, Always-on at boot
- Battery use, other phone makers, Android 10–15
- Paid plans
FAQ
Questions
Is this an official Proton app?
No. LeanVPN is an independent, unofficial project, not made or endorsed by Proton AG. It uses Proton's API the way Proton's own apps do. "Proton" and "Proton VPN" are trademarks of Proton AG.
Where's the app?
There isn't one to look at. Opening LeanVPN only offers to add its tile; after that, everything happens from Quick Settings. Long-press the tile for a small menu with Switch server and Sign out.
Does it work with a free Proton account?
Yes, that's what it was built on. With a free plan it chooses among Proton's free servers; with a paid plan it can use any non-Secure-Core server.
Why does it sign in as the Apple TV app?
LeanVPN uses Proton's "enter a code on the web" sign-in so it never handles your password. Proton's code page only approves codes for its Apple TV app, so LeanVPN uses that app's identifier when signing in. Proton could change or block this at any time, and using an unofficial client may be against Proton's terms.
Where is my sign-in stored?
In the app's private storage, which other apps can't read, with backups switched off. LeanVPN talks only to vpn-api.proton.me and the VPN servers: no analytics, crash reporting, ads or Google services.
Does it drain the battery?
When it's off, it does nothing at all. When it's on, the health check runs every 10 seconds only while the phone is awake and never wakes it, and WireGuard's keepalive is Proton's 60 seconds. On phones with aggressive battery savers (some OnePlus, Xiaomi and Samsung models), set LeanVPN's battery use to Unrestricted if it disconnects.
Is there a kill switch?
Use Android's: Settings → Network → VPN → LeanVPN → Always-on VPN plus "Block connections without VPN". Nothing leaves the phone outside the tunnel, even while LeanVPN switches servers.
What about IPv6?
On servers that support it, IPv6 goes through the tunnel. On the others it's routed into the tunnel and dropped, so nothing leaks around it.
Is it on Google Play or F-Droid?
Not yet. Install the APK from GitHub Releases, or build it yourself from source.
Is there a Mac version?
Yes: LeanVPN for macOS lives in the menu bar and works the same way.