Whether you're a developer running into the dreaded "Port already in use" error or just trying to figure out why your app won't start, knowing how to identify and terminate a process occupying a port is an essential skill. In this guide, we'll walk through exactly how to do that — on both Windows (PowerShell) and Linux/macOS (Bash).
The problem
You fire up your dev server and get hit with something like:
Error: listen EADDRINUSE: address already in use :::3000
This means another process is already listening on port 3000. It could be a previous server you forgot to stop, a background service, or anything in between. Let's track it down and shut it up.
Windows — using PowerShell
Step 1: Find what's using the port
netstat -ano | Select-String ":3000"
What this does:
netstat -ano— lists all active TCP/UDP connections and listening ports. The flags mean: a = all connections, n = show addresses as numbers (no DNS resolution), o = show the owning process ID (PID).| Select-String ":3000"— pipes the output and filters lines that contain:3000, so you only see the relevant entry.
Example output:
TCP 0.0.0.0:3000 0.0.0.0:0 LISTENING 9672
The last number — 9672 in this case — is the PID (Process ID). That's the process hogging your port.
Step 2: Identify the process
Now that you have the PID, let's find out which program it belongs to.
tasklist /FI "PID eq 9672"
What this does:
tasklist— displays all currently running processes./FI "PID eq 9672"— applies a filter (/FI) to show only the process whose PID equals9672.
Example output:
Image Name PID Session Name Session# Mem Usage
========= ==== ============ ======== =========
node.exe 9672 Console 1 152,084 K
Now you know it's a node.exe process — likely a stray Next.js or Express dev server.
Alternatively, use PowerShell's native cmdlet for more detail:
Get-Process -Id 9672
This gives you the process name, CPU usage, memory, and more in a clean table format.
Step 3: Kill the process
Once you've confirmed which process to terminate:
taskkill /PID 9672 /F
What this does:
taskkill— the Windows command to terminate processes./PID 9672— targets the process with this specific PID./F— stands for Force. Without it,taskkillsends a polite termination request that the process can ignore. With/F, it's non-negotiable — the process is killed immediately.
Example output:
SUCCESS: The process with PID 9672 has been terminated.
Bonus: kill all instances of a process by name
If you want to kill every running Node.js process at once (useful when you have multiple stale servers):
taskkill /IM node.exe /F
/IMstands for Image Name — it matches by the executable name rather than a specific PID.
Warning: This kills all
node.exeprocesses, not just the one on port 3000. Use with care if other Node apps are running.
One-liner: find and kill in a single command
If you just want to get it done fast without looking up the PID manually:
$pid = (netstat -ano | Select-String ":3000 ").ToString().Trim().Split()[-1]; taskkill /PID $pid /F
What this does: runs netstat, filters for port 3000, extracts just the PID from the last column, then immediately kills it — all in one go.
Linux / macOS — using Bash
Step 1: Find what's using the port
lsof -i :3000
What this does:
lsofstands for List Open Files — in Unix, everything is a file, including network sockets.-i :3000— filters for any file (socket) associated with port3000.
Example output:
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
node 4821 hiren 22u IPv6 0x... 0t0 TCP *:3000 (LISTEN)
You can see the command (node), the PID (4821), the user running it, and the port it's listening on.
Alternatively, you can use:
ss -tulnp | grep :3000
What this does: ss is a modern replacement for netstat, used to investigate socket statistics. -t = TCP sockets, -u = UDP sockets, -l = listening sockets, -n = show port numbers (not service names), -p = show the process using the socket.
Or the classic:
netstat -tulnp | grep :3000
Same idea as ss, just using the older netstat tool (may need to install net-tools on some distros).
Step 2: Identify the process (optional)
If you want more details about a process by PID:
ps -p 4821 -o pid,comm,args
What this does: ps reports a snapshot of current processes. -p 4821 targets the specific PID, and -o pid,comm,args formats the output to show the PID, command name, and full command-line arguments — great for knowing exactly what command started the process.
Step 3: Kill the process
kill 4821
kill sends a signal to a process. By default it sends SIGTERM (signal 15) — a polite request for the process to clean up and shut down gracefully.
If the process doesn't respond to SIGTERM (stubborn process!), force it:
kill -9 4821
-9 sends SIGKILL — this signal cannot be caught or ignored by the process. The OS forcibly terminates it immediately. Use this as a last resort since it doesn't allow the process to clean up.
One-liner: find and kill in a single command
kill -9 $(lsof -t -i :3000)
lsof -t -i :3000 — the -t flag makes lsof output only the PID (no headers or extra columns), perfect for piping into kill -9 via command substitution.
Or using fuser (another handy tool):
fuser -k 3000/tcp
fuser identifies processes using a file or socket, -k tells it to kill those processes immediately, and 3000/tcp targets TCP port 3000. Clean and minimal — one command, no PID lookup needed.
Quick reference cheat sheet
Windows (PowerShell)
| Goal | Command |
|---|---|
| Find PID using a port | netstat -ano | Select-String ":3000" |
| Get process name by PID | tasklist /FI "PID eq 9672" |
| Get process details (PowerShell) | Get-Process -Id 9672 |
| Kill process by PID | taskkill /PID 9672 /F |
| Kill all by process name | taskkill /IM node.exe /F |
| Find and kill in one line | $pid = (netstat -ano | Select-String ":3000 ").ToString().Trim().Split()[-1]; taskkill /PID $pid /F |
Linux / macOS (Bash)
| Goal | Command |
|---|---|
| Find PID using a port | lsof -i :3000 |
| Find PID (minimal output) | lsof -t -i :3000 |
| Find PID (using ss) | ss -tulnp | grep :3000 |
| Get process details | ps -p 4821 -o pid,comm,args |
| Kill gracefully (SIGTERM) | kill 4821 |
| Kill forcefully (SIGKILL) | kill -9 4821 |
| Find and kill in one line | kill -9 $(lsof -t -i :3000) |
| Kill port directly | fuser -k 3000/tcp |
Summary
Ports being occupied by stale processes is a common headache in development. The fix is always the same three-step process: find the port → identify the PID → kill the process. Whether you're on Windows or Linux/macOS, the tools are slightly different but the workflow is identical.
Bookmark this guide and you'll never be stuck staring at an EADDRINUSE error again.