Skip to content
proton-cli

How it works

proton talks to the same API as the Proton web apps, with the same authentication and the same encryption. Nothing proxies your data, and no server other than Proton's sees it.

  1. Session - an unauthenticated session is created via POST /auth/v4/sessions.
  2. SRP - login runs Secure Remote Password through Proton’s own go-srp, so your password is never sent to the server, not even hashed. Two-factor codes are handled in the same exchange.
  3. Key password - the salted password derived during login is what unlocks your PGP keys. It stays on your machine.
  4. Session file - tokens plus the key password (encrypted with a random client key held server-side) are written to ~/.config/proton-cli/sessions/<profile>.json with mode 0600, so later commands don’t re-authenticate. Security documents this storage model in full.
  5. Refresh - expired access tokens are refreshed automatically.

Proton may occasionally require human verification during step 2. See Human verification.

Proton’s encryption is a tree, and proton walks the same one as the web client, using gopenpgp:

key password
└── user key
├── address keys (mail, signing)
├── calendar keys (events)
├── drive node keys (files and folders)
├── contact encryption (contact cards)
└── pass vault keys (vault and item keys)

Unlocking happens lazily, and alongside everything else: a command that only lists metadata never touches your keys, and one that decrypts asks for them at the same time as the content they will open, so the keys cost no round trip of their own. Below the user key, only the branch a command actually reads is unwrapped - a calendar’s keys, a vault’s, a file’s.

Content Encrypted with Signed with
Mail bodies and attachments Session key per message Address key
Calendar events Calendar key Address key
Drive file contents Node key, per block Address key
Drive file and folder names Parent node key Address key
Contact cards User key User key
Pass items AES-256-GCM item key symmetric, no signature
Pass vaults AES-256-GCM vault key symmetric, no signature

Reading works the other way around: content arrives encrypted, gets decrypted locally, and signatures are verified against the sender’s key. mail messages get reports the verdict on a Signature: line.

  • API requests to https://mail.proton.me/api over HTTPS, authenticated with your session tokens.
  • Encrypted payloads you asked to create: an encrypted message, an encrypted file block, an encrypted event.
  • The SRP proof during login, which does not reveal your password.

What never leaves: your password, your key password, and your private keys.

The endpoint shapes are generated from Proton’s own open-source web client into openapi.yaml, covering roughly 740 endpoints. A weekly workflow regenerates it, so the CLI tracks upstream changes rather than guessing.

Proton guards its most destructive endpoints behind an elevated session scope. A request that needs one and hasn’t got it comes back refused, and the client is expected to prove a human is present: re-run SRP against a scope-granting endpoint, retry the request, then drop the scope again.

proton handles that in the transport layer, the way the web clients do, rather than in each command. So no command has to know which operations are guarded - it runs, the server asks, your password is requested once, the request is retried, and the elevation is dropped immediately afterwards.

Both halves of SRP are verified, on the initial sign-in and on every elevation: the server has to prove it knows your verifier just as you prove you know your password.

A TOTP code is asked for only when the account actually has one enabled, so a code is never wasted on a guess.

Security keys (FIDO2/WebAuthn) need a browser, so proton cannot sign in with one.