Python: how to make a WHOIS request

In this article we will see how to make a WHOIS request with Python.

A WHOIS request is made by querying a remote server by socketing on port 43 and sending the domain name as a byte stream followed by a carriage return.

We need a WHOIS server list in JSON or CSV format that contains the hostname of the server and the domain extension it manages.

To extract the domain extension from the FQDN we can install the module tldextract which also handles double extensions (like .co.uk). Our JSON file containing the list of WHOIS servers will have the following structure for each entry:

{
    "extension": ".it",
    "server": "whois.nic.it",
    "response": "AVAILABLE"
}

We define a first function to read the contents of this file as a list of dictionaries.

import socket
import json
import tldextract


def get_whois_server_list(list_path='./servers.json'):
    with open(list_path, 'r') as f:
        return json.load(f)

Now we have to find in this list of dictionaries the element whose key extension corresponds to the extension that we will have to extract from the domain name. To search efficiently, we will use the filter() function on the list.

def find_whois_server_for_domain(domain_name=None):
    if domain_name is None:
        return None
    full_domain_url = f'https://{domain_name}'
    domain_extension = tldextract.extract(full_domain_url)
    full_extension = f'.{domain_extension.suffix}'
    whois_server_list = get_whois_server_list()
    whois_server_found = list(
        filter(lambda server: server['extension'] == full_extension, whois_server_list))
    whois_server = whois_server_found[0] if len(
        whois_server_found) > 0 else None
    return whois_server

Finally, we need to connect via socket to the server that manages the extension of the selected domain and return the response as output. This response will have to be constructed by reading from the returned data stream as the remote server sends it.

def whois_lookup(domain_name=None):
    if domain_name is None:
        return None
    whois_server = find_whois_server_for_domain(domain_name)
    if whois_server is None:
        return None
    query = f'{domain_name}\r\n'
    server = whois_server['server']
    connection = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    connection.connect((server, 43))
    connection.send(query.encode())
    response = ''

    while len(response) < 10000:
        chunk = connection.recv(100).decode()
        if (chunk == ''):
            break
        response = response + chunk
    return response

The response comes as a byte stream, so we need to convert it to a string if we want to represent it legibly on the shell. Usage example:

def main():
    domain = input('Enter domain name:')
    print(whois_lookup(domain))


if __name__ == '__main__':
    main()
Back to top