python-nmap: Run Network Scans Safely from Python

Quick answer: python-nmap is a wrapper around the Nmap executable, not a replacement for it. Use it only for authorized inventory or testing, verify the executable and target scope, apply timeouts, inspect exit status and stderr, and treat partial scan output as incomplete evidence.

Python Pool infographic showing python-nmap wrapper Nmap executable authorized target structured results and timeout
python-nmap orchestrates Nmap from Python; authorization, target scope, timeouts, and result validation remain application responsibilities.

python-nmap is a Python wrapper around the Nmap command-line scanner. It lets a Python script start an Nmap scan, read host and port results, and turn those results into reports or checks.

Use it only on systems you own, administer, or have explicit written permission to test. Port scanning can trigger security alerts, abuse reports, or legal issues when it targets third-party networks. The examples below use localhost, private lab ranges, and sample data for that reason.

The main references are the python-nmap PyPI page, the python-nmap usage documentation, the official Nmap reference guide, the Nmap download page, and Nmap’s page on legal issues.

Install the Nmap program first, then install the Python wrapper with python -m pip install python-nmap. The wrapper depends on the external nmap executable, so installing only the Python package is not enough.

The basic workflow is to create nmap.PortScanner(), call scan() with authorized hosts and ports, then inspect host dictionaries for state, protocols, ports, service names, and product details.

Decide the scan scope before writing code. A scope should include the host or network range, port list, scan arguments, owner approval, and the time when the scan may run. Put those choices near the top of the script so a reviewer can see what the program will touch.

Keep scans small while testing. A narrow localhost scan is easier to understand than a broad network scan, and it avoids surprising other systems. Save larger scans for approved maintenance windows.

Also record the exact command line that Nmap runs. scanner.command_line() helps you audit flags, repeat a scan manually, or include scan details in a report.

Prefer simple scan arguments until you know why you need more. Service detection can be useful, but it sends additional probes. Aggressive or intrusive options should be reserved for lab systems or clearly approved assessment work.

For repeatable maintenance checks, store the parsed result, the command line, the scan time, and the approved scope together. That makes it easier to compare changes later and prove what the script was allowed to do.

Check python-nmap Setup

Before writing scan logic, confirm that the Nmap executable and the Python package are both available.

from shutil import which

print("nmap installed:", which("nmap") is not None)

try:
    import nmap
    print("python-nmap installed")
except ModuleNotFoundError:
    print("install python-nmap")

If the first line prints False, install Nmap from the official project or your operating system package manager. If the import fails, install the Python wrapper in the same environment that runs your script.

Setup errors are common on new machines because the wrapper imports successfully but cannot find the nmap executable. Test both layers before debugging scan output.

Define A Localhost Scan

This function shows the core PortScanner pattern without running the scan during import.

def scan_localhost_ports():
    import nmap

    scanner = nmap.PortScanner()
    scanner.scan(
        hosts="127.0.0.1",
        ports="22,80,443",
        arguments="-sV",
    )
    return scanner.command_line()

print("scan function ready")

Call this only on a machine where scanning localhost is permitted. The -sV argument asks Nmap to probe service versions, which can take longer than a simple port-state check.

For a first run, use a short port list and a single host. After the script behaves correctly, widen the scope only if the authorization and operational plan allow it.

Python Pool infographic showing an authorized target, nmap scanner, ports, and results
Only scan systems and ranges for which you have explicit authorization.

Read Open Ports From Results

Scan results are nested dictionaries. This sample uses the same shape you inspect after a real scan.

scan = {
    "scan": {
        "127.0.0.1": {
            "status": {"state": "up"},
            "tcp": {
                22: {"state": "open", "name": "ssh"},
                80: {"state": "closed", "name": "http"},
                443: {"state": "open", "name": "https"},
            },
        }
    }
}

host = scan["scan"]["127.0.0.1"]
open_ports = [
    port
    for port, data in host.get("tcp", {}).items()
    if data.get("state") == "open"
]

print(open_ports)

The code reads the TCP section and keeps ports whose state is open. Use get() so the parser does not fail when a protocol section is absent.

Not every scan produces every section. Some hosts may be down, filtered, or missing the protocol key you expected, so robust parsing is important for automated reports.

Build Report Rows

For reports, flatten host and port data into rows.

scan = {
    "scan": {
        "127.0.0.1": {
            "tcp": {
                22: {"state": "open", "name": "ssh", "product": "OpenSSH"},
                443: {"state": "open", "name": "https", "product": "nginx"},
            }
        }
    }
}

rows = []
for host, details in scan["scan"].items():
    for port, service in details.get("tcp", {}).items():
        rows.append({
            "host": host,
            "port": port,
            "state": service.get("state", ""),
            "service": service.get("name", ""),
            "product": service.get("product", ""),
        })

print(rows[0])

This structure is easy to write as CSV, JSON, or a database row. Keep the raw scan result too when auditability matters.

Flat rows are useful for dashboards and diffs. The raw nested result is useful when you later need extra fields such as service version, reason, script output, or hostnames.

Python Pool infographic mapping Python code through python-nmap to the nmap executable
python-nmap is a wrapper around an installed nmap executable and its output.

Limit Targets To Approved Ranges

A small target check can prevent accidental scans of public addresses.

from ipaddress import ip_network

def allowed_lab_target(value):
    network = ip_network(value, strict=False)
    return network.is_loopback or network.is_private

print(allowed_lab_target("127.0.0.1"))
print(allowed_lab_target("192.168.1.0/24"))
print(allowed_lab_target("8.8.8.8"))

This helper allows loopback and private address space. It is not a replacement for authorization, but it catches obvious mistakes before a script launches a scan.

Production tools should still require an approved scope file, command-line confirmation, or deployment control. A helper like this is only a guardrail, not permission.

Handle Scan Errors

Wrap real scans so setup failures and Nmap errors produce useful messages.

def scan_with_error_handling(hosts, ports):
    import nmap

    scanner = nmap.PortScanner()
    try:
        return scanner.scan(hosts=hosts, ports=ports, arguments="-sV")
    except nmap.PortScannerError as error:
        return {"error": str(error)}

print("error-handled scan function ready")

Common causes include the Nmap executable not being installed, insufficient permissions for a chosen scan type, blocked network traffic, or a target string outside the approved scope.

Log failures with enough detail to reproduce the issue, but avoid dumping sensitive network inventories into public logs. Keep reports in a location that matches the sensitivity of the systems being scanned.

In short, use python-nmap as a controlled wrapper around Nmap: install both layers, scan only authorized targets, keep command lines auditable, parse result dictionaries carefully, and handle setup errors clearly.

Separate The Wrapper From Nmap

The Python package coordinates a command-line scanner that must be installed and available to the running process. Check the executable path, version, permissions, and the interpreter environment before debugging result parsing. A package import can succeed even when the Nmap binary is missing.

Python Pool infographic comparing scan output, hosts, ports, states, and structured data
Parse results with clear handling for hosts, ports, states, and missing data.

Define An Authorized Scope

Write down the hosts, ports, timing limits, and purpose before starting a scan. Do not scan public systems or networks without explicit permission. In a production inventory tool, constrain targets at the application boundary and log who requested the scan and why.

Validate Structured Results

A returned dictionary or parsed object is not automatically complete or correct. Check the command status, stderr, host state, protocol, port state, and scan arguments. Keep raw output for a controlled diagnostic path when a parser or Nmap version changes.

Python Pool infographic testing authorization, rate, timeouts, logging, and validation
Check authorization, scope, rate, timeouts, logging, and responsible handling of scan data.

Use Timeouts And Resource Limits

Network scans can be slow or produce large output. Set a timeout, limit concurrency, avoid unbounded target lists, and handle process termination deliberately. A timed-out scan should be reported as timed out rather than converted into an empty successful result.

Test With Fixtures

Unit tests should parse deterministic sample output and cover open, closed, filtered, unreachable, malformed, and partial cases. Integration tests belong in an isolated lab or test network with permission, not against arbitrary Internet hosts.

The Nmap reference guide documents scan behavior and options. The python-nmap project describes the wrapper interface. Related guidance includes Python test isolation and operational logging.

For related process control, compare running commands, subprocess termination, and operational logging when wrapping an external scanner.

Frequently Asked Questions

What is python-nmap?

python-nmap is a Python wrapper that helps call the Nmap network scanner and inspect its results from Python code.

Does python-nmap install Nmap itself?

Usually no. Install the Nmap executable separately, verify its path and version, and then configure the wrapper to use it.

Can I scan any public IP address?

No. Scan only systems you own or have explicit permission to test, and follow the target network’s rules and rate limits.

How should I handle scan failures?

Validate targets, capture stderr and exit status, apply timeouts, and treat partial results as incomplete rather than as proof that a port is closed.

Subscribe
Notify of
guest
11 Comments
Oldest
Newest Most Voted
Prince
Prince
4 years ago

It threw key error when I change ip addr

Python Pool
Admin
4 years ago
Reply to  Prince

Do you input an IP outside of the network?

ami
ami
4 years ago

I tried the code, only option 7 is available,
all other return the following message:
in analyse_nmap_xml_scan
  raise PortScannerError(nmap_err)
nmap.nmap.PortScannerError: ‘You requested a scan type which requires root privileges.\nQUITTING!\n’

Pratik Kinage
Admin
4 years ago
Reply to  ami

You need to run your Python code as an administrator to get results. In windows, you can do this by opening a command prompt using “Run as Administrator” option. In Linux, you can do this by using the “sudo” command.

Regards,
Pratik

ami
ami
4 years ago
Reply to  Pratik Kinage

Thanks for addressing my question. I’m using a Mac…Already tried sudo su in terminal…with no results 🙁

Pratik Kinage
Admin
4 years ago
Reply to  ami

sudo command should work in Mac. Can you check if your user account has admin privileges? Check this guide if it helps support.apple.com

Regards,
Pratik

seret
seret
4 years ago

hey i’m trying to run the code but it’s writing scanner = nmap.PortScanner()
AttributeError: module ‘nmap’ has no attribute ‘PortScanner’
can you help?

seret
seret
4 years ago

Hey i’m trying to run the code but it’s writing scanner = nmap.PortScanner()
AttributeError: module ‘nmap’ has no attribute ‘PortScanner’
can you help?

Pratik Kinage
Admin
3 years ago
Reply to  seret

pip uninstall nmap
pip install python-nmap

This will solve it.

hackerregmi
hackerregmi
3 years ago

How u did OS detection?

Pratik Kinage
Admin
3 years ago
Reply to  hackerregmi

You can select option 5 to get OS info.