Quick answer
What does SSL: WRONG_VERSION_NUMBER mean with a proxy?
[SSL: WRONG_VERSION_NUMBER] through a proxy almost always means your client started a TLS handshake with something that answered in plain text. The usual cause is an https:// proxy URL pointing at a plain HTTP proxy port. With CrawlRelay, write http:// in front of the gateway address for both HTTP and HTTPS targets; the site's own HTTPS still works through the tunnel.
SSL: WRONG_VERSION_NUMBER at a glance
| Error | SSL: WRONG_VERSION_NUMBER |
|---|---|
| Type | TLS error in the client |
| Sent by | Your TLS library, when the other side does not speak TLS |
| Defined in | TLS 1.3: RFC 8446; HTTP proxy CONNECT: RFC 9110, section 9.3.6 |
| Retry it? | No. It is a configuration error |
| First check | Look at the scheme in front of your proxy URL |
What does SSL: WRONG_VERSION_NUMBER mean?
TLS starts with a handshake record. If the bytes that come back are an HTTP response instead, the TLS library reads a nonsense version number and stops. Python reports WRONG_VERSION_NUMBER; the exact wording varies with the OpenSSL version and the client.
The proxy URL scheme decides how your client talks to the proxy. http:// means plain HTTP to the proxy, followed by a CONNECT tunnel and TLS with the website. https:// means TLS with the proxy itself, which only works if the proxy port expects TLS.
What does SSL: WRONG_VERSION_NUMBER look like in Python, curl, Node.js and browsers?
The same failure prints differently in every tool. These are the messages to search your logs for:
- Python requests / urllib3 2.x:
SSLError(SSLError(1, '[SSL: WRONG_VERSION_NUMBER] wrong version number'))wrapped in aProxyError - httpx:
httpx.ConnectError: [SSL: WRONG_VERSION_NUMBER] wrong version number - curl:
curl: (35) ... wrong version numberwhen you write-x https://for a plain proxy - Node.js:
EPROTO ... wrong version numberin the error message
What causes SSL: WRONG_VERSION_NUMBER?
Most likely first:
https://in front of the proxy address on a port that speaks plain HTTP. This is the most common case.- Copy-pasted settings from a provider whose proxy port does expect TLS.
https://on a URL with port 80, orhttp://on a site port that expects TLS, outside any proxy.- An environment variable such as
HTTPS_PROXY=https://...that your code inherits.
How do I diagnose SSL: WRONG_VERSION_NUMBER step by step?
- Print the proxy URL your code uses and check its scheme.
- Check the environment for
HTTPS_PROXYandALL_PROXY. - Run the curl test below with
-x http://and confirm it works. - If curl works and your code does not, your code or environment still uses
https://.
# Use the URL that fails; with https://api.ipify.org instead, you test the gateway alone.
# "HTTP/1.1 200 Connection established" first, then the site's own status: the site answered.
curl -v -x http://USERNAME:[email protected]:7777 https://TARGET_URL
# Same test through the SOCKS5 port, with DNS resolved at the exit
curl -v --socks5-hostname gw.crawlrelay.com:7778 --proxy-user USERNAME:PASSWORD https://TARGET_URLHow do I fix SSL: WRONG_VERSION_NUMBER?
- Use
http://for the proxy URL in every key:{"http": "http://...", "https": "http://..."}. - Leave TLS verification on. The fix is the scheme, not
verify=False. - Fix the environment variable instead of overriding it in one script.
Should I retry after SSL: WRONG_VERSION_NUMBER?
Never retry this error: every attempt fails the same way. It is a one-character configuration fix.
How does SSL: WRONG_VERSION_NUMBER apply to CrawlRelay?
CrawlRelay's HTTP port is a plain HTTP proxy port that carries HTTPS sites through CONNECT tunnels. TLS runs end to end between your client and the website inside the tunnel, so the gateway never needs an https:// proxy URL.
Gateway: gw.crawlrelay.com, port 7777 (HTTP, HTTPS through CONNECT) and port 7778 (SOCKS5). Username format: USERNAME-country-{cc}-state-{state}-city-{city}-zip-{zip}-asn-{asn}-session-{id}-ttl-{minutes}. Related: SSL certificate verify failed · Cannot connect to proxy · Python guide.
SSL: WRONG_VERSION_NUMBER: questions developers ask
Is my traffic unencrypted if I use an http:// proxy URL?
Not for HTTPS websites. The http:// scheme only covers the short CONNECT exchange with the proxy, which includes your proxy credentials. After that, your client runs TLS directly with the website inside the tunnel, and the proxy only forwards encrypted bytes. Plain http:// websites are unencrypted with or without a proxy.
Why did this start after upgrading urllib3?
urllib3 2.x supports HTTPS proxies, so it takes an https:// proxy URL literally and starts TLS with the proxy. Older setups sometimes worked by accident with the wrong scheme. Write http:// for plain HTTP proxy ports and the error goes away.
Should I set verify=False to make the error go away?
No. Turning off certificate checks does not fix a wrong scheme, and it exposes you to interception on every request. Fix the proxy URL scheme. Keep verification on in production.
Other proxy errors in this reference
HTTP status codes
- 401 Unauthorized vs 407
- 403 Forbidden
- 407 Proxy Authentication Required
- 429 Too Many Requests
- 502 Bad Gateway
- 503 Service Unavailable
- 504 Gateway Timeout
Browser and client errors
Connection and TLS errors
Residential proxies with docs that cover the failure cases
CrawlRelay residential proxies from $0.50/GB, traffic that never expires.