Node.js HTTPS Client with Custom SSL/TLS Certificates
This article explains how to configure custom SSL/TLS certificates
for making secure HTTPS client requests in Node.js. You will learn how
to load custom Certificate Authorities (CA), client certificates, and
private keys using the native https module to establish
secure, authenticated connections with external servers.
Loading Certificate Files
To configure custom certificates, you must first load the certificate
files from your file system. This is typically done using the built-in
fs (File System) module. You will need to read these files
as buffers or strings.
const fs = require('fs');
const path = require('path');
// Load the custom CA, client certificate, and client private key
const customCA = fs.readFileSync(path.join(__dirname, 'ca.pem'));
const clientCert = fs.readFileSync(path.join(__dirname, 'client-cert.pem'));
const clientKey = fs.readFileSync(path.join(__dirname, 'client-key.pem'));Configuring the HTTPS Request Options
When making an HTTPS request, Node.js allows you to pass an options object to customize the TLS handshake. You can inject your custom certificates into this object using specific properties:
ca: An array of trusted certificates or a single certificate in PEM format. Use this if the server uses a self-signed certificate or a private CA.key: The client’s private key in PEM format (used for mutual TLS/mTLS).cert: The client’s public certificate in PEM format (used for mutual TLS/mTLS).rejectUnauthorized: If set totrue, the server certificate is verified against the list of supplied CAs. Set this totruein production to prevent man-in-the-middle attacks.
const options = {
hostname: 'secure.example.com',
port: 443,
path: '/api/data',
method: 'GET',
ca: customCA, // Trust the custom CA
key: clientKey, // Client private key for mTLS
cert: clientCert, // Client certificate for mTLS
rejectUnauthorized: true // Enforce certificate validation
};Making the Secure HTTPS Request
Once the options object is configured, pass it to
https.request() or https.get(). The underlying
TLS agent will use your custom credentials during the handshake.
const https = require('https');
const req = https.request(options, (res) => {
console.log(`Status Code: ${res.statusCode}`);
res.on('data', (chunk) => {
process.stdout.write(chunk);
});
});
req.on('error', (err) => {
console.error(`Secure connection failed: ${err.message}`);
});
// End the request
req.end();Using a Custom Agent for Reusable Connections
If you need to make multiple requests using the same SSL/TLS
configuration, it is highly efficient to create a reusable
https.Agent. This avoids the overhead of performing a full
TLS handshake for every single request.
const secureAgent = new https.Agent({
ca: customCA,
key: clientKey,
cert: clientCert,
keepAlive: true
});
// Reuse the agent across multiple request options
const requestOptions = {
hostname: 'secure.example.com',
port: 443,
path: '/api/resource',
method: 'POST',
agent: secureAgent
};