Advertisement
Open Source Projects by Phil Schwartz

Building a Python WHOIS bulk lookup utility

Working with hundreds of domain names at once is a common headache for developers, sysadmins, and even hobbyists running side projects from a home lab in Brisbane or a co-working space in Sydney. Whether you are auditing a portfolio of .com.au names before they lapse, screening candidates for a new startup, or chasing spam registrations sent from across the country, a quick bulk WHOIS lookup saves an enormous amount of copying and pasting between browser tabs. Python makes this kind of repetitive network work surprisingly approachable, and you do not need a heavyweight framework to get a clean script running. Learn more about Phil Schwartz.com.

The WHOIS protocol itself is older than most modern web standards, but it remains a reliable way to ask the regional registry who owns a domain, when it was registered, and which registrar currently holds it. For .au names, AusRegistry operates the authoritative database behind the scenes, while ACMA oversees the broader namespace. Building a small script that talks to these servers programmatically gives you far more control than any web form, especially when you want to chain the output into another tool or spreadsheet.

What WHOIS actually returns

WHOIS is a line-based text protocol that runs over TCP port 43. Your script opens a socket, sends a domain name followed by a carriage return and line feed, and reads back a free-form text record. The response is largely human-readable, with fields like Domain Name, Registrar, Registered On, Expiry Date, Name Server, and Status codes. Different registries format these fields slightly differently, so your parser has to tolerate a reasonable amount of variation.

A practical bulk script also needs to know that registrars run rate limits. If you hammer Verisign, Afilias, or the .au registry with thousands of lookups per minute from the same IP, you will quickly get blocked or handed back junk data. The solid approach is to throttle requests, back off on failure, and fall back to RDAP when WHOIS servers refuse to cooperate. RDAP returns structured JSON and is the modern replacement, but many older registries still expose only WHOIS, so a hybrid client covers more ground.

Setting up the script skeleton

Start with a recent Python 3 interpreter and keep dependencies minimal. The standard library ships socket, argparse, csv, json, and concurrent.futures, which is everything a small CLI tool actually needs. A simple requirements file pointing at the third-party python-whois package can speed development, but writing a minimal client by hand is a worthwhile exercise if you want to understand the wire protocol properly.

Create a new file, add an argparse block to accept an input file of domains plus optional flags for output format and worker count, and define a function for the lookup itself. Save the file as whois_bulk.py inside a project folder. Developers who already maintain a portfolio of small utilities, similar to the Python-based tools collected on phil-schwartz.com, often keep their network helpers in a shared module so they can be reused across scripts without duplicating socket boilerplate.

Crafting the actual lookup

The core function takes a single domain string, opens a socket with a sensible timeout, and writes the query to the registry's WHOIS server. For .com and .net names, whois.verisign-grs.com is the usual destination; for .au names, whois.audns.net.au or the relevant registrar endpoint does the job. Always include a timeout so a slow server cannot hang the whole batch, and wrap the socket read in a loop that decodes chunks until the connection closes.

import socket

def lookup(domain, server, port=43, timeout=10):
    with socket.create_connection((server, port), timeout=timeout) as sock:
        sock.sendall(f"{domain}\r\n".encode())
        data = b""
        while True:
            chunk = sock.recv(4096)
            if not chunk:
                break
            data += chunk
    return data.decode(errors="replace")

For a better-behaved tool, resolve the right WHOIS server using IANA's bootstrap data or a small dictionary of TLDs. Caching the resolved server per TLD avoids a DNS hop on every lookup, which matters when you are running a thousand domains through the pipeline during a quiet evening in Melbourne.

Running lookups in parallel

Running domains through one socket at a time is painfully slow. Python's concurrent.futures module gives you a ThreadPoolExecutor that can comfortably handle dozens of simultaneous WHOIS connections. With twenty workers and a one-second sleep between batches, a list of five hundred Australian domains typically clears in a few minutes on a typical NBN connection.

Watch out for two failure modes: socket timeouts and raw bytes that look like noise. Treat any exception as a transient failure, retry once after a short pause, and then record the domain as unresolved. Logging failures to a separate file lets you rerun the script later without reprocessing the clean records. If you are hosting the tool on a VPS in Sydney, keep an eye on egress and on each registry's published fair-use limits so you do not get your IP temporarily blacklisted.

Parsing and exporting the results

Once the raw text is in hand, write a small regex-based parser that pulls out registrar, creation date, expiry date, and status lines. Australian dates often follow DD/MM/YYYY formatting, so normalise to ISO 8601 when you store results. A lightweight dataclass per record keeps the rest of the script readable, and serialising to CSV with the csv module gives you a file you can pivot on in Excel or load into a SQLite database for further analysis.

For a tidier workflow, add a flag that writes JSON Lines instead of CSV, which plays well with command-line tools like jq. Both formats are easy to diff, version, and feed into other scripts. Wrapping the whole thing in a proper CLI with subcommands turns a one-off utility into something you will reach for whenever a new batch of names lands on your desk, whether you are operating from a home office in Perth, a startup hub in Adelaide, or anywhere else across Australia.