Migrate to RunxBuild and earn up to $50 in hosting credit on your first deposit.

Calculate your savings
unxBuild
Back to Blog Explainer

The Hypertext Transfer Protocol Port: Why 80 and 443, and What Changed

Sean

Platform Writer

Aug 10, 2026
7 min read

The Hypertext Transfer Protocol uses port 80 by default, and HTTP over TLS uses port 443. Those are the numbers your browser assumes when a URL omits a port, which is why you type example.com and not example.com:443. Both are TCP ports — although HTTP/3 has quietly changed that last part.

The Hypertext Transfer Protocol Port: Why 80 and 443, and What Changed

These two numbers are so familiar that most developers never ask where they came from or why port 80 still exists now that everything is encrypted. Both questions have answers that turn out to matter operationally, particularly the second one.

Table of contents

Where the numbers came from

Port 80 was not chosen for any technical reason. In the early 1990s the low port range was assigned by hand, and 80 was simply the next unallocated number in a region reserved for well-known services. Ports 79 and 81 were already taken. The HTTP specification then made it official: if no port is specified, 80 is assumed.

Port 443 was allocated for HTTPS when Netscape introduced SSL in 1994. There is even less of a story there — it was free.

The reason these are well-known ports matters more than the specific values. Ports below 1024 require root or an explicit capability to bind on Unix systems, which is a deliberate security boundary: an unprivileged process cannot claim to be the web server on a shared machine.

# This fails as a normal user
node server.js   # Error: listen EACCES: permission denied 0.0.0.0:80

# Grant the capability instead of running as root
sudo setcap 'cap_net_bind_service=+ep' $(which node)

# Or the far more common answer: bind high, proxy low
# app listens on 3000, nginx listens on 80/443 and forwards

That last pattern is why almost no application binds port 80 directly in production. The app listens on a high port and a reverse proxy or the platform handles the privileged one, along with TLS termination.

Why port 80 still exists in an HTTPS world

If everything should be encrypted, why keep an unencrypted port open at all? Three reasons, and only one of them is a good one.

  • Redirects. A user typing example.com into the address bar still gets HTTP first in many cases. Closing port 80 means that request times out rather than redirecting, which looks like your site is down.
  • ACME HTTP-01 challenges. The most common way to get a free TLS certificate involves the certificate authority fetching a file over plain HTTP on port 80. Close it and automatic renewal breaks — silently, sixty days later.
  • Legacy clients. Old integrations that hardcode http://. This is the reason you want to eliminate rather than accommodate.

The standard configuration keeps 80 open and does nothing on it except redirect:

server {
    listen 80;
    server_name example.com www.example.com;

    # Let ACME through unredirected
    location /.well-known/acme-challenge/ {
        root /var/www/certbot;
    }

    location / {
        return 301 https://$host$request_uri;
    }
}

Note the ACME exception before the catch-all redirect. Redirecting the challenge path to HTTPS is a classic self-inflicted renewal failure, and the symptom is a certificate that expires two months after you thought you had automated it.

HSTS, and getting off port 80 properly

The redirect has a weakness: the first request is still plaintext and therefore interceptable. HTTP Strict Transport Security closes that gap by telling browsers never to use HTTP for your domain again.

Strict-Transport-Security: max-age=31536000; includeSubDomains; preload

Once a browser has seen that header, it rewrites http:// to https:// internally before any request leaves the machine. The redirect stops happening because the plaintext request stops happening.

Treat preload with respect. Submitting to the preload list bakes your domain into browser binaries, and removal takes months. If any subdomain cannot serve HTTPS, includeSubDomains will break it and you cannot quickly undo that. Start with a short max-age, confirm every subdomain works, then raise it.

Headers like this are edge configuration rather than application code, which is where they belong — the response headers documentation covers setting them per route.

Non-standard ports, and when they are appropriate

Nothing forces HTTP onto 80. Any port works if the client is told:

http://localhost:3000        # dev servers
http://localhost:8080        # the traditional alternate HTTP port
https://example.com:8443     # alternate HTTPS

# Explicitly stating the default is legal and redundant
https://example.com:443/     # identical to https://example.com/

Non-standard ports are correct for development, internal services, and admin interfaces on private networks. They are a poor idea for anything public-facing:

  • Corporate firewalls frequently allow only 80 and 443 outbound, so your API on 8443 is unreachable from inside many networks.
  • Users cannot type it, share it, or remember it.
  • Some proxies and captive portals mangle non-standard ports.
  • It provides no security benefit — port scanners enumerate all 65,535 in seconds.

Security through a non-standard port is not security. It is worth stating plainly, because moving an admin panel to port 8443 is still offered as a hardening measure. Authentication and network scoping are the controls that work; the port number is not one.

HTTP/3 broke the TCP assumption

This is the part that surprises people who last read about this a few years ago. HTTP/1.1 and HTTP/2 both run over TCP. HTTP/3 runs over QUIC, which is UDP.

It still uses port 443 — but UDP 443, a different socket from TCP 443. If your firewall rules only permit TCP 443, HTTP/3 silently does not work and clients fall back to HTTP/2. Nothing breaks, so nobody notices, and you lose the performance benefit you thought you had enabled.

# Both need to be open for HTTP/3
sudo ufw allow 443/tcp
sudo ufw allow 443/udp

# Confirm the server advertises HTTP/3
curl -I --http3 https://example.com

# The advertisement itself, sent over HTTP/2
curl -sI https://example.com | grep -i alt-svc
# alt-svc: h3=":443"; ma=86400

The Alt-Svc header is how it works: the server responds over HTTP/2 and mentions that HTTP/3 is available on UDP 443. The client tries QUIC for subsequent connections and remembers the result.

Encryption is not optional in QUIC — TLS 1.3 is built into the protocol rather than layered beneath it. There is no plaintext HTTP/3, which means there is no UDP equivalent of port 80.

What this looks like on a managed platform

Most of the above is work you do not do if the platform does it. Binding privileged ports, obtaining certificates, renewing them, redirecting 80 to 443, and negotiating protocol versions are solved problems with no product differentiation in solving them again.

On RunxBuild, a service listens on whatever port it likes — read from the PORT environment variable, conventionally — and the platform handles the public 80 and 443 side, including certificates for custom domains. The custom domains documentation covers how a domain and its certificate get attached.

// Read the port rather than hardcoding it
const port = process.env.PORT || 3000;
app.listen(port, '0.0.0.0', () => {
  console.log(`listening on ${port}`);
});

Bind 0.0.0.0, not 127.0.0.1. A service bound only to loopback is unreachable from outside its own container, and this is one of the most common reasons a deploy that works locally returns nothing in production.

How this fits the rest of the stack

Port 80 for HTTP, 443 for HTTPS, and both were chosen because they happened to be free. Keep 80 open for redirects and certificate renewal, add HSTS so the plaintext hop stops happening, and open UDP 443 as well if you want HTTP/3 to actually engage. Then hand the whole layer to something that manages it for you. If you are sizing a deployment and want the bandwidth and runtime as separate figures, the RunxBuild hosting calculator breaks them out.

Useful related references:

FAQ

What port does HTTP use?

Port 80 by default, over TCP. HTTPS uses port 443. Browsers assume these when a URL omits a port, which is why example.com and example.com:80 are equivalent.

Why is port 80 still open if my site uses HTTPS?

For redirects from plaintext requests and for ACME HTTP-01 certificate challenges, which are fetched over port 80. Closing it makes typed URLs time out and can silently break automatic certificate renewal.

Does HTTP/3 use port 443?

Yes, but over UDP rather than TCP. If your firewall only permits TCP 443, HTTP/3 fails silently and clients fall back to HTTP/2. Open UDP 443 as well.

Is it safer to run my site on a non-standard port?

No. Port scanners enumerate all 65,535 ports in seconds, so it provides no meaningful protection. It also breaks access from corporate networks that only allow 80 and 443 outbound.

Why can my application not bind to port 80?

Ports below 1024 require root or the cap_net_bind_service capability on Unix systems. The standard solution is to bind a high port in the application and let a reverse proxy or the hosting platform handle 80 and 443.

#hypertext transfer protocol port#port 80#port 443#https#http/3 quic