Build a Simple Python Port Scanner

Overview

A Python port scanner is a simple networking tool that checks whether TCP ports on a host are accepting connections. While tools such as Nmap are far more powerful, writing a basic scanner yourself is a useful way to understand what port scanning actually does behind the scenes.

This example uses Python’s built-in socket module, so no third-party libraries are required.

Important: Only scan systems you own or have explicit authorization to test.

Python Port Scanner

Save the following as:

portscanner.py
#!/usr/bin/env python3

import socket
import sys

def scan_port(target, port):
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sock.settimeout(0.5)

    result = sock.connect_ex((target, port))
    sock.close()

    return result == 0


def main():
    if len(sys.argv) != 2:
        print(f"Usage: {sys.argv[0]} <target>")
        sys.exit(1)

    target = sys.argv[1]

    try:
        target_ip = socket.gethostbyname(target)
    except socket.gaierror:
        print(f"Unable to resolve target: {target}")
        sys.exit(1)

    print(f"Scanning {target} ({target_ip})")
    print("-" * 40)

    for port in range(1, 1025):
        if scan_port(target_ip, port):
            try:
                service = socket.getservbyport(port, "tcp")
            except OSError:
                service = "unknown"

            print(f"[OPEN] {port}/tcp - {service}")

    print("-" * 40)
    print("Scan complete.")


if __name__ == "__main__":
    main()

Running the Scanner

Make the script executable:

chmod +x portscanner.py

Then provide a hostname or IP address:

python3 portscanner.py 192.168.1.10

You can also scan a hostname:

python3 portscanner.py server.example.com

Example output might look like:

Scanning 192.168.1.10 (192.168.1.10)
----------------------------------------
[OPEN] 22/tcp - ssh
[OPEN] 80/tcp - http
[OPEN] 443/tcp - https
----------------------------------------
Scan complete.

How a Python Port Scanner Works

The scanner attempts to establish a TCP connection to each port between 1 and 1024.

The most important line is:

result = sock.connect_ex((target, port))

Python’s connect_ex() method attempts to connect to the specified TCP port.

If it returns:

0

the connection was successful and the port is considered open.

The scanner then prints the port number and attempts to identify the commonly associated service.

Creating the Socket

The following line creates the network socket:

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

The two arguments describe the type of connection being created.

ArgumentMeaning
AF_INETUse IPv4
SOCK_STREAMUse TCP

Together, these create an IPv4 TCP socket.

Setting a Timeout

The scanner uses:

sock.settimeout(0.5)

Without a timeout, a connection attempt could take several seconds before failing.

Setting the timeout to half a second prevents the script from waiting too long for hosts or ports that do not respond.

This is one of the biggest differences between writing a basic scanner and using a mature tool such as Nmap. Nmap contains sophisticated timing, retransmission, and host-discovery logic that this small script does not attempt to reproduce.

Resolving Hostnames

The script also supports DNS names:

target_ip = socket.gethostbyname(target)

For example:

python3 portscanner.py testserver.local

Python attempts to resolve that hostname into an IPv4 address before beginning the scan.

If resolution fails, the scanner exits instead of attempting to continue with an invalid target.

Identifying Services

When an open port is found, the script runs:

socket.getservbyport(port, "tcp")

This checks the operating system’s service database for the service commonly associated with that port.

For example:

22  -> ssh
80  -> http
443 -> https

This does not prove that the service actually running on the port is SSH, HTTP, or HTTPS. It only identifies the service traditionally assigned to that port.

That distinction is important.

An administrator could run SSH on:

2222/tcp

or a web server on:

8080/tcp

Tools such as Nmap perform additional probing to determine what service is actually listening.

Why Scan Ports 1 Through 1024?

The example scans:

range(1, 1025)

These include many commonly used and historically well-known ports.

Examples include:

PortTypical Service
21FTP
22SSH
23Telnet
25SMTP
53DNS
80HTTP
110POP3
139NetBIOS
143IMAP
443HTTPS
445SMB

A full TCP scan could check ports:

1-65535

but a simple sequential Python scanner becomes increasingly slow as the number of ports increases.

What This Scanner Does Not Do

This script is intentionally basic.

It does not perform:

  • UDP scanning
  • SYN scanning
  • OS fingerprinting
  • Banner grabbing
  • Service-version detection
  • NSE-style scripting
  • Vulnerability detection
  • Parallel or threaded scanning
  • Firewall evasion

For those tasks, a dedicated scanner such as Nmap is a much better choice.

The value of this Python script is educational: it shows what happens at the socket level when a TCP connection is tested.

Python Scanner vs. Nmap

The equivalent basic Nmap command would be:

nmap -p 1-1024 192.168.1.10

Nmap provides considerably more functionality:

nmap -sC -sV 192.168.1.10

Here:

OptionPurpose
-sCRuns Nmap’s default NSE scripts
-sVPerforms service and version detection

The Python scanner should therefore be viewed as a learning tool rather than a replacement for Nmap.

Security and Defensive Perspective

Port scanning is commonly associated with penetration testing, but administrators and defenders use exactly the same technique.

A security administrator might scan a server to verify that only expected services are exposed.

For example, a web server intended to expose only SSH and HTTPS might be expected to show:

22/tcp
443/tcp

If a scan unexpectedly reveals:

21/tcp
23/tcp
3306/tcp
5900/tcp

those services deserve investigation.

Regular internal scanning can help identify:

  • Accidentally exposed services
  • Unauthorized software
  • Misconfigured firewalls
  • Forgotten management interfaces
  • Shadow IT
  • Unexpected remote-access services

Common Mistakes

One common mistake is assuming that an open port automatically represents a vulnerability.

An open port simply means that something is accepting connections.

For example:

443/tcp open

does not mean the web server is vulnerable.

It means HTTPS is accessible and should be investigated further.

Another mistake is assuming that the port number proves which application is running. Port 22 normally means SSH, but applications can listen on virtually any available TCP port.

Key Takeaways

A Python port scanner is a useful project for understanding the fundamentals of TCP networking and reconnaissance.

The core operation is surprisingly simple:

sock.connect_ex((target, port))

Everything else around it handles input validation, DNS resolution, timeouts, output, and service-name lookup.

The most important skills practiced are:

  • Python socket programming
  • TCP networking
  • DNS resolution
  • Port enumeration
  • Error handling
  • Service identification
  • Basic network reconnaissance

From a defensive perspective, port scanning is equally useful for discovering unnecessary or unexpected network services before an attacker does.

Similar Posts