To make curl ignore SSL certificate errors, add -k (--insecure). curl then skips the certificate check and connects anyway. That is fine for a test server you control and a mistake anywhere else. The connection stays encrypted, but curl no longer knows who is on the other end. The fix that keeps the check on is usually one option: --cacert with the certificate of the authority that signed the server's certificate.
curl -k https://test.example/ # skips the check
curl --cacert ca.pem https://test.example/ # trusts this authority, keeps the check
We built a small test lab on our own server on 10 October 2026. It had a private certificate authority and five HTTPS servers on 127.0.0.1, each with a different certificate problem. Every command below ran there with curl 8.5.0 and OpenSSL 3.0.13 on Ubuntu 24.04, so nobody else's server was involved. One more check ran on Windows 11 with the curl.exe it ships.
What does curl -k actually turn off?
curl checks two things before it sends anything over HTTPS, and has done so by default since curl 7.10 in 2002. The certificate must be signed by an authority in its trust store, and it must be made for the host name in the URL. -k skips both, and expiry with them. Our four test servers each failed one way, and -k let all of them through:

The encryption stays. What goes is the proof of identity. RFC 9110 requires an HTTPS client to verify that identity. The check is what stops an attacker on the path, or one who controls your DNS, from posing as the server. curl's own documentation says never to skip verification in production.
-k does not even hide the problem from curl. With -w '%{ssl_verify_result}', our expired server under -k returned 20 200: the check failed with code 20, and curl carried on to a 200. OpenSSL's own openssl verify names code 20 "unable to get local issuer certificate", code 10 "certificate has expired" and code 18 "self-signed certificate".
Which certificate error do you have?
All four are exit 60. The words after it name the problem:
| curl says | What it means | The fix that keeps the check |
|---|---|---|
SSL certificate problem: unable to get local issuer certificate | The authority that signed the certificate is not in curl's trust store. | Pass that authority with --cacert, or add it to the store. |
SSL certificate problem: certificate has expired | The certificate's validity period has ended. | Renew the certificate on the server. |
SSL: no alternative certificate subject name matches target host name | The certificate was made for another name. | Use the name it was made for, or fix the certificate. |
SSL certificate problem: self-signed certificate | The certificate signed itself, so no authority vouches for it. | Trust that certificate with --cacert, or pin its key. |
RFC 5280 defines the validity period as the time during which the authority stands behind the certificate. Our expired test certificate ran from January to 1 February 2025.
How do you fix the error without -k?
You need the certificate of whoever signed the server's certificate, then you tell curl to trust it for this request.
Step 1: see who signed the certificate
curl -sk -o /dev/null -w '%{certs}' https://localhost:18501/ | grep -E '^(Subject|Issuer|Expire date):'
Subject:CN = localhost
Issuer:CN = Docs Test CA
Expire date:Nov 9 20:49:30 2026 GMT
-w '%{certs}' prints the certificates the server sent, and curl's documentation shows the same variable for saving them as a file. -k is fine here, because nothing is being trusted yet: you are only reading.
Step 2: trust that authority for one request
curl --cacert ca.pem https://localhost:18501/
With our test authority in ca.pem, the server that failed before answered ok from good, and the check stayed on.
Step 3: trust it for a whole session
On OpenSSL builds of curl, the environment variables CURL_CA_BUNDLE and SSL_CERT_FILE do what --cacert does. In our run, CURL_CA_BUNDLE=ca.pem curl https://localhost:18501/ and the same with SSL_CERT_FILE both answered ok from good. curl's documentation also describes adding the authority to the system's default store, which every program then shares.
Step 4: pin a self-signed server's key
For a self-signed server you run yourself, pin its public key instead of trusting everything. --pinnedpubkey takes a SHA-256 hash of the key, and the manual says it still checks that key when -k is set:

pin=$(openssl x509 -in selfsigned.pem -pubkey -noout | openssl pkey -pubin -outform der | openssl dgst -sha256 -binary | base64)
curl -k --pinnedpubkey "sha256//$pin" https://localhost:18504/
The right pin connected. A pin made from a different key stopped at once with curl: (90) SSL: public key does not match pinned public key.
Why is insecure in .curlrc a bad idea?
curl reads a .curlrc file before every command, from $CURL_HOME, $HOME or, on Windows, %USERPROFILE%. Some guides suggest writing insecure into it. We tried that:
$ mkdir -p rc && printf 'insecure\n' > rc/.curlrc; CURL_HOME=$PWD/rc curl -sS https://localhost:18504/
ok from selfsigned
$ CURL_HOME=$PWD/rc curl -q -sS -o /dev/null https://localhost:18504/
curl: (60) SSL certificate problem: self-signed certificate
The first command shows no -k at all, and still skipped the check. Every later command run by that user does the same, with nothing on the command line to warn you. -q, as the first option, makes curl ignore the file. If a command passes checks it should fail, look for a .curlrc.
Does -k cover an HTTPS proxy?
No. curl checks an HTTPS proxy's certificate separately from the site's, and its documentation names separate options for it: --proxy-cacert and --proxy-insecure. Our stub proxy on 127.0.0.1 uses a self-signed certificate:
| Command | Result |
|---|---|
curl -k -x https://localhost:18444 -U USER:PASS https://example.com/ | Exit 60: self-signed certificate. The proxy's certificate was still checked. |
curl --proxy-cacert stub-cert.pem -x https://localhost:18444 -U USER:PASS https://example.com/ | Status 200. The proxy logged CONNECT example.com:443. |
--proxy-cacert trusts the proxy's own certificate and keeps both checks on. --proxy-insecure skips the proxy check only, and leaves the site's certificate checked, as what is cURL shows. Our own gateway takes an http:// proxy address instead: -x http://premium.hproxy.com:10000 -U USER:PASS. Then the proxy needs no certificate, and the site's certificate is still checked end to end through the tunnel. Our residential proxies work that way, with the login from your dashboard.
When does -k not help at all?
-k only changes how curl judges the server's certificate. When the TLS handshake itself fails, -k makes no difference. One of our test servers demanded a client certificate:
$ curl -sS -k -o /dev/null https://localhost:18505/
curl: (56) OpenSSL SSL_read: OpenSSL/3.0.13: error:0A00045C:SSL routines::tlsv13 alert certificate required, errno 0
$ curl -sS --cacert ca.pem --cert client.pem --key client.key https://localhost:18505/
ok from mtls
The same failure came with and without -k. Only a client certificate, passed with --cert and --key, fixed it. The same goes for exit 35, the manual's "SSL handshaking failed". A Stack Overflow question from 2023 about unsafe legacy renegotiation disabled, one such handshake error, has over 88,000 views. That error is about the handshake, not about trusting a certificate, so -k is not the fix for it either.
What is different on Windows?
The curl.exe that Windows ships uses Schannel, Microsoft's TLS library, with the Windows certificate store. Our Windows 11 run printed schannel: lines and no CAfile line, where the Linux build names its file. The manual and curl's documentation spell out what follows:
- Schannel uses the certificates built into Windows, the same ones Windows itself trusts.
CURL_CA_BUNDLEis ignored with Schannel, and--ca-nativehas no effect there.--cacertworks with Schannel on Windows 7 and later, though the manual recommends the Windows store.- Schannel also checks whether a certificate was revoked.
--ssl-no-revoketurns that off, which the manual warns loosens security.
To trust a private authority on Windows, add it to the Windows certificate store, or pass --cacert for single commands.
What goes wrong most often?
| What you see | Why | What to do |
|---|---|---|
unable to get local issuer certificate | curl does not trust the signing authority | Pass it with --cacert, or add it to the store. |
certificate has expired | The server's certificate is out of date | Renew it on the server; do not hide it with -k. |
no alternative certificate subject name matches | The address does not match the certificate | Use the name the certificate was made for. |
self-signed certificate from a proxy, with -k set | -k does not cover HTTPS proxies | Use --proxy-cacert, or an http:// proxy address. |
| Checks pass that should fail | insecure in a .curlrc | Remove it; run curl -q to test without the file. |
curl: (56) or (35) that -k does not fix | The handshake failed, not the trust | Read the message: a client certificate, a protocol setting. |
curl: (90) public key does not match pinned public key | The server's key changed, or the pin is wrong | Make a new pin from the server's current key. |
The cURL proxy error guide covers exit 60 when a proxy sits in the middle and intercepts TLS.
What this page could not check
Our certificate errors came from our own test authority and servers on 127.0.0.1. They show how curl behaves, not how a given public site is set up. The Linux runs used curl 8.5.0 with OpenSSL 3.0.13; other TLS libraries word their errors differently, and Windows Schannel messages follow the system language. We did not reproduce the "unsafe legacy renegotiation" error, nor revocation failures behind a corporate proxy. On Windows we ran one verbose request and did not install an authority into the Windows store. curl's handling of native certificate stores keeps changing, so we will check this page again by 10 January 2027.
Sources
- curl project, SSL certificate verification, read 10 October 2026: curl.se/docs/sslcerts.html.
- The curl man page, version 8.23.0, read 10 October 2026: curl.se/docs/manpage.html.
- curl project, history, for verification by default from 7.10 in 2002, read 10 October 2026: curl.se/docs/history.html.
- RFC 9110, HTTP Semantics, June 2022, section 4.3.4 on https certificate verification: rfc-editor.org/rfc/rfc9110.
- RFC 5280, Internet X.509 Public Key Infrastructure Certificate and CRL Profile, May 2008: rfc-editor.org/rfc/rfc5280.
- Stack Overflow, "curl: (35) error:0A000152:SSL routines::unsafe legacy renegotiation disabled", asked 17 March 2023, read through the Stack Exchange API on 10 October 2026.
- Our TLS lab of 10 October 2026: a private test authority and five servers on 127.0.0.1, curl 8.5.0 with OpenSSL 3.0.13 on Ubuntu 24.04, and one Schannel run of curl.exe 8.21.0 on Windows 11. The scripts, certificates list, transcripts and captures are in this page's research folder.


