5900
The base port of the RFB protocol that VNC speaks — and the reason a viewer refuses to connect while the server sits happily on 5901.
Run the line for your platform. Each one names the process holding the port and the address it bound to, which is usually the whole answer.
sudo lsof -nP -iTCP:5900 -sTCP:LISTEN`-n` and `-P` keep addresses and ports numeric so the NAME column reads as `*:5900` rather than `*:rfb`; `-iTCP:5900` selects the port and `-sTCP:LISTEN` keeps only listening sockets. COMMAND names the owner, PID is the number to act on and NAME is the bind address — `*:5900` means every interface, which for Screen Sharing means anyone who can route to this Mac can try. The `sudo` is not optional here: the Screen Sharing listener belongs to a system account, so an unprivileged `lsof` prints nothing and a busy port looks free. Drop `-sTCP:LISTEN` to see established viewer sessions as well, which is how you find out somebody is already connected.
sudo ss -tlnp 'sport >= :5900 and sport <= :5910'Scan the range rather than the single port, because the display number decides which one is in use. `-t` displays TCP sockets, `-l` only listening ones, `-n` skips service-name resolution and `-p` shows the owning process; `sport` compares the source port and accepts `<`, `<=`, `=`, `!=`, `>=` and `>`, so a range is one expression. A row on 5901 is display `:1`, 5902 is `:2`, and so on. The Local Address:Port column separates a server on `127.0.0.1:5901` — loopback only, waiting for an SSH tunnel — from one on `0.0.0.0:5901` that the whole network can reach. The owner appears as `users:(("Xvnc",pid=2210,fd=8))`. Without `ss`, `sudo netstat -tlnp | grep -E ':59[0-9][0-9]'` gives the same picture with a slash-separated pid/program column; both need superuser privileges to name processes you do not own.
netstat -ano | findstr ":59"Match the prefix rather than the exact port, for the same display-number reason. `-a` displays all connections and listening ports, `-n` keeps addresses and ports numeric, and `-o` adds the owning process ID in the last column. Read the Local Address column to find which of `5900`, `5901` and so on is actually bound and whether it is `0.0.0.0` or `127.0.0.1`, and require a State of LISTENING before treating the row as the server. Then name the process with `tasklist /FI "PID eq 3320"`, whose PID filter takes eq, ne, gt, lt, ge and le; expect something like `tvnserver.exe` or `winvnc.exe`. Because `findstr` matches substrings, a broad `:59` pattern also catches unrelated high ports — check the full number before acting.
Get-NetTCPConnection -LocalPort 5900 | Select-Object LocalAddress,LocalPort,State,OwningProcessExact-match alternative to the substring hunt above, and it is worth running for each display number you suspect. `State` of `Listen` plus a `LocalAddress` of `127.0.0.1` means a server deliberately restricted to this machine, which is the safe configuration and also the reason a remote viewer is refused. Pipe `OwningProcess` into `Get-Process -Id` for the executable. An empty result on every port in the range means no VNC server is running at all, so the viewer's refusal is accurate rather than mysterious.
`nmap -Pn -p 5900-5910 host.example.com` is the version worth typing, because scanning the single port answers only half the question — the server may be on 5901 for display `:1`. `-Pn` skips host discovery so a host that ignores ping is still scanned. Nmap's states have exact meanings: `open` means an application on the target is listening; `closed` means the host replied but nothing is listening there; `filtered` means a firewall, filter or other network obstacle is blocking the probe so nmap cannot tell which. For VNC, a `closed` 5900 next to an `open` 5901 is the whole diagnosis in one line. Add `--reason` to see which packet decided each state, and `-sV` to have nmap read the RFB banner and report the protocol version and implementation. Scan only hosts you are responsible for.
| What you see | What it means |
|---|---|
The viewer reports connection refused on 5900 while the VNC server is definitely running | Almost always the display arithmetic. RFC 6143 puts server N on 5900+N, so `vncserver :1` is on 5901 and nothing at all is on 5900. A viewer given a bare host name dials 5900 and is correctly refused. Enter `host:1` or `host::5901` depending on the viewer's syntax, and confirm with a range scan rather than a single-port one. |
The viewer hangs and eventually times out instead of failing immediately | Nothing answered, so the packet was dropped rather than rejected: a host firewall, a cloud security group, or an ACL between you and the machine. A refusal is instant; a drop takes the full connect timeout. `nmap --reason` names it — `filtered` for the drop, `closed` for the refusal — and this is also the expected result when the server was correctly bound to loopback and you forgot the SSH tunnel. |
The server will not start: the display or port is already in use, or bind fails with Address already in use | `EADDRINUSE` on 5900+N. Either a previous `Xvnc` for that display is still alive, or a stale lock file left behind by one that was killed makes the display look taken while the port is free — the two cases look identical from the error alone, so check the port first with the probe for your platform. Starting on a different display number sidesteps it; killing the right process fixes it. |
No matching security types | The TCP connection succeeded and the RFB handshake reached the security negotiation, where the server's list and the viewer's list had nothing in common. Typically the server offers only VNC Authentication while the viewer is configured to require an encrypted vendor extension, or the server offers a proprietary type this viewer never implemented. It is a configuration mismatch between the two programs, not a network fault — nothing about the port needs changing. |
A long password is accepted, and so are its first eight characters | Not a bug in the server. VNC Authentication forms its DES key by truncating the password to eight characters or padding it with null bytes on the right, so every character past the eighth is discarded on both sides. Anyone attacking the session only ever has to search eight characters, which is why RFC 6143 itself calls this scheme cryptographically weak and unsuitable for untrusted networks. |
lsof or ss prints nothing, yet the port is clearly busy | The permission case: both tools show only processes you own unless you run them with `sudo`, and a VNC server started by another user, by a system service such as macOS Screen Sharing, or inside a container is invisible without it. Re-run with `sudo` before concluding the port is free — and if a Docker process turns out to own it, stop the container rather than killing the process, because the supervisor will just republish it. |
The session connects, but the screen is blank or shows only a grey background and an X cursor | The port and the authentication both worked, so this is not a networking problem at all. A standalone `Xvnc` display starts with no desktop session attached until a window manager is launched for it, which is what the server's startup script is meant to do. Look at the VNC server's own log for the display rather than at the port. |
5900 is the base port of the Remote Framebuffer protocol, standardised as RFC 6143 and registered with IANA as `rfb`. The RFC is explicit about the arithmetic that trips everyone up: "An RFB client contacts the server on TCP port 5900. On systems with multiple RFB servers, server N typically listens on port 5900+N, analogous to the way that X Window servers listen on port 6000+N." So a Unix `vncserver` that starts display `:1` is listening on 5901, not 5900 — and 5901 is not in the IANA registry at all; only the base number is assigned. Type a bare host name into a viewer and it dials 5900, which on that machine is very often nothing, which is why "connection refused" is the single most common VNC symptom and almost never means what people assume. What actually holds the port varies by platform and matters when you go looking: on macOS the built-in Screen Sharing and Apple Remote Desktop use 5900 directly, and Apple's own port list names it `rfb` with a reference to RFC 6143; on Linux it is `Xvnc` from TigerVNC or TightVNC, or `x11vnc` attached to a display that already exists; on Windows it is a service such as TightVNC's `tvnserver`. They all speak the same handshake, which is why a viewer from one project usually connects to a server from another — right up to the point where the two cannot agree on a security type.
Do not expose 5900 to the internet, and do not mistake VNC's password for protection. RFC 6143 defines only three security types in the core protocol — 0 Invalid, 1 None and 2 VNC Authentication — and type 1 means no authentication whatsoever, which is exactly what a great many internet-exposed servers still offer. Type 2 is barely better: the server sends a random 16-byte challenge, and the client encrypts it with DES using the password as the key, where "the password is truncated to eight characters, or padded with null bytes on the right". Eight characters is the entire key space no matter how long a password you typed. The RFC's own security considerations put it plainly: this "is known to be cryptographically weak and is not intended for use on untrusted networks. Many implementations will want to use stronger security, such as running the session over an encrypted channel provided by IPsec or SSH." Nothing in the core protocol encrypts the session either, so the framebuffer — and everything you type into it — crosses the network in the clear. Bind the server to loopback and reach it through a tunnel, for example `ssh -L 5901:127.0.0.1:5901 user@host`, then point the viewer at `127.0.0.1:5901`. Vendor extensions add TLS and stronger authentication, but they are extensions: both ends have to implement the same one, which is precisely what a security-type negotiation failure is telling you when they do not.
All of these run in your browser — nothing is uploaded.
Ports people usually end up checking in the same session as 5900.
Almost always permissions. lsof and ss list the socket but hide the owning process when it belongs to another user, so a server started by a system account, by a container runtime or by launchd shows up as an anonymous listener until you re-run the command with sudo. On Windows the opposite happens: netstat shows nothing at all, yet a bind still fails, which means the port sits inside a range that Hyper-V, WSL2 or Docker Desktop reserved at boot.
Look at what it is first. An orphaned dev server is safe to kill; a database with a write in flight is not, and neither is a system service that something else depends on. If the owner is a container, stop the container instead — killing the process the host sees only makes the runtime restart it. When the process is something you need, moving your own service to another port is the faster fix.
The listener bound to 127.0.0.1 rather than 0.0.0.0. The probes on every page print the bound address next to the process for exactly this reason: a loopback bind is reachable from the machine itself and from nowhere else, no matter how the firewall is configured. Many frameworks made that the default deliberately, so it is usually a flag rather than a bug. If the address is already 0.0.0.0 and it still fails, the next suspect is a host firewall or a cloud security group.
Barely. Internet-wide scanners sweep the whole port range continuously, so an unusual number buys hours, not safety, and it costs you every colleague who now has to remember it. It does cut the noise in your logs from opportunistic scans of the default port, which is a real if modest benefit. Authentication, a firewall that restricts source addresses, and not exposing the service at all are the measures that actually change the outcome.
Still stuck on port 5900? browse every port in the reference — or go back to the failure message you actually got, above.