The error cannot set verify_mode to CERT_NONE when check_hostname is enabled happens when Python’s SSL context is told to skip certificate verification while hostname checking is still turned on. Those two settings conflict.
Quick Answer
CERT_NONE means the client will not validate the peer certificate, while check_hostname asks Python to validate the requested hostname. Keep CERT_REQUIRED and hostname checking enabled for real connections; only use an unverified context for a controlled local test.

In a secure TLS connection, Python verifies that the certificate is trusted and that the certificate matches the hostname you requested. If you set verify_mode to ssl.CERT_NONE, Python cannot safely keep hostname checking enabled, so it raises an error.
This protection is intentional. A client that skips certificate verification but still claims to check hostnames would give a false sense of security. Python requires the settings to match so your code is explicit about whether it is making a verified connection or an intentionally unverified test connection.
The Python ssl documentation explains SSL contexts and certificate verification. For related networking topics, see how to get the hostname in Python and how to debug urllib HTTP 403 errors.
Reproduce The Error
The error appears when check_hostname is still true and code tries to set CERT_NONE.
import ssl
context = ssl.create_default_context()
try:
context.verify_mode = ssl.CERT_NONE
except ValueError as error:
print(error)
The default context is designed for secure HTTPS connections, so hostname checking starts enabled. That is why changing verification mode directly fails.
If you see this inside a larger library, search for code that modifies verify_mode after creating a default context. The order of those assignments is often the direct cause.

Disable Hostname Checking First
If you are working in a local lab and intentionally need an unverified context, disable hostname checking before setting CERT_NONE.
import ssl
context = ssl.create_default_context()
context.check_hostname = False
context.verify_mode = ssl.CERT_NONE
print(context.check_hostname)
print(context.verify_mode == ssl.CERT_NONE)
This order fixes the exception, but it also disables important TLS protection. Use it only for controlled testing, never as the default for production clients.
For example, a local appliance in a closed lab may use a temporary certificate while you test connectivity. That is a different risk profile from a public service or production integration.
Prefer Secure Verification
The better fix is usually to keep verification enabled and provide the correct certificate authority bundle when needed.
import ssl
context = ssl.create_default_context(
cafile="/path/to/company-ca-bundle.pem"
)
print(context.check_hostname)
print(context.verify_mode == ssl.CERT_REQUIRED)
Use this pattern when a private service uses an internal certificate authority. You keep hostname verification while teaching Python which CA should be trusted.
If the service certificate is expired, issued for the wrong hostname, or signed by an unknown authority, fixing that certificate is better than disabling verification. The SSL error is often pointing at a real configuration problem.

Connect With A Hostname
Hostname verification needs the hostname passed to wrap_socket(). Without it, Python cannot compare the certificate name to the requested host.
import socket
import ssl
hostname = "www.python.org"
context = ssl.create_default_context()
with socket.create_connection((hostname, 443), timeout=10) as sock:
with context.wrap_socket(sock, server_hostname=hostname) as tls:
print(tls.version())
print(tls.server_hostname)
This keeps the secure default behavior. The connection verifies both certificate trust and hostname match.
Always pass the real hostname, not just an IP address, when the certificate was issued for a DNS name. Hostname verification compares the requested name with the certificate subject information.

Use urllib With A Context
When using urllib.request, pass a secure context instead of disabling checks globally.
import ssl
from urllib.request import urlopen
context = ssl.create_default_context()
with urlopen("https://www.python.org/", context=context, timeout=10) as response:
print(response.status)
print(response.url)
If this fails for an internal service, fix the CA bundle or hostname. Do not turn off verification unless you are in a temporary diagnostic environment.
Some teams keep a company CA bundle in deployment configuration. That lets code use verified TLS for private endpoints without weakening the client logic.
Create An Explicit Helper
If you must support both verified and unverified modes, make the choice obvious in one helper function.
import ssl
def make_tls_context(verify=True):
if verify:
return ssl.create_default_context()
context = ssl.create_default_context()
context.check_hostname = False
context.verify_mode = ssl.CERT_NONE
return context
secure_context = make_tls_context(verify=True)
test_context = make_tls_context(verify=False)
This keeps insecure behavior visible at the call site. A parameter named verify=False is easier to audit than scattered SSL setting changes.
For command-line tools, print a warning when verification is disabled. For services, prefer refusing to start unless the insecure mode is explicitly allowed by configuration.

Why The Order Matters
Python protects you from an inconsistent TLS configuration. Hostname checking only makes sense when certificates are being verified. If certificate verification is disabled, there is no trusted certificate identity to compare against the hostname.
For development-only testing, set check_hostname to false first, then set verify_mode to CERT_NONE. For real clients, keep CERT_REQUIRED and provide a trusted CA bundle.
The reliable fix is to decide whether you need secure verification or a temporary unverified lab context. Most applications should keep verification enabled, because disabling it opens the door to interception and misconfigured endpoints.
Choose a Safe SSL Context
Do not silence this exception by disabling verification in a production client. Prefer the default client context, a trusted CA bundle, and the exact hostname used by the certificate. If an unverified context is unavoidable for a local test, keep it isolated and make the risk obvious in the code.
import ssl
secure_context = ssl.create_default_context()
assert secure_context.verify_mode == ssl.CERT_REQUIRED
assert secure_context.check_hostname is True
When a verified connection fails, inspect the hostname, certificate chain, system clock, CA bundle, proxy, and Python environment instead of turning verification off.
Frequently Asked Questions
Why do verify_mode and check_hostname conflict?
CERT_NONE disables certificate verification, while hostname checking assumes the certificate is being validated. Python rejects that contradictory combination.
What should production code use?
Use ssl.create_default_context() or another context with CERT_REQUIRED and hostname checking enabled, then fix the certificate or hostname problem that caused the connection to fail.
Can I disable check_hostname temporarily?
Only for an isolated, controlled test where certificate verification is intentionally disabled. Never use that configuration for normal production traffic.
What should I inspect when verification fails?
Check the requested hostname, certificate chain, CA bundle, system clock, proxy behavior, and the Python environment making the connection.