How to Find an Available Port on Linux, macOS, and Windows
TLDR: Use lsof -i :PORT on Linux/macOS or netstat -ano | findstr :PORT on Windows to check if a specific port is in use. For finding any available port programmatically, bind to port 0 and let the OS assign one. Tools like ss, netstat, and language-specific libraries make this straightforward.
When you're developing network applications, you often need to find a free port to bind your service to. Maybe you're running multiple development servers, setting up a test environment, or debugging a "port already in use" error. Here's how to check port availability and find open ports across different platforms and scenarios.
Checking If a Specific Port Is Available
The quickest way to check if a port is free depends on your operating system.
On Linux
The ss command is the modern replacement for netstat and shows socket statistics:
# Check if port 8080 is in use
ss -tuln | grep :8080
# -t: Show TCP sockets
# -u: Show UDP sockets
# -l: Show listening sockets
# -n: Show numerical addresses (don't resolve names)
If the command returns nothing, the port is available. If you see output, the port is occupied:
tcp LISTEN 0 128 *:8080 *:*
For more detailed information about what's using the port, use lsof:
# Find what process is using port 8080
sudo lsof -i :8080
# Output shows:
# COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
# node 12345 john 21u IPv4 98765 0t0 TCP *:8080 (LISTEN)
The lsof output tells you the process name (node), process ID (12345), and user (john) that's using the port.
On macOS
macOS uses the same tools as Linux:
# Check if port 3000 is in use
lsof -i :3000
# Or use netstat (older but still available)
netstat -an | grep LISTEN | grep 3000
If you want to see the process name without using sudo:
# This works without sudo but shows less detail
lsof -i :3000 | grep LISTEN
On Windows
Windows uses netstat with different flags:
REM Check if port 8080 is in use
netstat -ano | findstr :8080
REM -a: Show all connections
REM -n: Show numerical addresses
REM -o: Show process ID (PID)
The output looks like:
TCP 0.0.0.0:8080 0.0.0.0:0 LISTENING 5432
The last number (5432) is the process ID. To find out what program that is:
tasklist /FI "PID eq 5432"
Or use PowerShell for a cleaner output:
Get-NetTCPConnection -LocalPort 8080 | Select-Object LocalAddress,LocalPort,State,OwningProcess
# To see the process name:
Get-Process -Id (Get-NetTCPConnection -LocalPort 8080).OwningProcess
Finding Any Available Port
Instead of checking ports one by one, you can let the operating system assign an available port.
Using Port 0 in Applications
When you bind to port 0, the OS automatically allocates an available port. This is the most reliable method:
import socket
def find_available_port():
"""
Bind to port 0 to let the OS assign an available port.
Returns the port number.
"""
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# Bind to port 0 - OS will choose an available port
sock.bind(('', 0))
# Get the port number that was assigned
port = sock.getsockname()[1]
sock.close()
return port
port = find_available_port()
print(f"Available port: {port}")
# Output: Available port: 54321 (or some other high-numbered port)
The OS typically assigns ports from the ephemeral port range (usually 32768-60999 on Linux, 49152-65535 on Windows).
In Node.js
Node.js makes this even simpler:
const net = require('net');
function findAvailablePort() {
return new Promise((resolve, reject) => {
const server = net.createServer();
// Listen on port 0 to get an OS-assigned port
server.listen(0, () => {
const port = server.address().port;
server.close(() => resolve(port));
});
server.on('error', reject);
});
}
// Usage
findAvailablePort().then(port => {
console.log(`Available port: ${port}`);
// Now start your actual server on this port
const app = require('express')();
app.listen(port, () => {
console.log(`Server running on port ${port}`);
});
});
Many Node.js frameworks have this built in. For example, with Express:
const express = require('express');
const app = express();
// Listen on port 0, then log what port was assigned
const server = app.listen(0, () => {
const port = server.address().port;
console.log(`Server started on port ${port}`);
});
Finding a Range of Available Ports
Sometimes you need multiple ports or want to find ports in a specific range:
import socket
def find_available_ports(start, end, count=1):
"""
Find available ports in the specified range.
Returns a list of available port numbers.
"""
available = []
for port in range(start, end + 1):
if len(available) >= count:
break
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
# Try to bind to the port
sock.bind(('', port))
available.append(port)
sock.close()
except OSError:
# Port is in use, try next one
continue
return available
# Find 3 available ports between 8000 and 9000
ports = find_available_ports(8000, 9000, count=3)
print(f"Available ports: {ports}")
# Output: Available ports: [8000, 8001, 8002]
Keep in mind there's a race condition here - another process could grab the port between when you check it and when you actually use it. For production code, handle binding errors gracefully.
Checking Ports from the Command Line
If you want a quick way to see all listening ports and what's using them:
Linux and macOS
# Show all listening TCP ports with process names
sudo netstat -tulpn | grep LISTEN
# Or with ss (faster and more modern)
sudo ss -tulpn | grep LISTEN
# Just show the ports that are in use (no process info)
ss -tuln | awk '{print $5}' | cut -d: -f2 | sort -n | uniq
The last command gives you a clean list of port numbers:
22
80
443
3000
8080
Windows PowerShell
# Get all listening TCP ports with process names
Get-NetTCPConnection -State Listen |
Select-Object LocalPort,OwningProcess,
@{Name="ProcessName";Expression={(Get-Process -Id $_.OwningProcess).Name}} |
Sort-Object LocalPort |
Format-Table
# Output:
# LocalPort OwningProcess ProcessName
# --------- ------------- -----------
# 80 1234 nginx
# 443 1234 nginx
# 3000 5678 node
# 8080 9012 java
Finding Available Ports in Docker Containers
When working with Docker, you might want to find available ports on the host to map to container ports:
# Find an available port on the host
PORT=$(python3 -c 'import socket; s=socket.socket(); s.bind(("", 0)); print(s.getsockname()[1]); s.close()')
# Use it in docker run
docker run -p $PORT:80 nginx
echo "Container accessible at http://localhost:$PORT"
Or let Docker choose the port:
# Map container port 80 to a random host port
docker run -p 80 nginx
# Find out what port Docker chose
docker ps --format "{{.Ports}}"
# Output: 0.0.0.0:54321->80/tcp
Common Port Ranges
Understanding standard port ranges helps you choose appropriate ports:
Well-Known Ports: 0 - 1023 (require root/admin)
├─ SSH: 22
├─ HTTP: 80
├─ HTTPS: 443
└─ PostgreSQL: 5432
Registered Ports: 1024 - 49151 (no special privileges)
├─ MySQL: 3306
├─ Redis: 6379
├─ MongoDB: 27017
└─ Your apps: 8000-9000 (common dev range)
Dynamic/Ephemeral: 49152 - 65535 (OS-assigned)
└─ Used for: Temporary connections, port 0 binding
For development, ports 8000-8999 are commonly used and rarely conflict with system services. Avoid ports below 1024 unless you need them specifically, as they require elevated privileges to bind.
Handling Port Conflicts in Development
If you frequently run into port conflicts during development, here are some strategies:
#!/bin/bash
# dev-server.sh - Start server on next available port
BASE_PORT=8000
MAX_PORT=8100
PORT=$BASE_PORT
while [ $PORT -le $MAX_PORT ]; do
# Check if port is available
if ! lsof -i :$PORT >/dev/null 2>&1; then
echo "Starting server on port $PORT"
npm start -- --port $PORT
exit 0
fi
PORT=$((PORT + 1))
done
echo "No available ports in range $BASE_PORT-$MAX_PORT"
exit 1
This script tries ports incrementally until it finds one that's free, then starts your application on that port.
The key to finding available ports is understanding your platform's tools and using port 0 when you need the OS to choose for you. For quick checks, lsof and ss are your friends on Unix systems, while netstat and PowerShell commands work well on Windows.
Found an issue?