cURL Ignore SSL Certificate Errors: Complete Guide for Proxy Users
SSL certificate errors are among the most common issues when using cURL with proxies, corporate networks, or development environments. While skipping SSL verification is sometimes necessary, it is important to understand the security implications and use proper fixes when possible. This guide covers all SSL-related cURL options with a focus on proxy configurations.
Quick Fix: The -k Flag
The fastest way to bypass SSL certificate errors in cURL:
curl -k https://example.com
# or the long form
curl --insecure https://example.comWarning: This disables ALL certificate verification, making your connection vulnerable to man-in-the-middle attacks. Use this only for testing, never in production.
Common SSL Errors in cURL
Error Messages and Their Meanings
| Error | Meaning | Common Cause |
|---|---|---|
curl: (60) SSL certificate problem: unable to get local issuer certificate | CA bundle missing/outdated | Missing root CA certificates |
curl: (60) SSL certificate problem: self-signed certificate | Server uses self-signed cert | Dev/staging environments |
curl: (60) SSL certificate problem: certificate has expired | Certificate expired | Server admin hasn’t renewed |
curl: (35) SSL connect error | SSL handshake failure | TLS version mismatch, proxy interference |
curl: (51) SSL: certificate subject name does not match target host name | Hostname mismatch | Wrong domain, proxy MITM |
curl: (58) unable to set private key file | Client cert issue | Wrong key file or format |
SSL Issues with Proxy Servers
Proxy servers are one of the most common sources of SSL errors. Understanding why helps you fix them properly.
Why Proxies Cause SSL Errors
- SSL Interception (MITM Proxies): Corporate proxies often decrypt and re-encrypt HTTPS traffic using their own CA certificate
- Self-signed proxy certificates: Many proxy servers use self-signed certificates
- Certificate chain issues: Proxy may not forward the full certificate chain
- TLS version mismatches: Proxy may support different TLS versions than the target server
Using cURL with HTTP Proxies (No SSL Issues)
# HTTP CONNECT proxy - SSL is end-to-end, no proxy SSL issues
curl -x http://proxy:8080 https://example.comUsing cURL with HTTPS Proxies
# HTTPS proxy - requires trusting the proxy's certificate
curl -x https://proxy:8443 https://example.com
# If proxy has self-signed cert, skip proxy SSL verification
curl --proxy-insecure -x https://proxy:8443 https://example.comSeparate Flags for Proxy vs Server SSL
cURL distinguishes between proxy SSL and server SSL verification:
# Skip SSL verification for the proxy only (keep server verification)
curl --proxy-insecure -x https://proxy:8443 https://example.com
# Skip SSL verification for the target server only
curl -k -x http://proxy:8080 https://example.com
# Skip both (least secure)
curl -k --proxy-insecure -x https://proxy:8443 https://example.comProper SSL Fixes (Instead of -k)
Fix 1: Update CA Certificate Bundle
# macOS
brew install curl
# or update certificates
/usr/libexec/security_certificates
# Ubuntu/Debian
sudo apt-get update && sudo apt-get install ca-certificates
sudo update-ca-certificates
# CentOS/RHEL
sudo yum install ca-certificates
sudo update-ca-trust
# Specify CA bundle explicitly
curl --cacert /etc/ssl/certs/ca-certificates.crt https://example.comFix 2: Add Custom CA Certificate
For corporate proxies or internal services with custom CAs:
# Download the CA certificate
openssl s_client -connect proxy:8443 -showcerts </dev/null 2>/dev/null | \
openssl x509 -outform PEM > proxy-ca.crt
# Use it with cURL
curl --cacert proxy-ca.crt https://example.com
# Or add to system trust store (Ubuntu)
sudo cp proxy-ca.crt /usr/local/share/ca-certificates/
sudo update-ca-certificates
# Or add to system trust store (macOS)
sudo security add-trusted-cert -d -r trustRoot \
-k /Library/Keychains/System.keychain proxy-ca.crtFix 3: Specify CA Directory
curl --capath /etc/ssl/certs/ https://example.comFix 4: Set CA Bundle via Environment Variable
export CURL_CA_BUNDLE=/path/to/custom-ca-bundle.crt
curl https://example.com # Uses custom bundle automaticallyTLS Version Control
Sometimes SSL errors stem from TLS version incompatibilities:
# Force TLS 1.2
curl --tlsv1.2 https://example.com
# Force TLS 1.3
curl --tlsv1.3 https://example.com
# Set maximum TLS version
curl --tls-max 1.2 https://example.com
# Show which TLS version was negotiated
curl -v https://example.com 2>&1 | grep "SSL connection"Debugging SSL Issues
Verbose SSL Output
curl -v https://example.com 2>&1 | grep -A 20 "SSL"Show Full Certificate Chain
curl -vvv https://example.com 2>&1 | grep -E "subject:|issuer:|expire"Using OpenSSL for Diagnosis
# Check certificate details
openssl s_client -connect example.com:443 -showcerts
# Through a proxy
openssl s_client -connect example.com:443 -proxy proxy:8080
# Check certificate expiry
echo | openssl s_client -connect example.com:443 2>/dev/null | \
openssl x509 -noout -datesPython SSL Debugging Script
import subprocess
import ssl
import socket
import json
def diagnose_ssl(host, port=443, proxy=None):
"""Diagnose SSL certificate issues."""
print(f"Diagnosing SSL for {host}:{port}")
# Test with cURL
cmd = ["curl", "-v", "--connect-timeout", "10"]
if proxy:
cmd.extend(["-x", proxy])
cmd.append(f"https://{host}")
result = subprocess.run(cmd, capture_output=True, text=True)
# Parse SSL info from verbose output
ssl_lines = [
line for line in result.stderr.split("\n")
if any(kw in line.lower() for kw in ["ssl", "tls", "certificate", "issuer", "subject"])
]
print("\n--- SSL Connection Details ---")
for line in ssl_lines:
print(line.strip())
# Check if it failed
if result.returncode != 0:
print(f"\n--- Error (exit code {result.returncode}) ---")
error_lines = [l for l in result.stderr.split("\n") if "error" in l.lower()]
for line in error_lines:
print(line.strip())
print("\n--- Suggested Fixes ---")
if "unable to get local issuer certificate" in result.stderr:
print("1. Update CA certificates: sudo update-ca-certificates")
print("2. Use --cacert to specify CA bundle")
elif "self-signed certificate" in result.stderr:
print("1. Add the CA cert to your trust store")
print("2. Use --cacert with the self-signed cert")
elif "certificate has expired" in result.stderr:
print("1. Contact the server administrator")
print("2. Use -k for testing only (not production)")
elif "SSL connect error" in result.stderr:
print("1. Try --tlsv1.2 or --tlsv1.3")
print("2. Check if proxy supports SSL passthrough")
else:
print("\nSSL connection successful!")
# Usage
diagnose_ssl("example.com")
diagnose_ssl("example.com", proxy="http://proxy:8080")Handling Self-Signed Certificates Properly
Generate and Trust a Self-Signed Certificate
# Generate self-signed cert (for testing)
openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem \
-days 365 -nodes -subj "/CN=localhost"
# Use with cURL by specifying the cert as CA
curl --cacert cert.pem https://localhost:8443/apiPin a Specific Certificate
For maximum security, pin the exact certificate you expect:
# Get the certificate's public key hash
openssl s_client -connect example.com:443 2>/dev/null | \
openssl x509 -pubkey -noout | \
openssl pkey -pubin -outform DER | \
openssl dgst -sha256 -binary | base64
# Use certificate pinning in cURL
curl --pinnedpubkey "sha256//YhKJG3VwXBhYJSQROg..." https://example.comConfiguration File for SSL Settings
Create a .curlrc file for persistent SSL settings:
# ~/.curlrc
# Custom CA bundle
cacert = /path/to/custom-ca-bundle.crt
# Force minimum TLS 1.2
tlsv1.2
# Proxy with its own CA
# proxy-cacert = /path/to/proxy-ca.crtSSL Settings in Python (requests)
import requests
# Equivalent of curl -k
response = requests.get("https://example.com", verify=False)
# Specify custom CA bundle
response = requests.get("https://example.com", verify="/path/to/ca-bundle.crt")
# With proxy and custom CA
response = requests.get(
"https://example.com",
verify="/path/to/ca-bundle.crt",
proxies={"https": "http://proxy:8080"}
)
# Client certificate (mTLS)
response = requests.get(
"https://example.com",
cert=("/path/to/client.crt", "/path/to/client.key"),
verify="/path/to/ca-bundle.crt"
)SSL Error Troubleshooting Flowchart
SSL Certificate Error
├── "unable to get local issuer certificate"
│ ├── Update CA certificates (apt/yum)
│ ├── Use --cacert with correct CA bundle
│ └── Set CURL_CA_BUNDLE environment variable
├── "self-signed certificate"
│ ├── Add cert to system trust store
│ ├── Use --cacert with the self-signed cert
│ └── Use -k for testing only
├── "certificate has expired"
│ ├── Contact server admin to renew
│ └── Check system clock (wrong date causes this)
├── "SSL connect error" (error 35)
│ ├── Try --tlsv1.2 or --tlsv1.3
│ ├── Check proxy SSL configuration
│ └── Verify firewall isn't blocking
└── "subject name does not match"
├── Verify you're connecting to the right host
├── Check if proxy is intercepting (MITM)
└── Use --resolve to override DNSFAQ
Is it safe to use curl -k in production?
No. The -k flag disables all SSL certificate verification, making your connection vulnerable to man-in-the-middle attacks. Any attacker on the network path could intercept and modify your traffic. In production, always fix the root cause by updating CA certificates, adding custom CA certs to your trust store, or using --cacert to specify the correct CA bundle.
Why do I get SSL errors when using a proxy?
Proxies cause SSL errors for several reasons: HTTPS proxies may use self-signed certificates, corporate proxies often perform SSL interception (MITM) with their own CA, and some proxies don’t properly forward certificate chains. Use --proxy-insecure for proxy-only SSL issues, or add the proxy’s CA certificate to your trust store with --cacert.
How do I fix “unable to get local issuer certificate” in cURL?
This error means cURL cannot find the CA certificate bundle to verify the server’s certificate. Fix it by: (1) updating system CA certificates with sudo update-ca-certificates, (2) specifying the CA bundle path with curl --cacert /path/to/ca-bundle.crt URL, or (3) setting the CURL_CA_BUNDLE environment variable to point to your CA bundle file.
What is the difference between –insecure and –proxy-insecure?
--insecure (or -k) skips SSL verification for the connection to the target server. --proxy-insecure skips SSL verification only for the connection to the HTTPS proxy server. You can use them independently: --proxy-insecure still verifies the target server’s certificate, and -k still verifies the proxy’s certificate. Use --proxy-insecure when your proxy has a self-signed cert but you still want to verify the target server.
How do I check which TLS version cURL is using?
Run curl -v https://example.com 2>&1 | grep "SSL connection" to see the negotiated TLS version and cipher suite. You can force a specific version with --tlsv1.2 or --tlsv1.3. To see all supported TLS versions, run curl --version and check the SSL library version listed.
- cURL Authentication Guide: Basic, Bearer, Digest & Proxy Auth
- How to Download Files with cURL: Complete Guide with Proxy Support
- Anti-Bot Detection Glossary: 50+ Terms Defined
- Anti-Bot Terminology Glossary: Complete A-Z Reference 2026
- Backconnect Proxies Deep Dive: Architecture and Real-World Performance
- Best Proxies in Southeast Asia: Singapore, Thailand, Indonesia, Philippines
- cURL Authentication Guide: Basic, Bearer, Digest & Proxy Auth
- How to Download Files with cURL: Complete Guide with Proxy Support
- Anti-Bot Detection Glossary: 50+ Terms Defined
- Anti-Bot Terminology Glossary: Complete A-Z Reference 2026
- Backconnect Proxies Deep Dive: Architecture and Real-World Performance
- Best Proxies in Southeast Asia: Singapore, Thailand, Indonesia, Philippines
- 403 Forbidden Error: What It Means & How to Fix It
- 407 Proxy Authentication Required: Fix Guide
- Anti-Bot Detection Glossary: 50+ Terms Defined
- Anti-Bot Terminology Glossary: Complete A-Z Reference 2026
- Backconnect Proxies Deep Dive: Architecture and Real-World Performance
- Best Proxies in Southeast Asia: Singapore, Thailand, Indonesia, Philippines
Related Reading
- 403 Forbidden Error: What It Means & How to Fix It
- 407 Proxy Authentication Required: Fix Guide
- Anti-Bot Detection Glossary: 50+ Terms Defined
- Anti-Bot Terminology Glossary: Complete A-Z Reference 2026
- Backconnect Proxies Deep Dive: Architecture and Real-World Performance
- Best Proxies in Southeast Asia: Singapore, Thailand, Indonesia, Philippines