How-to · Network

Find what is using port 8080 on Windows

Your dev server says port 8080 is already in use. Find the process behind it with netstat, tasklist and PowerShell, learn what the listening addresses mean, and free the port without breaking something else.

Reading time
7 min
Updated
Applies to
Windows 10, Windows 11
Privileges
Standard user; elevation only to stop a service
Difficulty
Beginner

You start a development server and it stops immediately with “address already in use”. Something on your PC already owns port 8080, and Windows will not let two programs listen on the same port. This guide shows how to find out what that something is with the tools built into Windows 10 and 11, what the output means, and how to free the port without breaking anything else. The steps work for any port; 8080 is just the one that collides most often.

The symptom

Each runtime words the same error differently:

Node.js   Error: listen EADDRINUSE: address already in use :::8080
Python    OSError: [WinError 10048] Only one usage of each socket address
          (protocol/network address/port) is normally permitted
Java      java.net.BindException: Address already in use: bind
.NET      SocketException (10048): Only one usage of each socket address ...

Underneath they are all Windows socket error 10048, WSAEADDRINUSE: the program asked to bind a listening socket to port 8080 and the port was taken.

Note

A different message, “An attempt was made to access a socket in a way forbidden by its access permissions” (error 10013, shown by Node.js as EACCES), usually means the port is reserved by Windows rather than used by a program. Jump to When the port looks free but is unusable.

Why ports are exclusive

When a packet arrives for 127.0.0.1 port 8080, the TCP stack has to hand it to exactly one listening socket. Two listeners would make delivery ambiguous, so Windows refuses the second bind. The rule is per protocol: a UDP socket on 8080 does not block a TCP listener on 8080, which is why the commands below filter on protocol as well as port.

The usual owners of 8080 are mundane: an earlier instance of your own server that is still running (often a child process that survived the terminal being closed), a container, a proxy, Tomcat or Jenkins, or another project on the same machine. Occasionally it is a Windows service.

Find the owner with netstat

Open a terminal (Command Prompt, PowerShell or Windows Terminal; no elevation needed) and run:

netstat -ano | findstr ":8080"

The flags: -a shows all sockets, including listening ones; -n prints numeric addresses and ports instead of resolving names, which is faster and unambiguous; -o adds the owning process ID. findstr ":8080" keeps only the lines containing that text.

  Proto  Local Address          Foreign Address        State           PID
  TCP    0.0.0.0:8080           0.0.0.0:0              LISTENING       15324
  TCP    [::]:8080              [::]:0                 LISTENING       15324

Proto is TCP or UDP. Local Address is the address and port the socket is bound to on this machine. Foreign Address is the remote end, which is always 0.0.0.0:0 or [::]:0 for a listener. State says whether the row is a listener (LISTENING) or a connection (ESTABLISHED, TIME_WAIT and so on); UDP rows have no state. PID is the process that owns the socket.

A row whose foreign address ends in :8080 is a connection to someone else’s port 8080, not a listener on yours. To see only listeners:

netstat -ano | findstr ":8080" | findstr "LISTENING"

Turn the PID into a process

tasklist /FI "PID eq 15324"

/FI applies a filter, and "PID eq 15324" matches on process ID.

Image Name                     PID Session Name        Session#    Mem Usage
========================= ======== ================ =========== ============
node.exe                     15324 Console                    1     61,412 K

Image Name is the executable. Session Name and Session# tell you which logon session it runs in: Console is the interactive desktop, Services is session 0, where services live. Mem Usage is the working set.

If you would rather skip the second step, netstat -abno prints the executable name under each row, but -b only works from an elevated terminal.

The PowerShell way

Get-NetTCPConnection returns the same table as objects you can filter and pipe:

Get-NetTCPConnection -LocalPort 8080 -State Listen

It returns LocalAddress, LocalPort, RemoteAddress, RemotePort, State and OwningProcess (the PID). When nothing matches, the cmdlet reports an error that no matching objects were found; in scripts add -ErrorAction SilentlyContinue.

Hand the PID to Get-Process:

Get-Process -Id 15324 | Select-Object Id, ProcessName, Path, StartTime

Path is the full path of the executable. It is blank when Windows will not let your account open the process (another user’s session, a service, a protected process); running the same command from an elevated PowerShell usually fills it in.

As one pipeline:

Get-NetTCPConnection -LocalPort 8080 -State Listen |
  ForEach-Object { Get-Process -Id $_.OwningProcess } |
  Select-Object Id, ProcessName, Path

For UDP use Get-NetUDPEndpoint -LocalPort 8080; UDP sockets have no state, so there is no -State parameter.

If you prefer a window, Resource Monitor (run resmon, open the Network tab, expand Listening Ports) shows image, PID, address, port and protocol in one list.

What the address tells you

Local address Meaning
0.0.0.0:8080 Every IPv4 address on this machine; reachable from the LAN if the firewall allows it
127.0.0.1:8080 IPv4 loopback only; nothing outside this PC can connect
[::]:8080 Every IPv6 address; a dual-stack socket accepts IPv4 connections here too
[::1]:8080 IPv6 loopback only
192.168.1.20:8080 One specific interface

Two rows with the same PID on 0.0.0.0 and [::] are one dual-stack listener, not two programs. A server bound only to 127.0.0.1 can look down when a client resolves localhost to ::1 first, and a server bound only to [::1] is not reachable at 127.0.0.1. Binding to both, or to the wildcard of each family, avoids the confusion.

When the owner is svchost.exe

svchost.exe hosts Windows services, so the name alone does not say which service has the port. Ask for the services inside that PID:

tasklist /svc /FI "PID eq 1116"
Image Name                     PID Services
========================= ======== ============================================
svchost.exe                   1116 RpcEptMapper, RpcSs

PowerShell gives display names and state as well:

Get-CimInstance Win32_Service -Filter "ProcessId = 1116" |
  Select-Object Name, DisplayName, State

On a developer port like 8080 this is rare; on 135, 1900, 5353 or 7680 it is the norm. The guide What is svchost.exe and why does it use so many ports? covers the service groups and how to tell a genuine copy from an impostor.

When the port looks free but is unusable

If netstat shows nothing on 8080 and binding still fails, the port may be inside a range that Windows has reserved. Hyper-V, WSL 2 and Docker Desktop reserve blocks of ports through the Windows NAT driver, and a reserved port cannot be bound even though no process is listening on it. List the reserved ranges:

netsh interface ipv4 show excludedportrange protocol=tcp
Protocol tcp Port Exclusion Ranges

Start Port    End Port
----------    --------
      1061        1160
      5000        5099
      8032        8131
     50000       50059     *

* - Administered port exclusions.

If 8080 falls inside one of the ranges, that is the cause. Ranges marked * were added by an administrator (or by you) and stay put. The unmarked ones are allocated dynamically and can move after a reboot, which is why a port that worked yesterday may fail today. The troubleshooting guide Port in use but no process is listed on Windows walks through the fixes, from choosing another port to restarting the NAT service.

Free the port safely

In order of preference:

  1. Stop the other program the normal way. Press Ctrl+C in its terminal, close its window, run docker stop <name> for a container, or Stop-Service <name> for a service. The port is released the moment the socket closes.
  2. Change your own port instead. Most servers read a PORT environment variable or a --port option. If the other listener is something you need (a colleague’s proxy, a company agent), this is the only fix that lasts.
  3. Terminate the process, if you know what it is. taskkill /PID 15324 asks the program to close, which works for programs that have a window. taskkill /PID 15324 /F or Stop-Process -Id 15324 ends it immediately and loses unsaved work.

Warning

Do not force-kill a PID you have not identified. PID 4 is the Windows kernel, svchost.exe carries services that other programs depend on, and killing a database or an editor mid-write can corrupt its files. Stop services through Stop-Service or the Services app, not taskkill.

Stop-Process -Id 15324

Watch for the parent-and-child trap: closing a terminal that ran npm start can leave the node.exe child alive. Always stop the PID that netstat reports, not the one that launched it.

PortWho: the same answer in one view

The commands above work, but they are three steps across several tools, and when the result is svchost.exe you need one more. PortWho is a small Utility Forge tool that answers the question once:

portwho 8080

For every TCP listener and bound UDP socket on that port it reports the protocol, local address and port, the PID, the process name, the executable path, the Windows services hosted by that process (so svchost.exe is explained in the same row) and whether the executable carries a valid Authenticode signature and who signed it. portwho with no argument lists everything, portwho --search node filters by process name, path, service or signer, and portwho --json produces structured output for scripts.

PortWho is read-only. It never stops a process, never touches a socket or a service, and never uses the network, not even for signature checks. It is currently in development: the engine, the command line and a desktop application with a port lookup box are implemented and tested internally, and there is no public download yet. The PortWho page tracks its status and the documentation describes the output in detail. Like netstat’s LISTENING rows, it covers listening TCP sockets, not established connections, and it does not yet list reserved port ranges; use the netsh command above for those.

FAQ

Frequently asked

Does netstat need administrator rights?

No. netstat -ano runs as a standard user and still shows the owning PID of every socket. Only the -b flag, which prints the executable name under each row, needs an elevated terminal. Use tasklist or Get-Process with the PID instead and you never need to elevate.

Why does port 8080 show up twice, once on 0.0.0.0 and once on [::]?

If both rows carry the same PID, it is one dual-stack listener that accepts IPv4 and IPv6 connections. Two different PIDs mean one program listens on IPv4 only and another on IPv6 only, which Windows allows because the two sockets do not overlap.

netstat lists a PID but tasklist cannot find it. What happened?

The process exited between the two commands, or it restarts constantly (a file watcher such as nodemon does this). Run both commands again straight after the failure, or use the single PowerShell pipeline in this guide. If the port keeps failing and nothing is ever listed, read the troubleshooting guide on ports that are in use with no process listed.

Can I just use a different port?

Yes, and it is usually the best fix. Pick a port above 1024 that is not inside the dynamic range (49152 to 65535 by default) and not inside an excluded range, and set it through your server's PORT variable or --port option so the choice is recorded in the project.

Is a server listening on 0.0.0.0 reachable from other computers?

Potentially. Windows Defender Firewall decides, and the first time a program listens on a non-loopback address Windows normally asks whether to allow it on private or public networks. If you only need local access, bind to 127.0.0.1 instead and the question never arises.