Skip to main content

Security Toolbox

Zone Transfer

Test whether a domain's nameservers allow DNS zone transfer (AXFR), and show the zone contents when they do.

Warning: Authorised use only. This tool contacts nameservers and can expose a full zone. Use it only on systems you are allowed to test.

Install

Requires Python 3.10+. Runtime dependencies (dnspython, prettytable, and colored) install with the package.

pip install lupaxa-zone-transfer
zone-transfer --help

You can also run python -m lupaxa.zone_transfer.

CLI

zone-transfer example.com
zone-transfer example.com example.org
zone-transfer example.com --nameserver ns1.example.net --nameserver 203.0.113.10
zone-transfer example.com --format json
zone-transfer example.com --fail-open
zone-transfer example.com --timeout 10 --no-color
python -m lupaxa.zone_transfer --version

Each domain is inspected independently. The tool discovers NS records (or uses --nameserver for every domain and skips discovery), sorts hosts by name with IPv4 before IPv6, and tries AXFR on every address. On a TTY a spinner on stderr shows the current lookup or transfer. --fail-open exits 2 if any server allowed AXFR.

Flag Default Description
--nameserver, -n discover NS Nameserver host or IP (repeatable)
--format, -f table Output format: table or json
--fail-open off Exit 2 if any endpoint allowed AXFR
--timeout 10 DNS and AXFR timeout in seconds (must be > 0)
--no-color off Disable colour in table output
--version — Print the package version and exit

Table output is titled with the domain. Rows are nameserver, address, family, status, and reason. For each allowed attempt a second table lists name, type, TTL, and rdata. On a colour terminal, allowed is red, refused is green, and error is grey. Pass --no-color or set NO_COLOR for plain text.

JSON is a list of {domain, error, attempts} objects. Each attempt has nameserver, address, family, status, reason, and records. Record objects use type (not rtype). error is a string, never null. records is always a list.

[
  {
    "domain": "example.com",
    "error": "",
    "attempts": [
      {
        "nameserver": "ns1.example.net",
        "address": "203.0.113.10",
        "family": "IPv4",
        "status": "allowed",
        "reason": "",
        "records": [
          {"name": "@", "type": "SOA", "ttl": 3600, "rdata": "ns1.example.net. hostmaster. 1 1 1 1 1"}
        ]
      }
    ]
  }
]

Attempt Status

Status Meaning
allowed AXFR succeeded; records holds the zone
refused Server answered not permitted (REFUSED / FORMERR)
error Timeout, connect failure, or no addresses

Exit Codes

Code When
0 Every domain was tested; refused and per-endpoint errors are OK
2 Invalid input, NS discovery failure, or --fail-open + allowed

A domain-level NS discovery failure sets error and exits 2. A refused transfer is a normal result and exits 0 unless --fail-open saw an allowed attempt.

Library

from lupaxa.zone_transfer import inspect_domain, inspect_many

report = inspect_domain("example.com")
pinned = inspect_domain("example.com", nameservers=["203.0.113.10"])
reports = inspect_many(["example.com", "example.org"], timeout=10.0)

for attempt in report.attempts:
    print(attempt.endpoint.address, attempt.status)
    for record in attempt.records:
        print(record.name, record.rtype, record.rdata)

inspect_domain does not raise when AXFR is refused or one address fails. Those become attempt rows. Empty domains, an empty nameserver list, or an empty inspect_many list raise InvalidTargetError. NameserverLookupError is raised by lookup_nameservers; inspect_domain catches it into DomainReport.error. ZoneTransferError is the base class.

Pass on_progress to receive Progress events (domain, phase, message, current, total). Phases are lookup (NS discovery), resolve (A/AAAA expansion), and try (one AXFR). The library does not print; the CLI uses that hook for the spinner.

Development

make init
make python-install-dev
make python-check
The Lupaxa Project Footer

Metadata

Release files for lupaxa-zone-transfer 0.1.4

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for lupaxa-zone-transfer 0.1.4
File Size Uploaded
lupaxa_zone_transfer-0.1.4.tar.gz 11.4 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for lupaxa-zone-transfer 0.1.4
File Interpreter ABI Platform
lupaxa_zone_transfer-0.1.4-py3-none-any.whl Python 3 none any Details

Total release size: 26.9 kB

Release files / lupaxa_zone_transfer-0.1.4.tar.gz

Download URL lupaxa_zone_transfer-0.1.4.tar.gz
Size 11.4 kB
Tags Source
SHA-256 checksum
How to use checksums
545275ee10622d741dc38c6aa5eb891a1fe870c1c8d65d85361a9d7240d12163
BLAKE2b-256 checksum
How to use checksums
ac5afe5cb0cf1138e1424cc1ae99bf02f4c02191079f236e4309eea1e1eccfbe
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 30, 2026.

Transparency log

Release files / lupaxa_zone_transfer-0.1.4-py3-none-any.whl

Download URL lupaxa_zone_transfer-0.1.4-py3-none-any.whl
Size 15.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
06777fec6bda46d83595e796880a76c7a3765419088e81a2aa1c5d5a634b7013
BLAKE2b-256 checksum
How to use checksums
b49f67a08b1926995a14746f8184ed5462a1c4f95a83e6af18c8c91a6190d537
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 30, 2026.

Transparency log

Release history Release notifications | RSS feed

0.1.5

2 release files

This release

0.1.4 This release

2 release files

0.1.3

2 release files

0.1.2

2 release files

0.1.1

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page