SSL handshake errors in API tests
Updated 2026-11-13 · 3 min read
TLS can fail before an API returns an HTTP response. A disposable local certificate reproduces a trust rejection and a successful request with explicit CA trust.
The reproduced message
An isolated Node HTTPS server using a freshly generated local certificate produced this exact curl error:
curl: (60) SSL certificate problem: self signed certificate
This is a certificate-verification failure, one member of the broad group testers call “SSL handshake errors”. Modern HTTPS uses TLS. Other clients and TLS libraries report their failures differently; do not paste this curl message as though it came from Java or Postman.
1. The client does not trust the issuing certificate
This local fixture and the commands below were run. Generate a disposable certificate for localhost only; the private key is for this lab, not a shared environment.
mkdir -p /tmp/batch2-tls
openssl req -x509 -newkey rsa:2048 -nodes -keyout /tmp/batch2-tls/key.pem -out /tmp/batch2-tls/cert.pem -days 1 -subj /CN=localhost -addext subjectAltName=DNS:localhost
Save as tls-lab.cjs, then run node tls-lab.cjs in a separate terminal:
const https = require('node:https');
const fs = require('node:fs');
https.createServer({
key: fs.readFileSync('/tmp/batch2-tls/key.pem'),
cert: fs.readFileSync('/tmp/batch2-tls/cert.pem'),
}, (req, res) => res.end('TLS lab OK\n')).listen(4312, '127.0.0.1');
The first request failed verification. The second returned TLS lab OK with verification enabled and explicit trust in this lab certificate:
curl https://localhost:4312/
curl --cacert /tmp/batch2-tls/cert.pem https://localhost:4312/
For a real private PKI, obtain the approved CA bundle and configure the client's trust store. For a public service, check the server's complete intermediate chain. Do not use a global verification bypass as the suite's fix.
2. The certificate is for another hostname or has expired
Check the requested hostname against the certificate's subject alternative names and check validity dates and the machine clock. Use the intended DNS name; an IP address does not automatically match a DNS certificate. Reissue or renew the certificate when needed. Adding a CA does not repair those identity errors.
3. Client and server cannot agree on TLS, or mTLS is required
Confirm HTTPS is being sent to a TLS listener, not a plain HTTP port. Check the client and server protocol/cipher support in their logs. Upgrade obsolete clients or server configuration rather than enabling old protocols indiscriminately. If the server requires mutual TLS, provision the approved client certificate and matching private key separately from the CA trust bundle.
Prevention and interview answer
Run a TLS connectivity check before API assertions, record the exact client error and destination, and track certificate rotation in the environment runbook. “I separate trust, hostname, protocol negotiation and client identity, then fix the failing layer and rerun with verification enabled.”
For Postman's certificate settings see self-signed certificate errors. A browser-only failure after HTTP may instead be CORS.
Quick answers
Is every TLS failure a certificate trust issue?
No. Protocol negotiation, hostname validation and missing client identity can fail for different reasons.
Does HTTP 401 mean the TLS handshake failed?
No. Receiving an HTTP response means that connection progressed far enough to exchange HTTP data.
Sources
Want a project you can show in interviews?
The portfolio project kit walks you through testing a deliberately buggy app with Selenium or Playwright and API tests, then explaining it. The app itself is free.
