dnspython on main is 2.9.0dev0, and its build and tooling have drifted apart
a powerful DNS toolkit for python
At a glance
- What is it?
- dnspython is a pure Python DNS toolkit whose runtime needs nothing outside the standard library, but its main branch sits on a 2.9.0dev0 string, its newest tag is over a year old, and its Makefile, linters and documentation extras do not cover the same files.
- Who is it for?
- dnspython is a sound choice for a script that needs to speak the DNS protocol rather than resolve one name, and the zero required dependency list makes it easy to drop into a locked down environment. Pin a released version rather than the 2.9.0dev0 string on main, because the newest tag, v2.8.0, dates from 2025-09-07.
- Can I use it commercially?
- Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
- Is it still maintained?
- Yes. The repository last received commits 1 day ago.
- What is it written in?
- Mainly Python, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 5, 2026, and from our analysis. They are not legal advice.
Editorial analysis
Main carries 2.9.0dev0 while the newest tag is v2.8.0 from 2025-09-07
The version string in pyproject.toml is 2.9.0dev0, and the README opens its release notes section by calling itself the development version of dnspython 2.9.0, pointing readers at the What is New page for what changed. The tag history tells a slower story. v2.8.0 was published on 2025-09-07, v2.7.0 on 2024-10-05, and v2.6.1 on 2024-02-18, so the spacing between releases has been widening for two years. The last push to main is dated 2026-10-03, which means the code has moved well past the last published artifact while the release line has not. Anyone who installs from the repository rather than from a wheel therefore gets a version string that no PyPI index entry corresponds to, and that string can change without a tag ever appearing.
The license is ISC in three files and NOASSERTION in the metadata
The repository ships a LICENSE file at its top level, pyproject.toml declares license = ISC, the README badge points at the ISC text on opensource.org, and the Makefile header carries the standard ISC paragraph naming Nominum alongside the Dnspython Contributors. Against all of that, the license metadata attached to the repository itself reports no assertion at all. The manifest is internally consistent, so the disagreement is between the manifest and the metadata field, not between two licenses inside the tree. That matters for anything that reads license data from an API rather than from the source, including package catalogues and automated compliance checks, which will see nothing rather than ISC. Nothing in the tree suggests a second license or a scoping question about who the ISC text covers.
The default install needs nothing outside the standard library
dependencies = [] in the project table, and the README makes the same promise in prose: the default installation does not depend on any modules other than those in the Python standard library. Everything beyond that is an extra, and there are six of them, each mapping to one capability:
pip install dnspython[doh]
pip install dnspython[dnssec]
pip install dnspython[idna]DNS-over-HTTPS pulls httpcore2, httpx2, and h2. DNSSEC pulls cryptography at version 50 or later. IDNA pulls idna, Trio support pulls trio, DNS-over-QUIC pulls aioquic, and Windows WMI support pulls wmi. Combinations work by joining the names, so pip install dnspython[doh,dnssec,idna] is a documented single command. Worth noticing for anyone auditing a supply chain: the HTTPS stack is declared as httpx2 and httpcore2 rather than the httpx and httpcore names, and the DNSSEC path puts a compiled cryptography dependency behind a single extra.
The wmi extra installs nothing on anything but Windows
One of the six extras carries a platform marker. The wmi requirement is written as wmi>=1.5.1 with the marker platform_system=='Windows', and the README explains why the extra exists: on Windows you can use WMI to determine the active DNS settings instead of the default registry scanning method. That means the same command behaves differently depending on where it runs. On Linux or macOS, pip install dnspython[wmi] resolves to nothing, with no error and no warning that the feature was requested. If your build runs on one platform and your deployment on another, the resolver configuration that reads the active DNS server can silently fall back to the registry scanning path. The same gap applies to the extras themselves, since doh, doq, trio, and idna all vanish if the interpreter lacks the matching third party package and nothing in the import path complains until the code path runs.
Sphinx is gated to Python 3.12, so make doc has no tool to run on 3.10
requires-python is >=3.10 and the classifiers list Python 3.10 through 3.14, so the supported floor is lower than the tools the maintainers use. In the dev extra, sphinx is pinned at version 9.1.0 or later with the marker python_version >= '3.12', and sphinx-rtd-theme carries the matching python_full_version >= '3.12'. On Python 3.10 or 3.11, pip install dnspython[dev] completes without complaint and installs pytest, coverage, black, ruff, pyright, ty, hypercorn, quart-trio, and trustme, but no documentation builder at all. The Makefile's doc target runs make -C doc html, and the repository ships a .readthedocs.yml plus a doc/ directory, so the documentation exists and is published; it simply cannot be built from a dev install on the two oldest interpreters the project still claims to support. Pin the interpreter or add the documentation tools yourself.
Only doc is marked phony, so a stray file can shadow make test
The Makefile is short and mostly sensible. build runs python -m build. test runs pytest, and check depends on test. pyright runs pyright dns, ty runs ty check dns, type depends on both, ruff runs ruff check dns, and cov runs coverage with the branch flag followed by a coverage html and coverage report limited to dns/. clean removes htmlcov, .coverage, .pytest_cache, .ruff_cache, doc/_build, dist, and build. The wrinkle is the declaration list. Exactly one target is marked phony, the doc target, and the line sits directly above it. Every other target, build, clean, test, check, pyright, ty, type, ruff, cov, and black, is undeclared. In practice that means a file or directory named test, cov, or build in a working tree takes precedence over the recipe, and make test quietly succeeds without running pytest. Note also that check means tests only, not the type checkers or the linter, despite the reassuring name.
black formats examples and tests, but ruff and pyright only read dns
The lint and format targets do not cover the same ground, and the difference is worth knowing before a contribution bounces. The black recipe runs black dns examples tests, formatting the package, the twenty six example scripts, and the test suite. The ruff recipe runs ruff check dns, so static analysis covers the package only. The pyright recipe runs pyright dns, and the ty recipe runs ty check dns, so both type checkers also stop at the package boundary. Every example in the examples/ directory is therefore formatted but never linted and never type checked, which is the usual arrangement for sample code, but it does mean a stale example can sit in the tree without either tool objecting. The dev extra also installs two linters and two type checkers side by side, with ty pinned at 0.0.63 or later, a 0.0.x release, while pyright is required at 1.1.411 or later.
The repository steers simple forward lookups back to the standard library
The README opens with a scope warning that most project pages leave out. dnspython is a utility to work with DNS, so /etc/hosts is not consulted, and for simple forward lookups it is better to use socket.getaddrinfo() or socket.gethostbyname(). That is the project declining the most common use of a DNS library. The reason it was built at all is in the same file: it originated at Nominum, where it was developed to facilitate the testing of DNS software. The module name is dns rather than dnspython, which matters for anyone writing the import. High-level classes perform queries for a name, type, and class and return an answer set; low-level classes allow direct manipulation of zones, messages, names, and records. The examples directory holds twenty six scripts covering transfers, updates, DNSSEC, DoH, DoQ, and TSIG.
Editorial conclusion
dnspython is a sound choice for a script that needs to speak the DNS protocol rather than resolve one name, and the zero required dependency list makes it easy to drop into a locked down environment. Pin a released version rather than the 2.9.0dev0 string on main, because the newest tag, v2.8.0, dates from 2025-09-07. On Windows, expect `pip install dnspython[wmi]` to be the only route to the active settings, and on Linux expect it to install nothing. Before wiring the project into a build, check which Python you are on: the documentation toolchain only arrives on 3.12 and later, so `make doc` has nothing to run on 3.10 or 3.11.
Frequently asked questions
What is dnspython?
It is a DNS toolkit for Python that supports almost all record types, covering queries, zone transfers, and dynamic updates, with TSIG-authenticated messages and EDNS0. The import name is dns rather than dnspython, and the repository's own examples/ directory shows how it is used.
How do I use dnspython?
The high-level classes run queries for a given name, type, and class and return an answer set, while the low-level classes allow direct manipulation of zones, messages, names, and records. It does not read /etc/hosts, and for simple forward lookups the project points at socket.getaddrinfo() or socket.gethostbyname() instead.
How do I install dnspython?
From a wheel on PyPI the command is pip install dnspython, and the default install depends on nothing outside the Python standard library. Features come from extras such as pip install dnspython[doh], pip install dnspython[dnssec], or pip install dnspython[idna], and combinations like pip install dnspython[doh,dnssec,idna] work too.
How do I install dnspython on Linux?
The project says to check your distribution first, because many distributions package dnspython for you. From source it is pip install --upgrade pip build, then python -m build, then pip install dist/*.whl. For the main branch, pip install git+https://github.com/rthalley/dnspython.git. Note that the wmi extra installs nothing on Linux, because its requirement is marked platform_system=='Windows'.
What is the alternative to dnspython?
For simple forward DNS lookups the project points at the standard library instead, socket.getaddrinfo() or socket.gethostbyname(). No competing DNS library is named in the repository, and the stated reason for using dnspython at all is that it originated at Nominum to facilitate the testing of DNS software.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/rthalley-dnspython)