Every IP address ProtonVPN exits and enters from, refreshed daily. Scraped from the Proton API by a GitHub Action, committed as plain files.
| File | Contents |
|---|---|
protonvpn_ips.txt, .json |
exit IPs, the address a site sees |
protonvpn_entry_ips.txt, .json |
entry IPs, the address a client connects to |
protonvpn_entry_ip_ranges.txt |
CIDRs of the ASNs behind the entry IPs |
protonvpn_subdomains.json |
server hostnames |
protonvpn_logicals.json |
the full API response, every field |
import json
with open("protonvpn_ips.json") as file:
exit_ips = set(json.load(file))
"84.247.50.181" in exit_ips # TrueRanges are CIDRs behind a # header:
import ipaddress
with open("protonvpn_entry_ip_ranges.txt") as file:
networks = [
ipaddress.ip_network(line.strip())
for line in file
if line.strip() and not line.startswith("#")
]
address = ipaddress.ip_address("146.70.120.210")
any(address in network for network in networks) # TrueThese are whole ASNs and overshoot, only shared ISP and CDN ones are trimmed to their entry IPs. Prefer the IP lists.
ASNs come from the iptoasn.com combined table, cached for
a day in $XDG_CACHE_HOME/ip2asn. Trimming of the shared ASNs keeps the ranges
that X4BNet/lists_vpn also flags as VPN,
plus the ranges holding an entry IP.
python main.py # logicals, exit IPs
python entry_ips.py # entry IPs, ASN ranges
The API needs a logged-in session. Take four cookies from account.protonvpn.com (F12, Web Storage, Cookies) into secrets:
| Secret | Cookie |
|---|---|
AUTH_PM_UID |
the {uid} in the AUTH-{uid} name |
AUTH_TOKEN |
value of AUTH-{uid} |
REFRESH_TOKEN |
value of REFRESH-{uid} |
SESSION_ID |
value of Session-Id |
A fifth, GH_TOKEN with Contents: Read/Write and Secrets: Read/Write, lets
the workflow write refreshed tokens back. Auth rotates every ~24 h by itself,
REFRESH_TOKEN dies after ~180 days. Free accounts see fewer servers than paid.
Fork it. Two files, stdlib only, nothing to install, point any daily cron at
main.py and entry_ips.py with your own four cookies. GitLab CI, Woodpecker,
sourcehut, a Raspberry Pi under a desk.
Running one? Open an issue and it gets linked here. Mirrors, rewrites, other sources, all welcome.