I want to get any random open TCP port on localhost in Python. What is the easiest way?
-
4This is like dogs chasing cars - what are you going to do when you get one? – Greg Hewgill May 14 '10 at 23:31
-
1I need a TCP port number for another console application which needs an port as a parameter where it will listen on. – Albert May 14 '10 at 23:48
-
5There is an obvious (albeit minor) race condition with the approach you are contemplating. The port could be taken by the time you pass it the other process. Do you own the other process's code? If so, it might be better to get it to acquire a random port and report it back to the first process. – Marcelo Cantos May 14 '10 at 23:54
-
1Yes exactly, that is what I mean by "not 100% correct". But there will always be this short time span between I get the port and the call of the other process. (And I don't have that code.) – Albert May 14 '10 at 23:57
5 Answers
My current solution:
def get_open_port():
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(("",0))
s.listen(1)
port = s.getsockname()[1]
s.close()
return port
Not very nice and also not 100% correct but it works for now.

- 65,406
- 61
- 242
- 386
-
14Why the listen() call? For me, s.getsockname()[1] is populated as soon as I call bind() – ncoghlan Oct 28 '11 at 06:12
-
1Does one need to call `s.shutdown()` before `s.close()` in this case? – Jonathan May 13 '16 at 22:17
-
1fwiw, this is the same approach the popular node package `get-port` uses. https://github.com/sindresorhus/get-port/blob/master/index.js – cs01 Aug 15 '19 at 21:35
The free port can be found by binding a socket to a port selected by the operating system. After the operating system selects a port the socket can be disposed. However, this solution is not resistant to race conditions - in the short time between getting the free port number and using this port other process may use this port.
import socket
def find_free_port():
with socket.socket() as s:
s.bind(('', 0)) # Bind to a free port provided by the host.
return s.getsockname()[1] # Return the port number assigned.

- 3,780
- 1
- 31
- 44
I actually use the following in one of my programs:
port = random.randint(10000,60000)
Of course, this is even more prone to collisions than the code you have. But I've never had a problem with it. The point is, at any given time, most of those high-numbered ports are not in use and if you just pick one at random, having a conflict with another process is pretty unlikely. If you do something like the solution you posted in your answer (opening a socket and grabbing its port number), it's almost certain that the port isn't going to conflict. So if this is something that you'll only be using for yourself (as opposed to something you're going to release to the public), think about whether it's worth coming up with a truly bulletproof solution. Odds are it'll never make a difference.
Motivated by Marcelo Cantos' comment on your question, I will add that the standard solution in cases like this is to have the process that will be using the port bind to it and then share that information with any other program that needs it. Typically it'll do something like writing a temporary file containing the port number to some standard location in the filesystem. Since the process you're working with doesn't do that, in some sense whatever solution you come up with will be a bit of a hack. But again, if it's just for your own use, that's probably fine.

- 128,184
- 27
- 255
- 279
The ephemeral ports basically lie in range 49152 - 65535. if you want to check ports in bigger range then just change the values in randint.
import pustil
from random import randint
def getfreeport():
port = randint(49152,65535)
portsinuse=[]
while True:
conns = pstuil.net_connections()
for conn in conns:
portsinuse.append(con.laddr[1])
if port in portsinuse:
port = randint(49152,65535)
else:
break
return port

- 29
- 4
This is my version, however its not really random if you specify a port range. This will also suffer from race conditions, but this is the best way I know if you need to know the port ahead of time.
import socket
import errno
import contextlib
reserved_ports = set()
def get_open_port(lowest_port = 0, highest_port = None, bind_address = '', *socket_args, **socket_kwargs):
if highest_port is None:
highest_port = lowest_port + 100
while lowest_port < highest_port:
if lowest_port not in reserved_ports:
try:
with contextlib.closing(socket.socket(*socket_args, **socket_kwargs)) as my_socket:
my_socket.bind((bind_address, lowest_port))
this_port = my_socket.getsockname()[1]
reserved_ports.add(this_port)
return this_port
except socket.error as error:
if not error.errno == errno.EADDRINUSE:
raise
assert not lowest_port == 0
reserved_ports.add(lowest_port)
lowest_port += 1
raise Exception('Could not find open port')

- 169,610
- 28
- 168
- 175

- 1,646
- 1
- 12
- 18
-
Unfortunately, this is not 100% failproof and may return True when the port is indeed in use by another application. I haven't nailed down why, but .bind() will not always fail when another process is already listening on the port. – Joe Oct 06 '14 at 20:29
-
@Joe is it possible that the other application is bound to a different address but with the same port? or different address family? – Dave Butler Oct 08 '14 at 14:05
-
It's possible. All I know is that in my case, the server application I was trying to launch failed to open the port even though the code above said the port was free. The other application was erl.exe (erlang), which I got through RabbitMQ's setup if you want to try for yourself. – Joe Oct 09 '14 at 20:19
-