Proton VPN, minus everything but the connection.
LeanVPN lives in your Mac's menu bar, puts you on the fastest server that isn't overloaded, and quietly moves you when it fills up or stops answering. No window. No settings. 6 MB.
Connected: hover the shield for server, load and latency.
The problem
Free servers fill up. Your connection shouldn't drop because of it.
With the official app, a busy server meant a stalling connection and a trip to the server list, again and again. LeanVPN does that job for you: it measures, picks, keeps watching, and switches before you notice anything.
How it picks
The nearest server isn't always the best one.
Every connect takes about a third of a second, and it all happens outside the tunnel on your normal connection.
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.
The check every 10 seconds is two counters read from WireGuard. It costs nothing until something looks wrong.
- Stall detectionSending but nothing coming back for 20 s, or no handshake for 200 s, triggers a probe. Two failed probes and it moves to the next-best server, and the dead one is avoided 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.
- Network changesWi-Fi to Ethernet, sleep and wake, DHCP renewals: it re-pins the server route, rebinds the socket and re-applies DNS.
- RenewalsSession certificates and sign-in tokens renew themselves. If you were connected when you shut down, it reconnects at login.
Install
Three commands and a code.
LeanVPN is built from source on your Mac. No Xcode, no developer account. You'll need an Apple silicon Mac on macOS 13 or later and a Proton account (Free works).
Get the build tools
Apple's Command Line Tools and Go. Skip whichever you already have.
$ xcode-select --install
$ brew install go
Build and install
It asks for your admin password once, to install the small background helper that creates the VPN interface. Then the shield appears in your menu bar.
$ git clone https://github.com/ZephyrSai/LeanVPN.git
$ cd LeanVPN
$ make install
Sign in with a code
Click the shield, then Sign In…. Your browser opens account.protonvpn.com/appletv with the code already copied. Paste it, approve, and LeanVPN connects by itself. Your password never touches LeanVPN.
Quit the official Proton VPN app first: two VPNs at once fight over routes and DNS. If the sign-in page doesn't load on your network, open it on your phone and type the code from the menu.
Removing it is one command, make uninstall, which also restores your DNS and deletes the saved sign-in. The full guide covers troubleshooting 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 Mac.
It's the author's daily VPN, but one machine is a small sample. Please report anything odd, with logs.
Verified
- Code sign-in, connect, location-aware ranking
- Failover off a server that handshakes but carries no traffic
- All IPv4 through the tunnel, DNS via Proton, IPv6 blocked, Proton exit IP
- Auto-reconnect after the helper restarts
- Footprint and idle CPU above, about 40 Mbit/s on a free server
Needs more testing
- Multi-day sessions, sleep and wake cycles
- Wi-Fi ↔ Ethernet ↔ phone tethering mid-session, captive portals
- Certificate and token renewal over long sessions
- Paid plans, macOS 13–15, other networks
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.
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?
Session tokens and the WireGuard key live in /Library/Application Support/LeanVPN/, readable by root only. The helper only takes commands from your user account. LeanVPN talks only to vpn-api.proton.me and the VPN servers: no telemetry, analytics or update checks.
Is there a kill switch?
No. If the tunnel drops, traffic goes out normally until LeanVPN reconnects, which usually takes seconds. If you need a hard kill switch, use the official app.
What about IPv6?
While connected, IPv6 is blocked so nothing leaks around the IPv4-only tunnel. It comes back as soon as you disconnect.
Intel Macs? Older macOS?
Apple silicon and macOS 13 Ventura or later only, for now. It's tested on macOS 26.
My network blocks Proton. Will this work?
Some networks silently drop the TLS handshake to Proton's API. LeanVPN splits the first handshake packet in two, which gets past that on the networks it's been tried on. The sign-in web page itself may still be blocked; open it on your phone over mobile data instead.
How do I uninstall it?
Run make uninstall in the cloned folder. It disconnects, restores your DNS, and removes the app, the helper and the saved sign-in.