KH6LF

Electronics and Radio

How to access the HamDB callsign database with Python.

The ability to programmatically retrieve an amateur radio operator's information by callsign is incredibly powerful. Imagine a utility that automatically creates QSL card printouts personalized with the recipients name, address, and country. Or perhaps a homebrew logging software that dynamically fills out the operator's grid square and coordinates? Using a programming language like Python and the HamDB callsign database, such things are possible.

First things first, what is a database and why do we need to know this? A database is a organized collection of data, similar to a an Excel spreadsheet. It is optimized for large scale data retrieval and manipulation. Sites like Amazon use databases to store customer information and account data. Similarly, hamdb.org maintains a database of amateur radio operator information, which we can use in our own projects. To access this data, we can use a predefined method of transfering data over the internet, known as a REST API. The API can be accessed using a programming language such as JavaScript or Python, which allows it to be integrated with other functionality that your script may provide. Data is accessed via an endpoint, which is a location on the API that can respond to requests from it. This means that by sending a request to a specific URL (the endpoint), we can get the information we want. The HamDB API has just one endpoint:

http://api.hamdb.org/

The operators callsign is appended to the end of this URL, along with the format, and appname. The format parameter can be either XML, JSON, HTML, or CSV. I am partial to JSON data, so that is the format which I will be using in this article. The appname parameter is a string that should be unique to your application. From my tests, I have found that any arbitrary string can be used as the appname without negatively impacting the functionality of the API. Thus, the formatted endpoint is:

http://api.hamdb.org/callsign/json/appname

Where "callsign" is the callsign which you would like to query data for, and "appname" can be whatever you want.

After formatting the URL, the next step is to send a request to this web address. For testing purposes, you can just use a browser. Open up a new tab, type in the endpoint, followed by the callsign, format, and appname, then press enter. Your browser will send an HTTP request to the API, and display the returned data.

Request:

https://api.hamdb.org/kh6lf/json/appname

Response:

{
    hamdb: {
        version: "1",
        callsign: {
            call: "KH6LF",
            class: "E",
            expires: "01/19/2031",
            status: "A",
            grid: "BK29mo",
            lat: "19.6100788",
            lon: "-154.9574091",
            fname: "Levi",
            mi: "N",
            name: "Farinas",
            suffix: "",
            addr1: "15-1590 1st Avenue",
            addr2: "Keaau",
            state: "HI",
            zip: "96749",
            country: "United States"
        },
        messages: {
            status: "OK"
        }
    }
}

Now that we've confirmed the API works in a browser, we can create a simple Python function to access the API with code:

import requests

def get_info(callsign):
    url = f"https://api.hamdb.org/{callsign}/json/sample_application"
    data = requests.get(url).json()
    return data["hamdb"]["callsign"]

The program begins by importing the requests module, which will make the HTTP GET request to the API. Then, inside the "get_info" function, the URL string is formatted with the callsign. The next line sends the HTTP GET request and stores the response as a Python dictionary object in the "data" variable. The final line returns the data nested inside the "hamdb" and "callsign" fields, which is the information which is actually useful to us. To use this function, simply call the function with a valid callsign as the parameter:

kh6lf = get_info("kh6lf")
print(kh6lf["fname"]) # Will print the first name of the operator

But what if the callsign is not valid? In this case, the API will return "NOT_FOUND" in most of the fields. The code can be updated to account for this:

def get_info(callsign):
    url = f"https://api.hamdb.org/{callsign}/json/sample_application"
    data = requests.get(url).json()
    if data["hamdb"]["callsign"]["call"] == "NOT_FOUND":
        raise ValueError
    else:
        return data["hamdb"]["callsign"]

If callsign that is not in the database is requested, the function will raise a ValueError. Alternatively, it could be modified to do anything else, such as print a warning message to the console or return 0.

Response Fields

The function presented above will return a Python dictionary object, which has fields for various information (see the example response shown earlier). To access useful information from it, you can use the following format:

api_response["data_field"]

Some examples are listed below:

kh6lf = get_info("kh6lf")
print(kh6lf["fname"]) # Will print the first name of the operator
print(kh6lf["name"]) # Will print the last name of the operator
print(kh6lf["fname"]) # Will print the first name of the operator
print(kh6lf["grid"]) # Will print the grid square of the operator
print(kh6lf["addr1"]) # Will print the first part of the operator's address
print(kh6lf["zip"]) # Will print the operator's zip code

Applications of this API

This API presents a unique set of capabilities for the amateur radio hobbyist. One potential use for it is in a tool to automatically create a printable PDF QSL card prefilled with the recipients name, grid square, or even a greeting in their country's official language! Another useful application of this API is in homebrew logging software. I am quite interested in the possibilities of this API, and will be sure to revisit it in a future blog article. If you have any ideas for uses of this API, please send me an email. Thank you for reading!