If you're using QNetworkAccessManager in PySide2 to make network requests, you might find that HTTP requests work perfectly, but HTTPS requests fail with this error:
Error occurred: PySide2.QtNetwork.QNetworkReply.NetworkError.UnknownNetworkError: TLS initialization failed
The frustrating part is that this only happens with PySide2 on Windows. The same code works on macOS with PySide2, and it works everywhere with PyQt5. So what's going on?
The cause: Missing OpenSSL libraries
Qt uses OpenSSL to handle TLS/SSL connections (the "S" in HTTPS). On macOS, Qt can use the system's built-in Secure Transport framework, so OpenSSL isn't strictly required. On Windows, however, Qt needs OpenSSL DLL files to be available at runtime.
PyQt5 bundles the necessary OpenSSL DLLs in its installation, which is why HTTPS works out of the box. PySide2, unfortunately, does not always include these DLLs — meaning your application can't establish secure connections.
You can confirm this is the problem by checking whether SSL is available in your Python environment:
from PySide2.QtNetwork import QSslSocket
print("SSL enabled:", QSslSocket.supportsSsl())
print("SSL library build version:", QSslSocket.sslLibraryBuildVersionString())
print("SSL library runtime version:", QSslSocket.sslLibraryVersionString())
If supportsSsl() returns False, that confirms the OpenSSL libraries are missing.
Solution 1: Install OpenSSL for Windows
The most reliable fix is to install the OpenSSL libraries so that Qt can find them.
-
Download the OpenSSL installer for Windows from slproweb.com/products/Win32OpenSSL.html. Choose the version that matches your Python architecture — if you're running 64-bit Python, download the Win64 version. The "Light" version is sufficient.
-
Run the installer. When asked where to copy the OpenSSL DLLs, select "The OpenSSL binaries (/bin) directory".
Create GUI Applications with Python & Qt5 by Martin Fitzpatrick — (PyQt5 Edition) The hands-on guide to making apps with Python — Save time and build better with this book. Over 15K copies sold.
-
Add the OpenSSL
bindirectory to your systemPATH. By default this is something likeC:\Program Files\OpenSSL-Win64\bin.
After doing this, restart your terminal or IDE and run the SSL check above again. supportsSsl() should now return True, and your HTTPS requests will work.
Solution 2: Copy the DLLs manually
If you'd rather not install OpenSSL system-wide, you can copy just the two required DLL files into a location where Python can find them.
The files you need are:
libssl-1_1-x64.dlllibcrypto-1_1-x64.dll
(For 32-bit Python, the filenames won't have the -x64 suffix.)
You can get these from an OpenSSL installation, or from the PyQt5 package directory if you have it installed. Copy them into one of these locations:
- Your project directory (where your script is)
- Your Python installation directory (next to
python.exe) - Any directory that's on your system
PATH
Solution 3: Set the path in your script
You can also point Python to the DLLs at runtime by adding their directory to PATH before importing PySide2:
import os
os.environ['PATH'] = r'C:\Program Files\OpenSSL-Win64\bin' + os.pathsep + os.environ['PATH']
from PySide2 import QtNetwork
from PySide2 import QtCore
This approach is useful during development, but for distributing your application you'll want the DLLs bundled alongside your code instead.
Complete working example
Here's the original code with an SSL check added at the top, so you can verify your setup before making the request:
import sys
import os
# Uncomment and adjust the next line if you need to point to OpenSSL manually:
# os.environ['PATH'] = r'C:\Program Files\OpenSSL-Win64\bin' + os.pathsep + os.environ['PATH']
from PySide2 import QtNetwork
from PySide2 import QtCore
def check_ssl():
"""Print SSL support status for debugging."""
print("SSL supported:", QtNetwork.QSslSocket.supportsSsl())
print(
"SSL build version:",
QtNetwork.QSslSocket.sslLibraryBuildVersionString(),
)
print(
"SSL runtime version:",
QtNetwork.QSslSocket.sslLibraryVersionString(),
)
return QtNetwork.QSslSocket.supportsSsl()
class Example:
def __init__(self):
self.nam = QtNetwork.QNetworkAccessManager()
self.nam.finished.connect(self.handle_response)
def do_request(self):
url = "https://httpbin.org/get"
req = QtNetwork.QNetworkRequest(QtCore.QUrl(url))
self.nam.get(req)
def handle_response(self, reply):
er = reply.error()
if er == QtNetwork.QNetworkReply.NoError:
bytes_string = reply.readAll()
print(str(bytes_string, "utf-8"))
else:
print(f"Error occurred: {er}")
print(f"Error string: {reply.errorString()}")
QtCore.QCoreApplication.quit()
def main():
app = QtCore.QCoreApplication([])
if not check_ssl():
print(
"\nSSL is not available. HTTPS requests will fail."
"\nInstall OpenSSL or copy the required DLLs into your PATH."
)
sys.exit(1)
ex = Example()
ex.do_request()
sys.exit(app.exec_())
if __name__ == "__main__":
main()
With OpenSSL available, running this should print the JSON response from httpbin.org successfully.
Which OpenSSL version do you need?
Qt 5.12.4 and later (including Qt 5.15, which PySide2 5.15 uses) are typically built against OpenSSL 1.1.x. If you install a 3.x version of OpenSSL and it still doesn't work, try the 1.1.1 series instead. The sslLibraryBuildVersionString() output from the check above will tell you exactly which version Qt expects.
Why does PyQt5 work without this?
PyQt5's Windows wheels on PyPI include the OpenSSL DLLs as part of the package. When you pip install PyQt5, the DLLs are placed where Qt can find them automatically. PySide2's packaging doesn't consistently do this, which is why you need to provide them yourself. This is a packaging difference rather than a code difference — the underlying Qt framework is the same.
If you're choosing between PySide2 and PyQt5 for a project that needs HTTPS, be aware of this extra setup step on Windows with PySide2. Once the OpenSSL libraries are in place, both work identically.