Build netstat and Get-NetTCPConnection commands to find the process using a port and list connections.
Almost everyone who opens netstat on Windows is there for one reason: something is already using a port, and they need to know what. This builder writes that command for you. Pick the task, pick Command Prompt or PowerShell, type the port number, and copy the result. It runs entirely in your browser — nothing is sent anywhere, because the tool is only assembling a string of text, not contacting your machine.
The command it produces for a port lookup is the one worth memorising:
netstat -ano | findstr :3389
Then, with the PID from the last column:
tasklist /FI "PID eq 4144"
That two-step sequence answers “what is holding port 3389” on any Windows machine from Windows 7 onwards, with no downloads and no admin rights.
Only a handful of switches matter in practice, and this builder emits exactly those. Everything else in netstat’s help output is either legacy or better served by another tool.
| Flag | Effect | Why you would use it |
|---|---|---|
-a | Shows all connections and listening ports | Without it, listeners are hidden and you will miss the very thing you are hunting |
-n | Numeric output — no reverse DNS, no service-name substitution | Far faster, and it prints :443 instead of :https so you can grep for the number |
-o | Adds the owning process ID column | The whole point — without it you know a port is busy but not who is holding it |
-b | Shows the executable name instead of just the PID | Saves the tasklist step, but requires an elevated prompt and is noticeably slower |
-r | Prints the routing table | Identical output to route print; handy when a destination is going out the wrong interface |
-s | Per-protocol statistics (segments sent, retransmits, errors) | Counters since boot — useful for spotting retransmission problems, useless for finding a process |
-p | Restricts -s to one protocol | netstat -s -p tcp keeps the statistics screen readable |
The builder combines these into six ready-made tasks: find the process using a port, list all connections with PIDs, list only listeners, show the owning program, print the routing table, and show per-protocol statistics.
The rightmost column before the PID is the TCP state, and misreading it sends people chasing problems that do not exist. These are the states you will actually see.
0.0.0.0:0. This is the state you are looking for when a service refuses to start because “the address is already in use”.findstr does plain substring matching, so netstat -ano | findstr :80 also matches :8080, :8000 and any remote address ending in port 80. It will happily match a port number that appears in the remote column too, which is why a search for a port you believe is free can still return rows.
Two ways round it. Anchor the match to the local column by including the address, as in findstr "0.0.0.0:80 " with a trailing space, or switch the builder to PowerShell, where the filtering is done on a real field rather than on text:
Get-NetTCPConnection -LocalPort 80
That matches the port exactly, and cannot accidentally catch 8080.
The PowerShell toggle in the builder is not decoration. Get-NetTCPConnection returns objects with typed properties, so you can filter, sort and format without text-wrangling. The builder’s PowerShell output for a port lookup joins the connection to the process name in one pass:
Get-NetTCPConnection -LocalPort 3389 | Select-Object LocalAddress, LocalPort, State, OwningProcess, @{N='Process';E={(Get-Process -Id $_.OwningProcess).ProcessName}}
No second tasklist call, no copying a PID by hand. Choose between them like this.
| Situation | Use | Reason |
|---|---|---|
| You need the process name alongside the port | PowerShell | One command; netstat -b needs elevation to do the same job |
| You want to sort, filter or export the results | PowerShell | Objects pipe into Sort-Object, Where-Object and Export-Csv directly |
| You are looking at UDP | netstat | Get-NetTCPConnection is TCP only; UDP needs Get-NetUDPEndpoint |
| You want protocol counters and retransmit statistics | netstat | netstat -s has no direct cmdlet equivalent |
| You are on a recovery console, a stripped image, or someone else’s locked-down box | netstat | Present in every Windows install and in cmd.exe with no modules to load |
| You are pasting a command into a ticket for a non-technical user | netstat | Short, memorable, and works in the box that says “cmd” |
One honest caveat about the builder’s PowerShell mode: for the “per-protocol statistics” task it produces a connection count grouped by state, not the protocol counters that netstat -s prints. Those are different questions. If you want retransmission and error counters, use the Command Prompt output.
Say IIS refuses to bind port 443. Run netstat -ano | findstr :443 and you get back a LISTENING row whose last column is 4. PID 4 is the System process, which means the port is held by the kernel-mode HTTP driver (http.sys) rather than by an ordinary application — typically a stale URL reservation or another service that registered the endpoint. tasklist /FI "PID eq 4" will only confirm “System”, which is why people get stuck here. The follow-up in that specific case is netsh http show servicestate, not another netstat run.
If the PID is a normal number, tasklist /FI "PID eq 4144" names the executable. From there you either stop the service that owns it or change the port of the thing you were trying to start.
The builder’s “show owning program” task emits netstat -anob and warns you that it needs an Administrator prompt. Two things surprise people. First, without elevation it prints Can not obtain ownership information for many rows rather than failing outright, so it looks like it worked. Second, it is slow: resolving the executable for every connection on a busy machine can take tens of seconds. For anything routine, -ano plus a single tasklist lookup is faster and does not need admin rights at all.
-ano, -r or -s. Only -b requires elevation.-a, netstat omits listening sockets. The builder always includes -a for exactly that reason.If you are trying to work out what a port number is for rather than who is using it, our port reference covers the well-known assignments. This page is about the other half of the problem: identifying the process behind the socket on the machine in front of you.
When someone says a server has “too many connections”, the useful move is to count rather than scroll. In Command Prompt:
netstat -ano | find /c "TIME_WAIT"
The /c switch makes find print a count instead of the matching lines. Swap in ESTABLISHED or CLOSE_WAIT for the other states. In PowerShell the builder’s statistics task does the whole breakdown in one go:
Get-NetTCPConnection | Group-Object State | Select-Object Name, Count
That single table is often enough to characterise the problem. A large ESTABLISHED count on a busy service is health, not illness. A large TIME_WAIT count is the normal residue of many short-lived outbound connections. A large and growing CLOSE_WAIT count is an application that is not closing its sockets, and it will eventually run the process out of handles.
Genuine port exhaustion is a different failure, and it has a distinctive signature: outbound connections start failing while inbound ones are fine, and the machine has burned through its dynamic port range. On Windows that range defaults to 49152–65535, and you can confirm what is configured with netsh int ipv4 show dynamicport tcp. The cause is nearly always an application opening a new connection per request instead of reusing a pool — widening the range buys time, it does not fix the behaviour.
One last practical note: pipe any of these into a file when you need to compare two moments in time. netstat -ano > before.txt, reproduce the fault, then netstat -ano > after.txt. Diffing two snapshots shows you what changed far more reliably than reading a live screen and trusting your memory of it.
Run netstat -ano | findstr :PORT to list connections on that port; the process ID is in the last column. Then run tasklist /FI "PID eq NUMBER" to see the program name. In PowerShell, Get-NetTCPConnection -LocalPort PORT does the same in one step.
LISTENING means a service is waiting for connections on that port. ESTABLISHED is an active, open session. TIME_WAIT is a recently closed connection that is winding down, which is normal and clears on its own after a short timeout.
The -b flag reveals the executable that owns each connection, which requires administrator rights. Open Command Prompt or PowerShell as Administrator and run it again, or use -o instead to get just the process ID without elevation.
On modern Windows it is often more convenient. Get-NetTCPConnection returns structured objects you can sort, filter, and pipe directly to Get-Process to resolve the program name, whereas netstat returns plain text you have to parse with findstr and tasklist.