dnspython
A pure-Python DNS toolkit for queries, zone transfers, dynamic updates, and DNSSEC validation, with both high-level and wire-format-level control.
Repository Health
Technical Analysis
dnspython is a comprehensive DNS toolkit for Python that supports nearly every DNS record type and both the high-level and low-level sides of DNS work. Its high-level classes (dns.resolver, dns.asyncresolver) let you query for records by name, type, and class and get back an answer set with a couple of lines of code, while its low-level classes (dns.message, dns.name, dns.rdata, dns.rrset) allow direct construction and manipulation of DNS messages, names, and zones for tools that need to speak the protocol precisely.
Beyond simple lookups, dnspython handles zone transfers (AXFR/IXFR), RFC 2136 dynamic updates, TSIG-authenticated messages, EDNS0, and DNSSEC validation and signing. Query execution supports synchronous UDP/TCP/TLS/HTTPS transports as well as async equivalents built on a pluggable backend abstraction, so the same code paths work under both asyncio and Trio. Originally developed at Nominum to test DNS software, it has become the de facto DNS library for the Python ecosystem, with zero required dependencies beyond the standard library and optional extras for DNSSEC, DNS-over-HTTPS, DNS-over-QUIC, IDNA, and Trio support.
What You Get
- A stub resolver (
dns.resolver,dns.asyncresolver) for high-level name/type/class queries with an OS-aware system configuration reader for/etc/resolv.confand Windows registry settings - Low-level message, name, and rdata classes (
dns.message,dns.name,dns.rdata,dns.rrset) for building and parsing DNS packets by hand, with round-trip text and wire format support - Zone file reading/writing and comparison (
dns.zone,dns.zonefile,dns.zonediff), plus a transaction abstraction (dns.transaction) for atomic zone mutation and a versioned zone implementation with history retention - Inbound AXFR/IXFR zone transfer support (
dns.xfr) and RFC 2136 dynamic update message construction (dns.update) - DNSSEC validation and signing (
dns.dnssec) covering RRSIG verification, DS digest computation, and NSEC/NSEC3 handling, with pluggable per-algorithm crypto backends - Multiple query transports out of the box — UDP, TCP, DNS-over-TLS, DNS-over-HTTPS, and DNS-over-QUIC — available in both sync and async (asyncio/Trio) form via a pluggable nameserver/backend abstraction
Common Use Cases
- Resolving hostnames, MX records, and other DNS record types from application or infrastructure code without shelling out to
dig/nslookup - Writing DNS monitoring, testing, or diagnostic tools that need precise control over query construction, EDNS options, and TSIG authentication
- Automating dynamic DNS updates or zone transfers for DDNS clients/servers and internal DNS tooling
- Validating or generating DNSSEC-signed responses, or building custom DNSSEC-aware resolvers and validators
- Building async DNS clients (asyncio or Trio) for services that need non-blocking name resolution alongside other network I/O
Under The Hood
Architecture
dnspython is organized as a consistent layered data model that nearly every non-trivial feature touches: dns.name.Name (immutable domain names) sits under dns.rdataclass/dns.rdatatype (extensible enum-like registries for RR classes and types), which sit under dns.rdata.Rdata (per-record-type classes dynamically imported by convention from dns/rdtypes/{CLASS}/{TYPE}.py, e.g. dns/rdtypes/IN/A.py, falling back to ANY or a generic implementation), which are grouped into dns.rdataset.Rdataset and bound to an owner name as dns.rrset.RRset, all assembled into a full dns.message.Message. Every layer supports both text (from_text/to_text, via dns.tokenizer) and wire (from_wire/to_wire, via dns.wire/dns.renderer) representations that must round-trip, and core objects are made hashable and shareable via an @dns.immutable.immutable class decorator built on dns.set.Set. Zone handling layers a dns.transaction.Transaction/TransactionManager unit-of-work abstraction (with a versioned zone implementation retaining history) over this same data model for both zone-file loading and inbound AXFR/IXFR transfers, and query execution is split across sync (dns.query) and async (dns.asyncquery) paths that share logic through a pluggable dns.asyncbackend abstraction supporting both asyncio and Trio.
Tech Stack
The library targets Python 3.10+ and ships with zero required runtime dependencies, relying only on the standard library for its core query/resolve/message paths. Optional functionality is gated behind extras rather than hard imports: cryptography for DNSSEC, httpcore2/httpx2/h2 for DNS-over-HTTPS, aioquic for DNS-over-QUIC, idna for internationalized domain names, trio for the Trio async backend, and wmi for Windows DNS configuration discovery — each checked at runtime via dns._features.have() rather than imported unconditionally. The project builds with uv’s uv_build backend, is typed and checked with both pyright and ty, linted with ruff, formatted with black, and documented with Sphinx from RST sources in doc/.
Code Quality
The test suite lives in tests/ as roughly 65 pytest/unittest.TestCase modules, run through pytest, with fixture data (sample zones, TLS certs, TSIG keys) packaged alongside the tests. The project’s own contributor guidance states it maintains around 94% coverage overall with many core modules at or near 100%, including branch coverage where practical, and CI (ci.yml) runs pyright, ruff check, and the full pytest suite across Python 3.10 through the next pre-release plus PyPy, on both Linux and Windows. Public modules raise dns.exception.DNSException subclasses rather than bare built-in exceptions, and the maintainers explicitly prioritize backwards compatibility, keeping breaking changes small and documented when unavoidable.
API Design
dnspython deliberately offers two tiers of API so callers only pay for the complexity they need: a couple of lines via dns.resolver.resolve() for a straightforward lookup, versus direct construction of dns.message.Message objects for tools that need exact control over EDNS, TSIG, or wire-level framing. Naming is consistent across the sync and async surfaces (dns.query/dns.asyncquery, dns.resolver/dns.asyncresolver), internal-only modules are clearly underscore-prefixed, and the doc/ manual plus a dedicated examples/ directory of ~17 runnable scripts (async queries, DDNS client/server, DoH/DoT/DoQ, zone transfers, reverse lookups) give a working reference for nearly every feature area, keeping the ramp from “first query” to “custom wire-level tooling” gradual rather than a cliff.
Used by 12 apps in this directory
rowboat
AI Assistants · AI Development
Build, test, and deploy multi-agent AI workflows with a visual editor, RAG data sources, MCP tool integration, and a production-ready REST API.
SWIRL
Data Engineering · Databases · Search
Federated AI search and RAG across 100+ enterprise sources—no data extraction, no vector database required.
Tracecat
AI Agents · Automation · Security
Open-source agentic security automation platform that runs AI agents and durable workflows at scale with sandboxed execution.