ZYVOPMulti-Platform Sync
SeriesAI NewsWhy ZyVOPJoin Discord
LoginGet Started
ZYVOP
The Developer Publishing Hub
PrivacyTermsGuidelinesDMCACommunity
© 2026 ZyVOP
HomeBuild Your Own Port Scanner in Python (and Understand How Nmap Thinks)

Build Your Own Port Scanner in Python (and Understand How Nmap Thinks)

It’s simple enough to build in an afternoon, but building one teaches you more about how networks actually behave than reading ten articles about Nmap flags.

Lorenzo Fazioli
Lorenzo Fazioli
Student, Junior Developer
September 18, 2026
2 min read
Build Your Own Port Scanner in Python (and Understand How Nmap Thinks)
#cybersecurity#PortScanner#Python#GitHub#hacker

Why write one when Nmap exists?

Because using a tool and understanding a tool are different skills. When you write the scan loop yourself, you feel why a full connect scan is loud, why timeouts dominate your runtime, and why threading matters. That intuition transfers directly to reading Nmap output later.

The naive version

Start with the simplest thing that works: a socket, a connect call, and a loop.

import socket

def scan(host, ports):

    for port in ports:

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

        s.settimeout(0.5)

        if s.connect_ex((host, port)) == 0:

            print(f"[+] {port}/tcp open")

        s.close()

scan("127.0.0.1", range(1, 1025))

connect_ex is the key: it returns an error code instead of raising, so a closed port is just a non-zero return, not an exception to catch.

Why it’s painfully slow

Run it against 1024 ports and you’ll wait. Each closed port burns the full timeout serially. Scanning 1024 ports at 0.5s each is over eight minutes in the worst case — for one host.

Making it threaded

Network scanning is I/O bound, so threads help enormously here despite the GIL.

from concurrent.futures import ThreadPoolExecutor

def check(host, port):

    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:

        s.settimeout(0.5)

        if s.connect_ex((host, port)) == 0:

            return port

def scan(host, ports, workers=200):

    with ThreadPoolExecutor(max_workers=workers) as pool:

        results = pool.map(lambda p: check(host, p), ports)

    return [p for p in results if p]

Suddenly 1024 ports finish in seconds.

Where to go next

  • Grab banners: after connecting, send a probe and read the first bytes to fingerprint the service.

  • Add a SYN scan with raw sockets (requires root) to avoid completing the handshake.

  • Rate-limit yourself so you don’t trip IDS on networks you’re allowed to test.

One rule before you run it

Only scan hosts you own or have written permission to test. A port scan against someone else’s infrastructure can be illegal in most jurisdictions, full stop.

If you want the finished version, my Portscanner repo is on GitHub.

Comments (0)

Join the discussion by logging into your account.

Lorenzo Fazioli
Lorenzo Fazioli

Student, Junior Developer

Hi, my name is Lorenzo, I'm young but I like hacking and developer, especially web development and pent-testing.

Subscribe to Lorenzo Fazioli's Newsletter

Direct email dispatches when new stories are published. Zero algorithms.

Lorenzo Fazioli
Like
Love
Clap
Fire
Party
Wow

Trending on ZyVOP

Revamping Autonomous HDB Agents

In last week's post, Revamping the HDB Price Predictor, I overhauled my machine learning models into client-side, browser-evaluated engines with chronological...

See Hiong
See Hiong·
19 minSep 19

CSS reading-flow: Fix the Tab Order Your Layout Broke

Grid and flexbox let you rearrange a layout without touching the DOM, which quietly breaks keyboard navigation. The reading-flow and reading-order properties finally let CSS tell the browser which order actually counts.

Danny Holloran
Danny Holloran·
3 minSep 19

Cloudflare Quick Tunnels: One Command, Three Hard Limits

Quick Tunnels expose localhost in one command, no signup required. But they cap at 200 concurrent requests, drop Server-Sent Events, and carry no SLA. Here's the mechanics, a Node helper that reads the tunnel URL properly, and when to stop using them.

Sanju Singh
Sanju Singh·
13 minSep 19

macOS 27 Golden Gate: What Shipped, What's Dormant, and What's Missing

macOS 27 Golden Gate landed September 14 with a conversational Siri, a toned-down Liquid Glass, and the end of major macOS support for Intel Macs. Release-candidate research also points to dormant hooks for outside models.

Samod Alex
Samod Alex·
14 minSep 19

AI at the System Boundary: What This Week's Incidents Actually Tell Engineers

This week: Fields Medalists challenge how AI math progress gets measured, a four-month-old RubyGems spam campaign gets pinned on OpenAI agents, and an anti-bot tool bets scrapers will tire out first. The common thread: models get scrutinized, but the systems around them don't.

Ankit Singh
Ankit Singh·
7 minSep 18