LeanVPN Android
Alpha Unofficial client for Proton VPN · Android

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.

Free & open source (GPL-3.0)Android 10+Works with Proton Free

Connected. The second line shows the server and its load.

3.4MB
the whole app
installed size, nothing extracted
64KB
of app code
the rest is the WireGuard engine
2
permissions
internet and network state
0
screens
just the tile

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.

1

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.

2

Measure

Real latency to every candidate at the same time, with a TCP connect over your normal connection. No guesses from a map.

3

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.

score = latency_ms + 300 × load²

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.

90%
ServerLatencyLoadScore
Nearby40 ms
283
Farther90 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.

1

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.

2

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.

3

Allow the VPN

Android's own prompt, once: "LeanVPN wants to set up a VPN connection". Tap OK.

4

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.

ScreensSettingsCountry pickerSecure CoreNetShieldSplit tunnelingPort forwardingNotificationsWidgetsGoogle servicesAnalyticsAuto-update

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.