Error message
[SSL: UNEXPECTED_EOF_WHILE_READING] EOF occurred in violation of protocol
Also printed as
- ssl.SSLEOFError: EOF occurred in violation of protocol
With OpenSSL 3, Python shows the reason code "[SSL: UNEXPECTED_EOF_WHILE_READING]"; with OpenSSL 1.1.1 the text is just "EOF occurred in violation of protocol". A source location such as "(_ssl.c:1082)" follows.
Python ssl module (OpenSSL) — ssl.SSLEOFError, SSL_R_UNEXPECTED_EOF_WHILE_READING
What it means
The other side closed the TCP connection while Python was still in the TLS handshake (or in the middle of reading data), without sending a TLS alert or close_notify. OpenSSL treats that silent hang-up as a protocol violation. Python cannot know why the peer left; the reason is on the server, a proxy or a firewall in between.
Why it happens
The server drops handshakes it does not like
commonSome servers and load balancers close the connection instead of sending an alert when the ClientHello lacks SNI, offers no acceptable version or cipher, or the name is not configured.
A proxy, firewall or VPN cuts the connection
commonWrong proxy settings (HTTPS_PROXY pointing at a TLS proxy port, missing NO_PROXY for internal hosts), deep packet inspection that blocks the destination, or VPN clients often end the TCP connection silently.
Rate limiting or bot protection
occasionalAPIs and CDNs under load, or anti-bot systems that dislike Python's TLS fingerprint, may reset connections instead of returning an HTTP error.
The server closed the connection mid-response
occasionalWhen raised while reading a response, the server or a proxy terminated the connection without close_notify, for example after a timeout or a worker crash.
How to fix it
- 1.
Reproduce the handshake with openssl s_client
If s_client also gets disconnected, vary SNI and the TLS version to see what the server objects to; if s_client works, compare its settings with your Python client (proxy, SNI, versions).
bash # Does a plain OpenSSL handshake work from the same machine? openssl s_client -connect api.example.com:443 -servername api.example.com -brief </dev/null # Without SNI, and pinned to TLS 1.2, to see what the server objects to openssl s_client -connect api.example.com:443 -noservername -brief </dev/null openssl s_client -connect api.example.com:443 -servername api.example.com -tls1_2 -brief </dev/null - 2.
Check proxy environment variables
requests, urllib and pip honour HTTPS_PROXY and NO_PROXY. Fix the proxy URL scheme and exclude internal hosts that must be reached directly.
bash env | grep -i -E '^(https?|no|all)_proxy=' # Proxy URLs should normally be http:// (CONNECT tunnel), and internal hosts listed in NO_PROXY export HTTPS_PROXY=http://proxy.example.net:3128 export NO_PROXY=localhost,127.0.0.1,.internal.example.com - 3.
Retry when the cause is transient
For rate limiting and flaky networks, retries with backoff turn sporadic resets into slower successes; they do not fix a server that always refuses the handshake.
python import requests from requests.adapters import HTTPAdapter from urllib3.util.retry import Retry session = requests.Session() session.mount("https://", HTTPAdapter(max_retries=Retry(total=3, backoff_factor=1))) session.get("https://api.example.com/")
Related errors
[SSL: WRONG_VERSION_NUMBER] wrong version numberPython ssl module (OpenSSL)curl: (56) OpenSSL SSL_read: error:0A000126:SSL routines::unexpected eof while…curl (OpenSSL 3 backend)error:0A000126:SSL routines::unexpected eof while readingOpenSSL 3Client network socket disconnected before secure TLS connection was establishedNode.js tls / https / fetch