
Table of Contents
The DNSAudit web app answers one question well. How is this domain doing right now. You type a name, read the grade, fix what is red. That is the right tool when you care about a single domain.
Security teams do not have a single domain problem. They have an estate, and it drifts. That is the gap this SDK is for.
The problem is scale, and time
Most teams we talk to are not tracking one name. They have the main brand, a pile of regional TLDs, campaign microsites, a few acquisitions that were never fully absorbed, and a long tail of dev and staging subdomains nobody remembers standing up. Nobody audits four hundred names by hand, so in practice most of them never get looked at until something breaks.
And DNS posture is not static. It rots quietly. A marketing vendor gets added to your SPF record and tips you past the ten lookup limit, so SPF starts returning permerror and receivers stop trusting your mail. A DKIM selector gets rotated and the old record is left dangling. DMARC sits at p=none for a year because moving it to quarantine was on someone's list and then it was not. A DNSSEC key rollover goes wrong at the parent and validating resolvers start handing back SERVFAIL.
None of these throw a loud error. Mail mostly still flows. The site mostly still loads. You find out when someone spoofs your domain or a customer opens a ticket. A once a quarter manual review will not catch the change that happened in week three.
That is the actual job. Not scanning one domain, but watching many of them, continuously, and noticing when one of them slips.
Where the SDK earns its place
The audit rolls all of that, email authentication, DNSSEC state, NS and MX integrity, CAA, into a grade and a score, plus a list of issues. On its own, in a browser tab, that is a number a person has to go look at. In a script, it is a signal you can route.
That is the whole point of the SDK. It turns a scan from something you visit into something that runs on its own and reports into the systems your team already lives in. A few things that becomes easy once audits are callable from Python:
- Sweep the entire estate on a schedule instead of checking domains one at a time, and wake up to a list of what changed.
- Catch regressions between reviews. Pull the last recorded grade for a domain from history, compare it to a fresh scan, and only raise something when the grade actually drops.
- Gate changes. Before a new domain or subdomain goes live, scan it in CI and fail the build if it comes back below your bar.
- Feed your own tooling. The scan comes back as a plain Python dict, so from there you send it to your ticketing, your on call channel, or your SIEM. You write that glue, which means it fits your process instead of ours.
That last part matters. This is a building block, not a closed integration. You decide what a failing grade should do inside your environment.
A real example: a nightly estate sweep
Here is the shape of it. Scan a list of domains concurrently, keep only the ones that came back below an acceptable grade, and hand that worklist off to whatever you use for follow up.
import asyncio
from dnsaudit import AsyncClient
# Grades we are willing to accept. Everything else goes on the worklist.
PASSING = {"A+", "A", "B+", "B"}
async def sweep(domains):
async with AsyncClient() as client:
results = await asyncio.gather(
*(client.scan(d, no_cache=True) for d in domains)
)
return [r for r in results if r["grade"]["grade"] not in PASSING]
estate = ["example.com", "mail.example.com", "shop.example.com"]
worklist = asyncio.run(sweep(estate))
for r in worklist:
print(f"{r['domain']} came back {r['grade']['grade']}")
# r is a plain dict. Send it to your ticketing, channel, or SIEM from here.no_cache=True forces a fresh scan rather than the cached result, which is what you want on a scheduled run. The async client lets you fire the whole list at once instead of walking it domain by domain. That is the difference between a sweep that finishes in seconds and one you leave running.
What you actually get
The parts that matter for putting this into production, without repeating the full method reference, which is on GitHub and PyPI:
Both a synchronous Client and an asynchronous AsyncClient, so it drops into a script or into a FastAPI service the same way. Scans come back as raw dictionaries, so nothing is hidden behind wrapper objects and you can reach any field the API returns. You can export PDF or JSON reports straight to disk if you generate evidence for clients or audits. Burst rate limits are handled for you, the SDK reads the API's Retry-After header and pauses the right amount before retrying, so a large sweep does not need its own backoff logic.
It needs Python 3.8 or newer and one dependency, httpx.
Getting set up
Install it:
pip install dnsauditSet your key as an environment variable and the client picks it up on its own:
export DNSAUDIT_API_KEY="your-api-key"API access is enabled per account rather than bundled automatically into a plan. If your account does not have it yet, contact us to request it. Once enabled, generate a key from the API section of your dashboard. From there, the fastest way in is the examples/ directory in the repo. Start with examples/basic_scan.py and build up to a sweep like the one above.
Package: https://pypi.org/project/dnsaudit/
Source and examples: https://github.com/dnsauditio/dnsaudit-python-sdk

I'm Vikas, a security researcher focused on application security and attack surface management. I've spent my career working in cybersecurity, specializing in vulnerability research, automation, and threat detection. At DNSAudit, I help build new detection signatures and perform threat research to uncover exposure before it becomes a problem.
