When your server connects to an HTTPS API or website and fails with SSL certificate problem: unable to get local issuer certificate, certificate verify failed or UNABLE_TO_VERIFY_LEAF_SIGNATURE, the TLS client could not build a trusted chain to the remote certificate. The fix is never to turn verification off; it is to find which side is missing what.
Before you start
- SSH access to the server making the request.
- The URL being called.
Test from the command line
curl -v https://api.example.com 2>&1 | grep -iE 'ssl|certificate|issuer|expire'Then inspect the chain the remote server sends:
openssl s_client -connect api.example.com:443 -servername api.example.com -showcerts </dev/nullLook at Verify return code at the end. 0 (ok) means the chain verifies on this machine.
Cause 1: outdated CA certificates on your server
Root certificates expire and new ones are added. Old systems fail on sites using newer roots. Update the bundle:
apt update && apt install --only-upgrade ca-certificatesdnf update ca-certificatesThen run update-ca-certificates (Debian/Ubuntu) or update-ca-trust (RHEL). Very old OS releases may need an OS upgrade.
Cause 2: the remote server is missing its intermediate certificate
If s_client shows only one certificate (depth 0) and verification fails with unable to verify the first certificate, the remote site is misconfigured. Browsers sometimes hide this by fetching intermediates themselves; servers and apps do not. If it is your own site, install the full chain (fullchain.pem); if it is a third party, tell them.
Cause 3: wrong system clock
If the server's date is wrong, valid certificates look expired or not yet valid. Check with timedatectl and enable time sync.
Cause 4: an intercepting proxy or firewall
Some corporate proxies and security products re-sign HTTPS traffic with their own CA. Add that CA to the system trust store (/usr/local/share/ca-certificates/ then update-ca-certificates), rather than disabling checks.
Language-specific CA settings
| Runtime | Where CAs come from | Fix |
|---|---|---|
| PHP (curl/openssl) | curl.cainfo / openssl.cafile in php.ini, else system | Point to the system bundle, e.g. /etc/ssl/certs/ca-certificates.crt |
| Node.js | Built-in bundle | Add extra CAs with NODE_EXTRA_CA_CERTS=/path/ca.pem; upgrade Node for newer roots |
| Python requests | certifi package | pip install -U certifi, or set REQUESTS_CA_BUNDLE |
| Git | System bundle | git config --global http.sslCAInfo /path/bundle if needed |
Why not disable verification?
Options like curl -k, CURLOPT_SSL_VERIFYPEER => false, verify=False or NODE_TLS_REJECT_UNAUTHORIZED=0 make the connection vulnerable to interception: anyone in the path could read or change API traffic, including payment data and credentials. Use them only for a one-off local test.
Check the fix
Rerun the curl -v or openssl s_client test until it reports Verify return code: 0 (ok), then retry from the application.
SSL verify FAQ
The site works in my browser; why does the server fail?
Browsers have newer root stores and can fetch missing intermediates; server-side clients rely on the local CA bundle and the chain the server sends.
Does this affect my visitors?
Only if it is your own site with a missing intermediate. Outgoing call failures affect features like payments, webhooks and updates.
Can this happen on cPanel hosting?
The server's CA bundle is maintained by the host; contact support if outgoing HTTPS calls fail for valid sites.
