curl error 60: SSL certificate problem: unable to get local issuer certificate
Fixes curl exit 60: SSL certificate problem: unable to get local issuer certificate. Use when curl cannot verify a server's certificate chain: missing or outdated CA bundle, minimal containers without CA certificates, clock skew, or a corporate proxy re-signing TLS. Gives the CA-store update, --cacert, and CURL_CA_BUNDLE fixes plus how to install an org root CA. Not for curl exit 35 handshake failures, pinned-fingerprint mismatches, or expired domain certificates.
TL;DR
curl exit 60 means curl could not verify the server's certificate chain against its local trust store. The fix is to give curl a current CA bundle: update your system's CA certificates, point curl at a fresh bundle with --cacert or the CURLCABUNDLE variable, or install your organization's root CA if a corporate proxy re-signs TLS. The -k flag silences the error but is a diagnostic only, never the fix.
Verbatim error
curl: (60) SSL certificate problem: unable to get local issuer certificateWhen this applies
- Any
curl https://...exits with code 60. - Scripts or agents running in minimal containers or images that never installed CA certificates.
- Behind a corporate proxy that intercepts and re-signs TLS traffic; the proxy's signing CA is not in the trust store.
- Old OS or curl installs whose root store expired (the September 2021 DST Root CA X3 expiry broke a wave of clients).
- WordPress/PHP installations reporting "Update Failed: Download failed. cURL error 60" (same error, PHP's cURL layer).
When this does NOT apply
- curl exit 35 (SSL connect error): a TLS handshake or cipher mismatch, not a trust-store problem.
- curl exit 51 with a pinned certificate fingerprint that mismatches: the pin is wrong, not the bundle.
- Browser-only errors like NET::ERRCERTDATE_INVALID or an expired domain certificate: those are about the server's own cert, fixed server-side.
- Only one specific host fails while every other HTTPS host works: the server is probably not sending its intermediate certificates. That is a server-side chain problem; error 60 is just what the client sees.
Fix
1. Reproduce and see what curl trusts
curl -v https://example.comExpected output: the same curl: (60) line near the end. curl --version also prints the default CA bundle path curl was built with, which tells you where it is looking.
2. Update the system CA store
Debian/Ubuntu:
sudo apt-get update && sudo apt-get install -y ca-certificates
sudo update-ca-certificatesExpected output: Updating certificates in /etc/ssl/certs... 1 added, 0 removed; done. Re-run your curl command; error 60 should be gone.
RHEL/Fedora:
sudo dnf reinstall -y ca-certificates
sudo update-ca-trustExpected output: no errors, then update-ca-trust prints nothing on success. Re-run curl.
Alpine and other minimal images:
apk add --no-cache ca-certificatesExpected output: the package installs without errors.
3. Point curl at a fresh bundle explicitly
If you cannot touch the system store, download the current Mozilla bundle from https://curl.se/docs/caextract.html and use it directly:
curl --cacert [path to your downloaded cacert.pem] https://example.comExpected output: the request succeeds (HTTP 200) with no certificate error. To make it stick for the session:
export CURL_CA_BUNDLE=[path to your downloaded cacert.pem]Expected output: subsequent plain curl https://example.com calls succeed without --cacert.
4. Corporate MITM proxy: install the organization's root CA
Get your org's root CA certificate from your internal IT page. On Debian/Ubuntu, copy it into the system store and refresh:
sudo cp [org-root-ca].crt /usr/local/share/ca-certificates/
sudo update-ca-certificatesExpected output: 1 added, 0 removed; done. If you cannot modify the system, append the org CA to your downloaded cacert.pem and use it with --cacert from step 3.
5. Rule out clock skew
date -uExpected output: the current UTC time. Certificate validity is checked against the system clock; if it is off by days (common on VMs and containers), fix NTP first, then re-run curl.
Root cause
curl verifies the server's certificate chain against a local trust store of root CAs. "Unable to get local issuer certificate" means the chain terminated at an intermediate or root that is not in that store. That happens when the store is missing or stale (minimal containers, old images), when a middlebox re-signs the traffic and its CA was never added, or when the server fails to send its intermediate certificates so curl cannot complete the chain.
Variant phrasings
curl (60) SSL certificate problemunable to get local issuer certificate curlcURL error 60: SSL certificate problem(PHP/WordPress)SSL certificate problem: unable to get local issuer certificate(git, same root cause, fix is git's http.sslCAInfo)
Edge cases
- Python
requests, Guzzle, and other libraries bundle their own CA stores (certifi, a vendored cacert.pem). Updating the OS store does not fix them; update the package or set its CA path instead. -k/--insecureis fine for a thirty-second diagnostic to confirm the rest of the request works, but it leaves the connection unverified. Do not ship it as the fix.- macOS system curl validates against the system keychain rather than a PEM bundle; a persistent 60 there usually means a proxy CA missing from the keychain or a very old OS.
- WAMP/XAMPP on Windows: PHP's cURL reads its own CA file, so the OS store update does not help; point PHP at a current cacert.pem.
Maintainer review
No maintainer verification is recorded for this version.
This records the version a maintainer checked. It does not assert that the version is the latest upstream release.