Quick answer
Replace 3000 with your port. Try a normal kill first and only escalate to a forced kill if the process ignores it.
# macOS / Linux
lsof -ti :3000 | xargs kill # graceful (SIGTERM)
lsof -ti :3000 | xargs kill -9 # forced (SIGKILL) if it refuses
# Linux alternative
fuser -k 3000/tcp# Windows (cmd or PowerShell)
netstat -ano | findstr :3000
taskkill /PID 12345 /FWhy "address already in use" happens
Only one process can listen on a given TCP port and address at a time. When a second program tries to bind the same port, the operating system rejects it and Node reports EADDRINUSE, Python raises OSError: [Errno 98] Address already in use (errno 48 on macOS), and Java throws BindException. The usual culprits are:
- A previous run of the same dev server that did not exit, for example after closing a terminal tab, a crashed watcher, or a
Ctrl+Z(which suspends the process instead of stopping it). - Another project you forgot was running on the same default port: 3000 for Next.js, Express and Rails, 5173 for Vite, 8080 for many Java and proxy servers, 8000 for Django.
- A Docker container publishing the port, which shows up as
com.docker.backend,docker-proxyorvpnkitrather than your app. - On macOS Monterey and later, AirPlay Receiver (the ControlCenter process) listens on ports 5000 and 7000. Turn it off in System Settings, General, AirDrop and Handoff, or use another port.
- On Windows, Hyper-V and WSL reserve port ranges. That usually shows up as an access-permission error rather than EADDRINUSE; check with
netsh interface ipv4 show excludedportrange protocol=tcp.
macOS: find and kill the process with lsof
lsof (list open files) is installed on every Mac. lsof -i :3000 shows every process with a connection on port 3000, including clients connected to it. To see only the listening server, filter by TCP state; -n and -P skip DNS and port-name lookups so the output is instant and shows numbers.
-t prints PIDs only, which is what you pipe into kill. Plain kill sends SIGTERM, which lets the process close files and connections cleanly. kill -9 sends SIGKILL, which cannot be caught, so use it only when SIGTERM does not work. If the process belongs to another user or to root, prefix the command with sudo.
lsof -i :3000
# COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
# node 48213 ayush 23u IPv6 0x... 0t0 TCP *:hbci (LISTEN)
lsof -nP -iTCP:3000 -sTCP:LISTEN # only the listener, numeric output
kill 48213 # graceful
kill -9 48213 # forced
# One-liners
kill $(lsof -ti :3000)
lsof -ti :3000,8080 | xargs kill # several ports at onceLinux: lsof, ss and fuser
lsof works the same on Linux, though it is not installed on every minimal server or container image. ss from iproute2 is always available on modern distributions and replaces the older netstat. -l shows listening sockets, -t TCP, -n numeric and -p the owning process. Without sudo you only see the process names for sockets you own.
fuser (from psmisc) is the shortest route: fuser 3000/tcp prints the PID and fuser -k 3000/tcp kills it. By default -k sends SIGKILL, so pass -TERM for a graceful stop. If the port belongs to a system service such as nginx or Apache, stop it through its service manager instead (sudo systemctl stop nginx); otherwise systemd may simply restart it.
sudo ss -ltnp 'sport = :8080'
# State Recv-Q Send-Q Local Address:Port Peer Address:Port Process
# LISTEN 0 511 0.0.0.0:8080 0.0.0.0:* users:(("java",pid=2231,fd=9))
sudo ss -ltnp | grep ':8080'
sudo netstat -tulpn | grep ':8080' # older systems (net-tools)
fuser 8080/tcp # print PID
fuser -k -TERM 8080/tcp # graceful kill
sudo fuser -k 8080/tcp # SIGKILL, any owner
sudo lsof -ti :8080 | xargs -r killWindows: netstat, taskkill and PowerShell
On Windows, netstat -ano lists connections with the owning process ID in the last column. Filter it with findstr and look for the line in the LISTENING state, then end that PID with taskkill. /F forces termination; without it Windows asks the program to close, which console apps such as Node often ignore. tasklist /FI "PID eq 12345" tells you what the process is before you kill it. Run the terminal as Administrator if access is denied.
Command Prompt
netstat -ano | findstr :3000
:: TCP 0.0.0.0:3000 0.0.0.0:0 LISTENING 12345
tasklist /FI "PID eq 12345"
taskkill /PID 12345 /F
taskkill /IM node.exe /F :: kill every node.exe (use with care)PowerShell
Get-NetTCPConnection returns objects instead of text, so there is nothing to parse. Filter on -State Listen so you do not pick up PID 0 from connections in the TIME_WAIT state.
Get-NetTCPConnection -LocalPort 3000 -State Listen |
Select-Object LocalAddress, LocalPort, OwningProcess
$procId = (Get-NetTCPConnection -LocalPort 3000 -State Listen).OwningProcess
Get-Process -Id $procId
Stop-Process -Id $procId -ForceCross-platform: npx kill-port
If you work in JavaScript projects across operating systems, the kill-port npm package wraps the platform-specific commands. npx kill-port 3000 downloads it on first use and kills whatever listens on the port, on macOS, Linux and Windows alike. You can pass several ports, and some teams add it to a predev script so the dev server always starts on a free port. It is convenient, but it kills without asking what the process is, so it is best kept to local development.
npx kill-port 3000
npx kill-port 3000 5173 8080{
"scripts": {
"predev": "npx kill-port 3000",
"dev": "next dev"
}
}When the port belongs to Docker
If lsof or netstat shows a Docker process, killing it would take down Docker itself or other containers. Find the container that publishes the port and stop that instead.
On Linux the listener is usually docker-proxy; on macOS and Windows it is the Docker Desktop backend process. In both cases docker ps shows the mapping in its PORTS column, such as 0.0.0.0:3000->3000/tcp. If the container belongs to a Compose project, run docker compose down in that project folder so it does not restart on its own because of a restart: always policy.
docker ps --filter publish=3000
docker stop <container-id>Alternatives to killing the process
Killing is a blunt fix. Before you do it, check what the process is: ending a database, a VPN client or a system service can cause more trouble than a busy port. Often the better solution is to run your app on another port, for example PORT=3001 npm run dev, next dev -p 3001, vite --port 5174 or python manage.py runserver 8001. Next.js and Vite will also offer the next free port automatically.
If your own server restarts too quickly after a crash and fails to bind, the old socket may be in TIME_WAIT. Servers can set the SO_REUSEADDR socket option to bind anyway; most frameworks already do. And if a suspended job is holding the port in your current terminal, jobs lists it and fg brings it back so you can stop it properly with Ctrl+C.
Warning
Avoid kill -9 and taskkill /F on databases and anything that writes files. A forced kill skips clean-up, can corrupt data files and leaves stale lock or PID files that block the next start.
Kill process on port: FAQ
Quick answers to common questions
How do I kill port 3000 on a Mac?
Run lsof -ti :3000 | xargs kill. If the process does not exit, run lsof -ti :3000 | xargs kill -9. Add sudo if the process belongs to another user.
How do I kill the process on port 8080 in Windows?
Run netstat -ano | findstr :8080 to get the PID from the last column, then taskkill /PID <pid> /F. In PowerShell, Stop-Process -Id (Get-NetTCPConnection -LocalPort 8080 -State Listen).OwningProcess -Force does it in one line.
What does EADDRINUSE mean?
It means another process is already listening on the address and port your program tried to use. Find it with lsof -i :PORT or netstat -ano, then stop it or run your app on a different port.
What is the difference between kill and kill -9?
kill sends SIGTERM, which asks the process to shut down cleanly. kill -9 sends SIGKILL, which ends it immediately with no clean-up. Always try plain kill first.
Why does lsof show nothing but the port is still in use?
The process probably belongs to another user or root, so run sudo lsof -i :PORT. It can also be a Docker container (check docker ps) or, on macOS, AirPlay Receiver on ports 5000 and 7000.

