Command-line tools
curl: (60) SSL certificate problem: causes and fixes
curl: (60) SSL certificate problem: unable to get local issuer certificatecurl: (60) SSL certificate problem means curl reached the server but could not build a trusted chain from the server's certificate to a root CA it trusts. In most cases the server forgot to send its intermediate certificate; otherwise the client's CA bundle is missing, outdated, or does not contain your company's private root.
Quick fix
A chain with one certificate means the server must be fixed; a full chain means the client's trust store is the problem.
Find out which side is broken before changing anything. Test the server from a clean environment:
openssl s_client -connect example.com:443 -servername example.com -showcerts </dev/null
- If the output shows only one certificate (
depth=0) and ends withVerify return code: 21 (unable to verify the first certificate)or20 (unable to get local issuer certificate), the server chain is incomplete. Install the full chain on the server (see missing intermediate certificate). - If the server sends a full chain and other machines connect fine, your client's trust store is the problem. Update it, or point curl at the right root:
curl --cacert /path/to/company-root.pem https://example.com
# or for every curl call in this shell
export CURL_CA_BUNDLE=/path/to/ca-bundle.pem
You can also paste the hostname into the SSL checker to see the chain the server sends.
Causes
1. The server does not send its intermediate certificate
A server that omits its intermediate certificate is the most common cause. Web servers must send the leaf certificate plus every intermediate; only the root is left out. Browsers often hide the mistake, curl does not.
- Confirm:
openssl s_client -showcertslists a single certificate, and itsissueris an intermediate CA rather than a root. - Fix: in Nginx point
ssl_certificateatfullchain.pem(leaf followed by intermediates), notcert.pem. In Apache 2.4.8+ put the full chain inSSLCertificateFile. Rebuild the chain with the chain builder if you only have the leaf.
2. The client CA bundle is missing or outdated
Minimal container images and old systems often ship without a CA bundle, or with one that predates a newer root.
- Confirm:
curl -v https://example.com 2>&1 | grep -i cafileshows a path that does not exist, or the server's root is not in that file. - Fix: install or update the system package (
ca-certificates), or download Mozilla's bundle from curl.se and use it with--cacert.
3. A TLS-inspecting proxy or antivirus
Corporate proxies, security gateways and some antivirus products decrypt HTTPS and re-sign it with their own root. Machines that have that root in the OS store but not in curl's bundle fail with error 60.
- Confirm: the
issuerinopenssl s_clientoutput names your proxy vendor instead of a public CA. - Fix: get the proxy root from your IT team and add it to the system trust store (below) or pass it with
--cacert.
4. Self-signed or private CA certificate
Internal services often use a self-signed certificate or an internal CA. The message then reads self-signed certificate or self-signed certificate in certificate chain.
- Fix: distribute the internal root and trust it explicitly. See self-signed certificate in certificate chain.
5. Hostname or date problems
If the message mentions subject name does not match or certificate has expired, curl verified the chain but the name or the validity period is wrong. Fix the certificate's SAN list or renew it.
Fixes by environment
On every platform, fix the server's chain or add the missing root to the store that curl uses; never switch verification off.
Debian / Ubuntu
sudo apt-get install --reinstall ca-certificates
sudo cp company-root.crt /usr/local/share/ca-certificates/
sudo update-ca-certificates
RHEL / Rocky / Fedora
sudo cp company-root.pem /etc/pki/ca-trust/source/anchors/
sudo update-ca-trust
Alpine and Docker images
RUN apk add --no-cache ca-certificates
COPY company-root.crt /usr/local/share/ca-certificates/
RUN update-ca-certificates
On Debian-based images use apt-get install -y ca-certificates instead.
macOS: the system curl uses the macOS keychain. Add the root in Keychain Access (System keychain, "Always Trust"). A Homebrew curl uses its own bundle; check curl -V and the CAfile: line from curl -v.
Windows: curl.exe shipped with Windows 10/11 uses Schannel and the Windows certificate store, so import the root with certutil -addstore -f Root company-root.cer from an elevated prompt.
PHP, Git and other libcurl users inherit the same problem; see PHP cURL error 60 and Git SSL certificate problem.
Don't do this
curl -k/--insecurein scripts. It turns off every certificate check, including the hostname check. A man-in-the-middle can then read API tokens and change downloads.echo insecure >> ~/.curlrc. This silently disables verification for every future curl call on that account.- Replacing the system bundle with a file copied from a forum. Use the OS package or the bundle published on curl.se, and add private roots alongside it rather than instead of it.
FAQ
What does curl exit code 60 mean?
Exit code 60 is CURLE_PEER_FAILED_VERIFICATION: the TLS handshake worked, but the server certificate or its chain could not be verified against curl's trusted CA certificates. The text after the colon (for example "unable to get local issuer certificate" or "self-signed certificate") is the underlying OpenSSL reason.
Why does the site open in Chrome but fail in curl?
Chrome can fetch a missing intermediate certificate on its own (AIA fetching) and may have it cached from another site. curl does neither, so a server that sends only the leaf certificate works in the browser and fails in curl. Check the chain with the chain builder and fix the server.
Is `curl -k` ever acceptable?
Only for a one-off manual test against a host you control, when you already know why verification fails. In scripts, CI jobs and cron tasks -k disables all certificate checks, so anyone on the network path can impersonate the server and read or change the data.
Where does curl look for CA certificates?
It depends on the TLS backend and how curl was built. OpenSSL builds use a compiled-in bundle path such as /etc/ssl/certs/ca-certificates.crt (Debian/Ubuntu) or /etc/pki/tls/certs/ca-bundle.crt (RHEL); Windows Schannel and macOS builds use the system store. Run curl -v https://example.com and read the CAfile: line.