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.
| Argument | Meaning |
|---|---|
AF_INET | Use IPv4 |
SOCK_STREAM | Use 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:
| Port | Typical Service |
|---|---|
| 21 | FTP |
| 22 | SSH |
| 23 | Telnet |
| 25 | SMTP |
| 53 | DNS |
| 80 | HTTP |
| 110 | POP3 |
| 139 | NetBIOS |
| 143 | IMAP |
| 443 | HTTPS |
| 445 | SMB |
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:
| Option | Purpose |
|---|---|
-sC | Runs Nmap’s default NSE scripts |
-sV | Performs 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.
