How to fix Error: SSL: CERTIFICATE_VERIFY_FAILED (SSL protocol error) in Node.js
SSL protocol errors occur when Node.js cannot verify an HTTPS server's certificate. This happens due to missing intermediate certificates, self-signed certificates, expired certificates, or incorrect system time. Learn how to diagnose and fix certificate verification failures safely.
Quick fix
Fixes CERTIFICATE_VERIFY_FAILED
date- Verify the system time is correct
- Check if the certificate is expired
- Download the server's certificate chain
- Use NODE_EXTRA_CA_CERTS to include additional CA certificates
dateError: SSL: CERTIFICATE_VERIFY_FAILED (SSL protocol error)
What this error means
This error occurs when your Node.js application attempts to make an HTTPS request (or establish a TLS connection) but cannot verify the server's SSL/TLS certificate. Node.js validates certificates by checking the complete certificate chain: the server certificate, any intermediate certificates, and the root certificate. If any part of this chain is missing, improperly configured, or issued by an untrusted Certificate Authority, Node.js rejects the connection. The error does not mean the certificate is necessarily invalid—it means your system cannot establish trust in the certificate through the standard verification process. This is a security feature that prevents man-in-the-middle (MITM) attacks and other certificate-based threats.
Typical symptoms
- HTTPS requests fail with "CERTIFICATE_VERIFY_FAILED" error
- fetch() or http.request() calls to specific servers always fail
- Error occurs in development or testing environments but not in production
- API calls to servers with self-signed or internally-signed certificates fail
- Certificate errors appear after system time changes or clock drift
- Intermediate CA certificates are missing from the server's configuration
Common causes
- Missing intermediate certificates in the server's certificate chain
- Self-signed certificate not added to the system or Node.js trust store
- Certificate issued by a private or corporate CA not recognized by default root CAs
- System clock is incorrect or significantly out of sync (certificate appears not-yet-valid)
- Expired SSL/TLS certificate on the server
- Server misconfigured to not send the full certificate chain
- Node.js version lacks updated CA certificates or modern TLS support
- Corporate proxy or antivirus software intercepting SSL connections
How to fix "Error: SSL: CERTIFICATE_VERIFY_FAILED (SSL protocol error)"
SSL certificates have validity periods (not-before and not-after dates). If your system clock is significantly wrong, valid certificates may appear expired or not-yet-valid.
Check current time:
dateIf the time is incorrect, sync your system clock using NTP (Network Time Protocol):
Linux/macOS:
sudo ntpdate -s time.nist.gov
# or
sudo timedatectl set-ntp trueWindows:
w32tm /resyncRestart your Node.js application after correcting the time.
Verify the expiration date of the server's certificate using OpenSSL:
openssl s_client -connect example.com:443 -showcerts 2>/dev/null | grep -A 5 "notAfter"Or for a specific port:
echo | openssl s_client -connect api.example.com:8443 2>/dev/null | openssl x509 -noout -datesIf the certificate has expired, the server administrator must renew it. If it's a self-signed certificate you control, generate a new one with an extended validity period:
openssl req -x509 -newkey rsa:4096 -nodes -out cert.pem -keyout key.pem -days 365Get the full certificate chain from the server:
openssl s_client -connect example.com:443 -showcerts 2>/dev/null > fullchain.pemThis will output all certificates in the chain. Save this file for the next steps.
Alternatively, download just the certificate using a web browser (click the padlock icon) or use:
openssl s_client -connect example.com:443 2>/dev/null | openssl x509 -outform PEM > server-cert.pemFor self-signed or internal CA certificates, tell Node.js to trust them by setting the NODE_EXTRA_CA_CERTS environment variable:
Linux/macOS:
export NODE_EXTRA_CA_CERTS=/path/to/ca-cert.pem
node your-app.jsWindows (PowerShell):
$env:NODE_EXTRA_CA_CERTS = "C:\path\to\ca-cert.pem"
node your-app.jsWindows (Command Prompt):
set NODE_EXTRA_CA_CERTS=C:\path\to\ca-cert.pem
node your-app.jsIf you have multiple CA certificates, concatenate them into a single file:
cat ca1.pem ca2.pem ca3.pem > ca-bundle.pem
export NODE_EXTRA_CA_CERTS=/path/to/ca-bundle.pem
node your-app.jsThis is the recommended approach for corporate or development environments with internal CAs.
For more control, you can also configure certificates directly in your Node.js code:
import https from 'https';
import fs from 'fs';
const ca = fs.readFileSync('/path/to/ca-cert.pem', 'utf8');
const options = {
hostname: 'api.example.com',
port: 443,
path: '/endpoint',
method: 'GET',
ca: ca, // Add the CA certificate
};
const req = https.request(options, (res) => {
res.on('data', (chunk) => {
console.log('Received:', chunk.toString());
});
});
req.on('error', (err) => {
console.error('Request failed:', err.message);
});
req.end();For fetch (Node.js 18+):
import https from 'https';
import fs from 'fs';
const ca = fs.readFileSync('/path/to/ca-cert.pem', 'utf8');
const agent = new https.Agent({ ca });
const response = await fetch('https://api.example.com/endpoint', {
agent,
});For axios:
import https from 'https';
import fs from 'fs';
import axios from 'axios';
const ca = fs.readFileSync('/path/to/ca-cert.pem', 'utf8');
const httpsAgent = new https.Agent({ ca });
axios.get('https://api.example.com/endpoint', {
httpsAgent,
});Outdated Node.js versions may have incomplete or outdated CA certificate bundles. Update to the latest stable release:
# Check current version
node --version
# Update Node.js (use nvm, brew, or download from nodejs.org)
nvm install node # if using nvm
# or
brew upgrade node # if using Homebrew
# Update npm packages
npm update
npm audit fixAfter updating, restart your application.
For development environments, you can permanently add a self-signed certificate to your system's trusted CA store:
Linux (Debian/Ubuntu):
sudo cp ca-cert.pem /usr/local/share/ca-certificates/ca-cert.crt
sudo update-ca-certificatesmacOS:
sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain ca-cert.pemWindows:
Right-click the .pem or .crt file → Install Certificate → Select "Local Machine" → Place in "Trusted Root Certification Authorities"
After adding, restart Node.js to apply the changes.
Advanced notes
Corporate Proxies and Antivirus Software:
Some corporate environments use SSL inspection (decrypting HTTPS traffic to scan it). This replaces the server's certificate with a proxy certificate, causing verification failures. If your IT department has deployed such tools, they should provide a root CA certificate to add to NODE_EXTRA_CA_CERTS.
Intermediate Certificate Chain:
The complete certificate chain must be in the correct order: server certificate → intermediate CA(s) → root CA. If your server is only sending the server certificate without intermediates, the verification will fail. The server administrator must configure it to send the full chain (using fullchain.pem rather than just the leaf certificate).
Self-Signed vs. CA-Signed Certificates:
Self-signed certificates are valid for internal testing but should never be used in production without explicit trust configuration. In production, always use certificates from a recognized public CA (Let's Encrypt, DigiCert, etc.).
Disabling SSL Verification (Not Recommended):
While Node.js allows disabling certificate verification with rejectUnauthorized: false, this should only be done temporarily in development:
const agent = new https.Agent({ rejectUnauthorized: false });Never use this in production as it removes all protection against MITM attacks.
Debugging Certificate Issues:
Enable verbose TLS debugging with:
NODE_DEBUG=tls node your-app.js 2>&1 | grep -i certCertificate Rotation:
For production systems, implement automatic certificate renewal (e.g., using Let's Encrypt with certbot or similar tools) to prevent expiration-related errors.
Frequently asked questions
- What does "CERTIFICATE_VERIFY_FAILED" mean?
- js application attempts to make an HTTPS request (or establish a TLS connection) but cannot verify the server's SSL/TLS certificate. js validates certificates by checking the complete certificate chain: the server certificate, any intermediate certificates, and the root certificate. js rejects the connection.
- How do I fix "CERTIFICATE_VERIFY_FAILED"?
- SSL protocol errors occur when Node.js cannot verify an HTTPS server's certificate. This happens due to missing intermediate certificates, self-signed certificates, expired certificates, or incorrect system time. Learn how to diagnose and fix certificate verification failures safely.
- What causes "CERTIFICATE_VERIFY_FAILED"?
- Missing intermediate certificates in the server's certificate chain Self-signed certificate not added to the system or Node.js trust store Certificate issued by a private or corporate CA not recognized by default root CAs
- Is the "CERTIFICATE_VERIFY_FAILED" error serious?
- Yes. This is a high-severity error that usually blocks work until it is fixed, but the steps above resolve it.
Official resources & further reading
- 📚Node.js Official Documentation
- 📖Node.js TLS (SSL) Documentation(Official Docs)
- 🐙
- 📝
- 🐙