Skip to content

Instantly share code, notes, and snippets.

@ianrenton
Created March 16, 2025 07:10
Show Gist options
  • Save ianrenton/cc3bb8282e552d979b3cf06722c9ef5a to your computer and use it in GitHub Desktop.
Save ianrenton/cc3bb8282e552d979b3cf06722c9ef5a to your computer and use it in GitHub Desktop.
List all Parks on the Air (POTA) activators in the UK in 2024
from requests_cache import CachedSession
from datetime import timedelta
from time import sleep
# List of UK-adjacent programs
programs = ["GB", "IM", "GG", "JE", "GI", "FK"]
call_prefixes = ["G", "M", "2"]
year = 2024
# Setup
session = CachedSession("newparks_cache", expire_after=timedelta(days=1))
activators = set()
call_prefixes_tuple = tuple(call_prefixes)
parks = []
# For each program, fetch a list of parks
for program in programs:
parks_in_program = session.get("https://api.pota.app/program/parks/" + program).json()
print("Found " + str(len(parks_in_program)) + " parks in " + program)
parks.extend(parks_in_program)
# For each park, get the list of activations
i = 0
for park in parks:
if park["activations"] and park["activations"] > 0:
activations = session.get("https://api.pota.app/park/activations/" + park["reference"] + "?count=all").json()
for activation in activations:
# For each activation in the required year with the required callsign prefix, add to the set of activators
if activation["qso_date"].startswith(str(year)):
callsign = activation["activeCallsign"]
if callsign.startswith(call_prefixes_tuple):
activators.add(callsign)
sleep(1)
# Status report
percent_complete = int(round((i / len(parks)) * 100))
print(str(percent_complete) + "% complete. Found " + str(park["activations"]) + " activations of " + park["reference"] + ". " + str(len(activators)) + " unique activators so far.")
i += 1
# Print output
print("\nFound " + str(len(activators)) + " POTA activators in " + str(year) + " with callsign prefixes " + str(call_prefixes) + ":")
f = open("activators.txt", "w")
for callsign in sorted(activators):
f.write(callsign + "\n")
print(callsign)
f.close()
@ianrenton
Copy link
Author

Notes:

  • Written on request for a fellow OARC member. It can be adapted for other countries, programs and years by tweaking the values at the top
  • Includes a 1-second delay after every API call to avoid hammering the API. This means that as of March 2025 it takes ~2 hours to run.
  • Includes SES and club calls as well as personal calls
  • Does not do any special handling suffixes such as /P
  • Won't count anyone from the UK who activated only overseas parks, or anyone from abroad that activated UK parks
  • Will double count folks who have changed licence level during the year and activated using both calls

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment