Last active
March 22, 2025 11:38
-
-
Save st1vms/52f3a974c7a60c06ea0b4a726974dd04 to your computer and use it in GitHub Desktop.
Python script to rate ProtonVPN FreeTier domains by load factor.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
"""Auto retrieve ProtonVPN free-tiers load ratings""" | |
from requests import get as http_get | |
# Taken from https://account.protonvpn.com/downloads | |
# Open dev-tools and look for GET requests to /api/vpn/logicals endpoint | |
# Copy the entire cookie header value into this string | |
__COOKIE_STRING = "" | |
# Also copy the x-pm-uid header value from that same GET request into this string | |
__X_PM_UID_STRING = "" | |
# Also copy your browser User Agent into this string | |
__USER_AGENT = "" | |
def __get_json_stats() -> dict | None: | |
url = "https://account.protonvpn.com/api/vpn/logicals" | |
headers = { | |
"Host": "account.protonvpn.com", | |
"User-Agent": __USER_AGENT, | |
"Accept": "application/vnd.protonmail.v1+json", | |
"Accept-Language": "en-US,en;q=0.5", | |
"Accept-Encoding": "gzip, deflate, br", | |
"Referer": "https://account.protonvpn.com/downloads", | |
"x-pm-appversion": "[email protected]", | |
"DNT": "1", | |
"Connection": "keep-alive", | |
"x-pm-uid": __X_PM_UID_STRING, | |
"Cookie": __COOKIE_STRING, | |
"Sec-Fetch-Dest": "empty", | |
"Sec-Fetch-Mode": "cors", | |
"Sec-Fetch-Site": "same-origin", | |
"TE": "trailers", | |
} | |
res = http_get(url, headers=headers, timeout=5) | |
if res.status_code == 200: | |
return res.json() | |
return None | |
def get_free_tier_ratings() -> list[tuple[str, float]] | None: | |
"""Retrieves list of tuples, containing ordered domain names with their load number""" | |
stats = __get_json_stats() | |
if not stats or not "LogicalServers" in stats: | |
print("Error retrieving stats...") | |
return None | |
tiers = __free_tiers() | |
ret = [] | |
for entry in stats["LogicalServers"]: | |
if not "Domain" in entry or not "Load" in entry: | |
continue | |
domain: str = entry["Domain"] | |
load = entry["Load"] | |
if domain.split(".")[0] in tiers: | |
ret.append((domain, load)) | |
return sorted(ret, key=lambda x: x[1]) | |
def __main() -> None: | |
"""Main""" | |
i = 0 | |
while not i: | |
try: | |
i = int(input("\nHow many results you want to get?\n>>").strip()) | |
if i <= 0: | |
i = 0 | |
print("\nMust be a positive value!") | |
continue | |
except ValueError: | |
i = 0 | |
continue | |
ratings = get_free_tier_ratings() | |
for rate in ratings[:i]: | |
print(f"{rate[0]} -> {rate[1]}%") | |
def __free_tiers() -> set: | |
"""Embedded ProtonVPN free tiers domain names.""" | |
return { | |
"node-jp-26", | |
"node-nl-141", | |
"node-nl-93", | |
"node-nl-182", | |
"node-us-198", | |
"node-nl-161", | |
"node-us-91", | |
"node-us-61", | |
"node-nl-139", | |
"node-us-145", | |
"node-nl-172", | |
"node-us-175", | |
"node-us-162", | |
"node-nl-185", | |
"node-nl-06", | |
"node-nl-113", | |
"node-nl-83", | |
"node-ro-07", | |
"node-nl-02", | |
"node-nl-191", | |
"node-nl-132", | |
"node-nl-187", | |
"node-nl-162", | |
"node-nl-81", | |
"node-jp-28", | |
"node-nl-134", | |
"node-us-128", | |
"node-nl-199", | |
"node-nl-124", | |
"node-nl-123", | |
"node-nl-163", | |
"node-nl-189", | |
"node-nl-98", | |
"node-us-151", | |
"node-nl-110", | |
"node-nl-128", | |
"node-jp-13", | |
"node-nl-203", | |
"node-nl-97", | |
"node-us-159", | |
"node-us-141", | |
"node-us-72", | |
"node-nl-180", | |
"node-us-155", | |
"node-nl-158", | |
"node-nl-200", | |
"node-nl-156", | |
"node-us-191", | |
"node-jp-19", | |
"node-nl-72", | |
"node-jp-24", | |
"node-nl-196", | |
"node-us-147", | |
"node-nl-149", | |
"node-nl-140", | |
"node-pl-12", | |
"node-nl-71", | |
"node-nl-148", | |
"node-nl-05", | |
"node-us-137", | |
"node-ro-04", | |
"node-nl-94", | |
"node-nl-95", | |
"node-jp-15", | |
"node-nl-130", | |
"node-nl-178", | |
"node-jp-18", | |
"node-nl-68", | |
"node-nl-105", | |
"node-jp-16", | |
"node-ro-03", | |
"node-nl-74", | |
"node-us-54", | |
"node-nl-57", | |
"node-us-146", | |
"node-nl-76", | |
"node-us-184", | |
"node-ro-06", | |
"node-nl-159", | |
"node-nl-181", | |
"node-nl-193", | |
"node-nl-111", | |
"node-jp-27", | |
"node-nl-129", | |
"node-us-154", | |
"node-nl-117", | |
"node-nl-150", | |
"node-nl-109", | |
"node-nl-108", | |
"node-nl-142", | |
"node-nl-133", | |
"node-us-136", | |
"node-us-193", | |
"node-nl-170", | |
"node-us-148", | |
"node-nl-173", | |
"node-nl-92", | |
"node-jp-22", | |
"node-us-70", | |
"node-nl-79", | |
"node-nl-186", | |
"node-us-163", | |
"node-nl-101", | |
"node-us-73", | |
"node-us-131", | |
"node-us-55", | |
"node-nl-197", | |
"node-nl-96", | |
"node-us-133", | |
"node-nl-126", | |
"node-jp-21", | |
"node-us-47", | |
"node-nl-184", | |
"node-us-62", | |
"node-nl-152", | |
"node-nl-147", | |
"node-nl-188", | |
"node-us-45", | |
"node-us-156", | |
"node-nl-106", | |
"node-us-196", | |
"node-us-76", | |
"node-us-60", | |
"node-us-71", | |
"node-nl-70", | |
"node-nl-179", | |
"node-us-152", | |
"node-nl-201", | |
"node-nl-102", | |
"node-nl-127", | |
"node-us-149", | |
"node-jp-25", | |
"node-nl-164", | |
"node-nl-198", | |
"node-nl-175", | |
"node-us-142", | |
"node-nl-137", | |
"node-us-170", | |
"node-nl-69", | |
"node-us-132", | |
"node-nl-114", | |
"node-us-180", | |
"node-us-150", | |
"node-nl-90", | |
"node-nl-125", | |
"node-ro-05", | |
"node-nl-154", | |
"node-jp-20", | |
"node-nl-75", | |
"node-us-56", | |
"node-pl-13", | |
"node-nl-77", | |
"node-nl-115", | |
"node-nl-82", | |
"node-nl-169", | |
"node-nl-195", | |
"node-nl-176", | |
"node-pl-11", | |
"node-nl-78", | |
"node-nl-177", | |
"node-nl-116", | |
"node-nl-91", | |
"node-nl-103", | |
"node-us-78", | |
"node-pl-10", | |
"node-nl-153", | |
"node-nl-138", | |
"node-us-81", | |
"node-nl-118", | |
"node-nl-183", | |
"node-us-138", | |
"node-us-140", | |
"node-jp-23", | |
"node-us-139", | |
"node-jp-11", | |
"node-nl-190", | |
"node-nl-160", | |
"node-nl-04", | |
"node-us-153", | |
"node-nl-155", | |
"node-nl-104", | |
"node-nl-157", | |
"node-nl-171", | |
"node-pl-09", | |
"node-us-157", | |
"node-nl-73", | |
"node-nl-192", | |
"node-nl-03", | |
"node-nl-131", | |
} | |
if __name__ == "__main__": | |
__main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment