I need to set timeout on python's socket recv method. How to do it?
11 Answers
The typical approach is to use select() to wait until data is available or until the timeout occurs. Only call recv()
when data is actually available. To be safe, we also set the socket to non-blocking mode to guarantee that recv()
will never block indefinitely. select()
can also be used to wait on more than one socket at a time.
import select
mysocket.setblocking(0)
ready = select.select([mysocket], [], [], timeout_in_seconds)
if ready[0]:
data = mysocket.recv(4096)
If you have a lot of open file descriptors, poll() is a more efficient alternative to select()
.
Another option is to set a timeout for all operations on the socket using socket.settimeout()
, but I see that you've explicitly rejected that solution in another answer.

- 26,309
- 7
- 59
- 69

- 74,198
- 17
- 88
- 77
-
22use `select` is good, but the part where you say "you can't" is misleading, since there is `socket.settimeout()`. – nosklo Apr 28 '10 at 16:41
-
9One caution on using `select` -- if you're running on a Windows machine, `select` relies on the WinSock library, which has a habit of returning as soon as *some* data has arrived, but not necessarily *all* of it. So you need to incorporate a loop to keep calling `select.select()` until all the data is received. How you know you've gotten all the data is (unfortunately) up to you to figure out -- it may mean looking for a terminator string, a certain number of bytes, or just waiting for a defined timeout. – JDM Jan 24 '13 at 19:07
-
8Why is it necessary to set the socket no non-blocking? I don't think that matters to the select call (and it blocks until a descriptor can be read or the timeout expires in this case) and the recv() won't block if the select is satisfied. I tried it using recvfrom() and it seems to work correctly without setblocking(0). – HankB Nov 30 '15 at 03:45
-
1Would `ready[0]` only be false if there's no body in the server's response? – matanster Jul 19 '18 at 19:24
-
1Since Python 3.4 `selectors` is a high-level alternative to `select`. – Jarek Przygódzki May 09 '19 at 11:41
-
I used this in python3.10 and the result was a little counter-intuitive for me: select returned and was evalled to True even if there was no data in socket buffer, so so.recv() hanged, so this is a little different than a timeout for me since it raises no exception and is not evalled to False. Anyway it helps a lot. – Marco Montevechi Filho Jan 09 '23 at 12:28
-
@JOM That's what it's supposed to do. Neither `select()` nor Winsock nor TCP has any concept of 'all of it'. The socket becomes readable when *any* data arrives. – user207421 Jun 29 '23 at 00:35
there's socket.settimeout()
-
23It doesn't timeout the recv (at least when I tried it). Only the accept() is timed out. – Oren S Jun 01 '11 at 11:40
-
9The socket.recv() seems to time out for me just fine after setting socket.settimeout(), exactly as intended. Am I making this up? Can anyone else confirm this? – Aeonaut Oct 23 '11 at 03:20
-
3@Aeonaut I think that this times out recv() most of the time, but there is a race condition. In socket.recv() Python (2.6) calls select/poll internally with the timeout and then recv() is called right after. So if you use a blocking socket and between these 2 calls the other end point crashes, you can end up hanging indefinitely on the recv(). If you use non-blocking socket, python doesn't call select.select internally, so I think Daniel Stutzbach's answer is the correct way. – emil.p.stanchev Aug 04 '12 at 08:51
-
4Actually, I probably misunderstood when select() returns, so please scratch the previous comment. Beej's Guide says the above is a valid way to implement a timeout on recv: http://beej.us/guide/bgnet/output/html/singlepage/bgnet.html#indexId434909-198 so I'll trust is an authorative source. – emil.p.stanchev Aug 04 '12 at 09:42
-
3i'm not sure why the solution that uses `select` is preferred when this solution is a one liner (easier to maintain, less risk in implementing wrong) and uses select under the hood (implementation is the same as the @DanielStuzbach answer). – Trevor Boyd Smith Nov 21 '17 at 16:26
-
As mentioned both select.select()
and socket.settimeout()
will work.
Note you might need to call settimeout
twice for your needs, e.g.
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind(("",0))
sock.listen(1)
# accept can throw socket.timeout
sock.settimeout(5.0)
conn, addr = sock.accept()
# recv can throw socket.timeout
conn.settimeout(5.0)
conn.recv(1024)

- 343
- 2
- 11

- 11,864
- 10
- 72
- 89
-
3I think he is getting in the same thing I am where no matter how you poke and prod this function it hangs. I've tried 2 or 4 timeouts now and it still hangs. settimeout hangs as well. – Cate Daniel Sep 30 '14 at 22:19
-
5As you call `.settimeout()` more than once you could call the `setdefaulttimeout()` method in first place. – mvarge Nov 17 '16 at 21:40
-
I found it necessary to call .settimeout(), right before .accept()/.recv() otherwise the time out doesn't always work. – Ben Jun 18 '23 at 05:55
You could set timeout before receiving the response and after having received the response set it back to None:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.settimeout(5.0)
data = sock.recv(1024)
sock.settimeout(None)

- 181
- 1
- 2
The timeout that you are looking for is the connection socket's timeout not the primary socket's, if you implement the server side. In other words, there is another timeout for the connection socket object, which is the output of socket.accept()
method. Therefore:
sock.listen(1)
connection, client_address = sock.accept()
connection.settimeout(5) # This is the one that affects recv() method.
connection.gettimeout() # This should result 5
sock.gettimeout() # This outputs None when not set previously, if I remember correctly.
If you implement the client side, it would be simple.
sock.connect(server_address)
sock.settimeout(3)

- 142
- 1
- 2
- 9
Got a bit confused from the top answers so I've wrote a small gist with examples for better understanding.
Option #1 - socket.settimeout()
Will raise an exception in case the sock.recv()
waits for more than the defined timeout.
import socket
sock = socket.create_connection(('neverssl.com', 80))
timeout_seconds = 2
sock.settimeout(timeout_seconds)
sock.send(b'GET / HTTP/1.1\r\nHost: neverssl.com\r\n\r\n')
data = sock.recv(4096)
data = sock.recv(4096) # <- will raise a socket.timeout exception here
Option #2 - select.select()
Waits until data is sent until the timeout is reached. I've tweaked Daniel's answer so it will raise an exception
import select
import socket
def recv_timeout(sock, bytes_to_read, timeout_seconds):
sock.setblocking(0)
ready = select.select([sock], [], [], timeout_seconds)
if ready[0]:
return sock.recv(bytes_to_read)
raise socket.timeout()
sock = socket.create_connection(('neverssl.com', 80))
timeout_seconds = 2
sock.send(b'GET / HTTP/1.1\r\nHost: neverssl.com\r\n\r\n')
data = recv_timeout(sock, 4096, timeout_seconds)
data = recv_timeout(sock, 4096, timeout_seconds) # <- will raise a socket.timeout exception here

- 32,361
- 10
- 130
- 129
try this it uses the underlying C.
timeval = struct.pack('ll', 2, 100)
s.setsockopt(socket.SOL_SOCKET, socket.SO_RCVTIMEO, timeval)

- 56,346
- 20
- 107
- 159

- 71
- 1
- 5
-
This is great, as it allows one to set different values for send and recv timeout using `SO_RCVTIMEO` and `SO_SNDTIMEO`. – jtpereyda Jun 30 '18 at 20:59
-
-
```timeval = struct.pack('ll', sec, usec)``` ```s.setsockopt(socket.SOL_SOCKET, socket.SO_RCVTIMEO, timeval)``` usec = 10000 means 10 ms – Tavy Mar 02 '19 at 19:55
-
This won't work on Windows, as the parameter is a DWORD (64-bit) https://learn.microsoft.com/en-us/windows/win32/winsock/sol-socket-socket-options – Cherona Jul 03 '21 at 05:57
You can use socket.settimeout()
which accepts a integer argument representing number of seconds. For example, socket.settimeout(1)
will set the timeout to 1 second

- 439
- 5
- 18
As mentioned in previous replies, you can use something like: .settimeout()
For example:
import socket
s = socket.socket()
s.settimeout(1) # Sets the socket to timeout after 1 second of no activity
host, port = "somehost", 4444
s.connect((host, port))
s.send("Hello World!\r\n")
try:
rec = s.recv(100) # try to receive 100 bytes
except socket.timeout: # fail after 1 second of no activity
print("Didn't receive data! [Timeout]")
finally:
s.close()
I hope this helps!!

- 334
- 3
- 10
#! /usr/bin/python3.6
# -*- coding: utf-8 -*-
import socket
import time
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
s.settimeout(5)
PORT = 10801
s.bind(('', PORT))
print('Listening for broadcast at ', s.getsockname())
BUFFER_SIZE = 4096
while True:
try:
data, address = s.recvfrom(BUFFER_SIZE)
except socket.timeout:
print("Didn't receive data! [Timeout 5s]")
continue

- 31
- 2
Shout out to: https://boltons.readthedocs.io/en/latest/socketutils.html
It provides a buffered socket, this provides a lot of very useful functionality such as:
.recv_until() #recv until occurrence of bytes
.recv_closed() #recv until close
.peek() #peek at buffer but don't pop values
.settimeout() #configure timeout (including recv timeout)

- 21
- 1