What Causes ERR_BAD_SSL_CLIENT_AUTH_CERT

In a normal HTTPS connection, only the server shows a certificate. Sites running mutual TLS (mTLS) also send a certificate request, and the browser has to answer with a client certificate plus a signature made with the matching private key. If that step fails, the handshake stops. Every Chromium-based browser shows the same code.
Your Certificate Is the Problem, Not the Website's
Many guides tell you to renew the site's SSL certificate. That targets the wrong certificate. The Chromium source defines error -117 as a handshake failure caused by a bad or missing client certificate. Chrome maps server alerts like bad_certificate, certificate_expired, unknown_ca, access_denied, and certificate_required straight to it. Problems with the server's own certificate get separate codes, like ERR_CERT_DATE_INVALID.
The Usual Triggers
The certificate is missing, expired, revoked, issued by a CA the server does not trust, or imported without its private key. A TLS-inspecting antivirus causes it too, and so does a cancelled certificate prompt.
Also Read: Guide to Proxy Error Codes
How to Fix It in Chrome

Restart Chrome Completely
Chrome caches the certificate you picked for each site, including the decision to send nothing. Reloading changes nothing. Quit Chrome fully, reopen it, and pick the right certificate when the prompt appears.
Check the Certificate and Its Private Key
On Windows, run certmgr.msc, open Personal, then Certificates, and double-click your certificate. It should say you have a private key that corresponds to it. On macOS, the certificate must appear under My Certificates in Keychain Access. A .cer or .crt file carries no key, so reinstall from the original .p12 or .pfx file.
Check the Expiry Date and Your Clock
Expired certificates stay in the store after they lapse, so they are easy to miss. Check the dates with OpenSSL:
openssl pkcs12 -in client-cert.p12 -clcerts -nokeys | openssl x509 -noout -subject -datesIf notAfter has passed, ask whoever issued the certificate for a new one. Also set your system clock to sync automatically, since a wrong date can make a valid certificate look expired.
Turn Off HTTPS Scanning
Antivirus web shields and corporate filters that inspect HTTPS end your TLS session and open a new one to the site. They don't hold your private key, so mTLS fails. Add the site to the exclusion list instead of leaving protection off.
If You Run the Server
Check that client verification is not on by mistake. In nginx, ssl_verify_client set to on means every visitor needs a certificate, and ssl_client_certificate has to point to the CA that issued your users' certificates.
How to Fix It in Playwright and Puppeteer

In automation, the error shows up as net::ERR_BAD_SSL_CLIENT_AUTH_CERT in Puppeteer or Playwright logs. A headless browser can't click the certificate prompt, so it sends nothing.
Playwright
Playwright added native client certificate support in version 1.46. You pass the certificate when creating the context. The Playwright release notes cover the option for every language binding.
from playwright.sync_api import sync_playwright
TARGET = "https://portal.example.com"
with sync_playwright() as p:
browser = p.chromium.launch()
context = browser.new_context(client_certificates=[{
"origin": TARGET,
"certPath": "client-cert.pem",
"keyPath": "client-key.pem",
}])
page = context.new_page()
page.goto(TARGET)Puppeteer and Python Requests
Puppeteer has no equivalent option. The workable route is Chrome's AutoSelectCertificateForUrls policy, which tells the browser which certificate to send for a given URL pattern. In Requests, pass the certificate and key through the cert argument.
import requests
proxy = "http://USER:PASS@HOST:PORT"
r = requests.get(
"https://api.example.com/data",
cert=("client-cert.pem", "client-key.pem"),
proxies={"http": proxy, "https": proxy},
timeout=30,
)
print(r.status_code)Does a Proxy Break Client Certificates
A standard HTTP or SOCKS5 proxy does not. For HTTPS, the proxy only relays encrypted bytes while your client runs the TLS handshake with the target end to end. Your certificate passes through residential proxies or datacenter proxies untouched. Proxies that decrypt traffic, like SSL-inspecting gateways and unblocker endpoints that ask you to trust their CA, do break it. The proxy formatter turns raw proxy strings into the URL format above.
Also Read: How to Fix Proxy Authentication Error
FAQ Section

How do I fix a bad SSL client authentication certificate?
Restart the browser fully, then confirm the certificate is installed with its private key and still within its validity dates. If it expired or was revoked, only the issuer can replace it.
Does ERR_BAD_SSL_CLIENT_AUTH_CERT mean the website is unsafe?
No. It means the site enforces an extra layer of authentication and refused a connection it could not verify. There is no "proceed anyway" option because the handshake never finished.
Why does Chrome not show the certificate prompt?
Either no installed certificate matches what the server asked for, or Chrome is reusing a choice it cached earlier. A full restart or an Incognito window brings the prompt back.
Will clearing the cache and cookies fix it?
Rarely. Cookies play no part in the TLS handshake. The cached certificate choice is what matters, and a browser restart clears that.
Can a VPN cause ERR_BAD_SSL_CLIENT_AUTH_CERT?
Only if it inspects HTTPS traffic. A VPN that just tunnels your connection leaves the handshake alone, the same way a normal proxy does.
Final Thoughts
ERR_BAD_SSL_CLIENT_AUTH_CERT is almost always about the certificate on your side of the connection. Restart the browser, confirm the certificate still has its key and a valid date, and take HTTPS scanning out of the path before you touch anything on the server. In code, pass the certificate explicitly, because a headless browser will never pick one for you.