Skip to main content

Python Network: How to Build a GUI Network Scanner with Nmap

Network scanning is a critical step in cybersecurity and network administration for discovering active devices and open ports. While nmap is a powerful command-line tool, building a Graphical User Interface (GUI) around it makes it more accessible and user-friendly.

This guide demonstrates how to create a Python application that accepts an IP address, executes an Nmap scan, and displays the results using tkinter for the GUI and subprocess to interact with the system.

Prerequisites and Installation

To build this scanner, you need Python installed, along with the nmap system utility. We will also use tkinter (usually included with Python) and subprocess (standard library).

Installing Nmap

You must have the underlying nmap tool installed on your operating system, not just the Python library.

# Ubuntu/Debian
sudo apt update
sudo apt-get install nmap -y
sudo apt-get install python3-tk -y
note

This tutorial uses the standard library subprocess to call nmap directly, giving you full control over the command arguments without relying on third-party wrappers like python-nmap.

Handling the Nmap Process

The core logic involves receiving an IP address, running a shell command, and capturing the output.

The Scan Function

We need a function that runs nmap -F <ip> (Fast scan) and captures the standard output.

import subprocess

# ⛔️ Basic approach (Prone to crashing)
# If nmap fails or isn't installed, this crashes the program
def basic_scan(ip_address):
output = subprocess.check_output(["nmap", "-F", ip_address])
return output.decode("utf-8")

To make this robust, we must handle exceptions, such as the user entering an invalid IP or Nmap failing to run.

import subprocess

# ✅ Correct: Robust approach with Error Handling
def scan_network(ip_address):
try:
# Run nmap -F (Fast scan) on the provided IP
output = subprocess.check_output(["nmap", "-F", ip_address])
return output.decode("utf-8")
except subprocess.CalledProcessError:
return "Error: Could not scan. Check IP address or Nmap installation."
except FileNotFoundError:
return "Error: Nmap is not installed or not in your PATH."
warning

Using subprocess.check_output in a GUI application on the main thread will freeze the window until the scan is complete. For production apps, consider using Python's threading module to run the scan in the background.

Building the GUI with Tkinter

We will construct a simple window with three main elements:

  1. Entry: For the user to type the IP.
  2. Button: To trigger the scan.
  3. Text: To display the multiline output.
import tkinter as tk

# Initialize main window
window = tk.Tk()
window.title("Network Scanner")

# Input Section
label_ip = tk.Label(window, text="Enter IP Address:")
label_ip.pack()

entry_ip = tk.Entry(window)
entry_ip.pack()

# Result Section
result_text = tk.Text(window, height=15, width=60)
result_text.pack()

Complete Source Code

Here is the fully functional code combining the logic and the interface.

Create a file named network_scanner.py:

import tkinter as tk
import subprocess

def run_scan():
"""
Retrieves IP from entry, runs Nmap, and updates the text area.
"""
# Get user input
ip_address = entry_ip.get()

# Clear previous results (1.0 is line 1, char 0)
result_text.delete(1.0, tk.END)
result_text.insert(tk.END, f"Scanning network: {ip_address}...\nPlease wait.\n\n")

# Force UI update so the "Please wait" message appears immediately
window.update()

try:
# ✅ Correct: Execute nmap command securely
# -F stands for Fast mode (scans fewer ports)
output = subprocess.check_output(["nmap", "-F", ip_address])

# Decode bytes to string and display
result_text.insert(tk.END, output.decode("utf-8"))

except subprocess.CalledProcessError:
result_text.insert(tk.END, "⚠️ Error: The scan failed. Please check the IP address.")
except FileNotFoundError:
result_text.insert(tk.END, "⚠️ Error: 'nmap' command not found. Please install Nmap.")

# --- GUI Setup ---
window = tk.Tk()
window.title("Python Network Scanner")
window.geometry("500x400")

# Label
label_ip = tk.Label(window, text="Enter Target IP (e.g., 127.0.0.1):", font=("Arial", 12))
label_ip.pack(pady=10)

# Input Field
entry_ip = tk.Entry(window, font=("Arial", 12))
entry_ip.pack(pady=5)

# Button
scan_button = tk.Button(window, text="Scan Network", font=("Arial", 12, "bold"), command=run_scan)
scan_button.pack(pady=10)

# Output Area
result_text = tk.Text(window, font=("Consolas", 10), height=15)
result_text.pack(padx=10, pady=10, fill=tk.BOTH, expand=True)

# Start App
window.mainloop()

Running the Project

python network_scanner.py
  1. The window appears.
  2. Enter an IP (e.g., 127.0.0.1 or google.com).
  3. Click Scan Network.

Output Example (in GUI):

Scanning network: 127.0.0.1...
Please wait.

Starting Nmap 7.80 ( https://nmap.org ) at 2025-12-20
Nmap scan report for localhost (127.0.0.1)
Host is up (0.000045s latency).
Not shown: 96 closed ports
PORT STATE SERVICE
22/tcp open ssh
80/tcp open http
631/tcp open ipp
5432/tcp open postgresql

Nmap done: 1 IP address (1 host up) scanned in 0.12 seconds
tip

Some Nmap scans (like OS detection -O) require root privileges. To run these, you would need to execute your Python script with sudo python network_scanner.py.

Conclusion

You have successfully built a GUI wrapper for a command-line tool.

  1. subprocess.check_output allows you to harness the power of system tools like Nmap within Python.
  2. tkinter provides a straightforward way to accept input and visualize the raw text output.
  3. Error Handling ensures the application reports issues (like missing dependencies) instead of crashing silently.