Why Network Ports Go From 0 to 65535: The 16-Bit Story
Port numbers stop at 65535 because TCP and UDP store them in a 16-bit field. Here is what that means, how IANA splits the range, and why low ports need root.
You have probably seen :8080, :443, or :3000 hanging off the end of an address and never wondered why the ceiling is 65535 and not, say, 100000. The number is not arbitrary. It falls directly out of how many bits TCP and UDP set aside to store a port.
It is a 16-bit field, so the math is fixed
Both the TCP and UDP headers reserve exactly 16 bits for the source port and 16 bits for the destination port. A 16-bit unsigned integer can represent 2^16 = 65536 distinct values. Counting from zero, that gives you the inclusive range 0 to 65535. There is no extra register, flag, or extension that grows it; the size of the field is the size of the address space.
This is the same reason an 8-bit byte tops out at 255 (2^8 - 1) and a classic unsigned short in C tops out at 65535. A port is, quite literally, an unsigned short. If you ever try to bind to port 70000, the library either rejects it or silently wraps the value, because the number simply does not fit in the slot the protocol gives it.
A port is not a physical thing. It is a label inside a packet that lets one machine run many network services at once. Your laptop has one IP address but can talk to a web server, an SSH daemon, and a database simultaneously because each conversation is tagged with a different port. The operating system uses the combination of (protocol, source IP, source port, destination IP, destination port) to route each packet to the right socket.
How IANA carves up the 65536 values
The numbers themselves are just integers, but the Internet Assigned Numbers Authority (IANA) splits the range into three conventional zones so that software agrees on where common services live:
- Well-known / system ports — 0 to 1023. These are the famous ones: HTTP on 80, HTTPS on 443, SSH on 22, DNS on 53, SMTP on 25. They are assigned for standard services so that a client can connect to
https://example.comwithout being told the port. - Registered ports — 1024 to 49151. Vendors and projects register these with IANA for specific applications, but they are not as tightly controlled. PostgreSQL’s default 5432 and MySQL’s 3306 live here.
- Dynamic / private / ephemeral ports — 49152 to 65535. Nobody owns these. The OS hands them out temporarily for the client side of a connection.
That last category is the one you rarely type but use constantly. When your browser opens a connection to port 443 on a server, your own machine needs a return address too. It grabs a free ephemeral port for the duration of that connection and releases it afterward. Open 30 browser tabs and your OS is juggling dozens of ephemeral ports behind the scenes.
Why low ports need elevated privileges
On Unix-like systems, binding to any port below 1024 traditionally requires elevated privileges (root, or a specific capability like CAP_NET_BIND_SERVICE on Linux). Ports at or above 1024 can be bound by ordinary users.
The reason is historical and security-minded. The well-known ports map to trusted services, so the rule prevents an unprivileged user from, say, starting a fake SSH server on port 22 and harvesting other people’s passwords. The cost is friction: it is why a Node or Python dev server defaults to something like 3000 or 8080 instead of 80, and why production setups often run the app on a high port and put a privileged reverse proxy in front to listen on 80 and 443.
You can verify which ports are listening with a quick command:
# macOS / Linuxss -tlnp # or: lsof -i -P -n | grep LISTENFAQ
The port number ceiling is one of those facts that looks like a magic constant but is really just a consequence of a design decision made decades ago: give each port a 16-bit slot in the packet header, and 65535 is what you get.
FAQ
Can the same port number be used by both TCP and UDP at once?+
Why does it start at 0 and not 1?+
Could ports ever go higher than 65535?+
Related reading
2026-06-04
ACID vs BASE: What Database Guarantees Actually Promise
ACID and BASE describe two ends of a tradeoff between strict correctness and scalable availability. Learn what each guarantee means, when each fits, and why most modern databases sit somewhere in between.
2026-06-04
Big-Endian vs Little-Endian
Byte order explained: how big-endian and little-endian lay out multi-byte numbers in memory, why network protocols pick one, and when the difference actually bites you.
2026-06-04
Big-O Notation in Plain English
Big-O describes how an algorithm's runtime or memory grows as input grows. Learn the common classes — O(1), O(log n), O(n), O(n log n), O(n^2), O(2^n) — with plain examples.
2026-06-04
CORS in Plain English: Why the Browser Blocks Your Fetch
A clear walkthrough of CORS and the same-origin policy — what an origin is, why your fetch fails, how servers opt in, and the big misconception about who CORS actually protects.
2026-06-04
Environment Variables and PATH, Explained
What environment variables actually are, why they hold config and secrets, and how PATH decides which binary runs when you type a command.
Get the best tools, weekly
One email every Friday. No spam, unsubscribe anytime.