Short answer: curl -k https://host (long form --insecure) makes curl ignore certificate errors. The wget equivalent is wget --no-check-certificate, and PowerShell 7 uses -SkipCertificateCheck. The connection stays encrypted but is no longer authenticated, so anyone in the path could pose as the server. Use it to diagnose, then fix the certificate or trust it properly.
curl -k https://192.0.2.10/ # curl, short form
curl --insecure https://test.internal/api/health # curl, long form
wget --no-check-certificate https://test.internal/file.tar.gz
Invoke-WebRequest https://test.internal -SkipCertificateCheck # PowerShell 6.0 and laterThe curl and wget flags here were checked against curl --help all, man curl and wget --help on Debian 12 (curl 7.88.1 with OpenSSL 3.0.22, GNU Wget 1.21.3) on 21 October 2026, and the verbose output further down is a real request from that machine. The PowerShell parts follow Microsoft Learn.
Ignore the certificate, or fix it: tool by tool
| Tool | Skip verification | Safer: trust a specific CA |
|---|---|---|
| curl | -k, --insecure | --cacert ca.pem |
| wget | --no-check-certificate | --ca-certificate=ca.pem |
| PowerShell 7 | -SkipCertificateCheck | Import the CA into the Windows certificate store |
| git | git -c http.sslVerify=false clone URL | git config http.sslCAInfo /path/ca.pem |
| pip | --trusted-host HOST | --cert /path/ca.pem |
| npm | npm config set strict-ssl false | npm config set cafile /path/ca.pem |
| Node.js | NODE_TLS_REJECT_UNAUTHORIZED=0 | NODE_EXTRA_CA_CERTS=/path/ca.pem |
| Python requests | verify=False | verify="/path/ca.pem" |
The right-hand column is almost always what you actually want. It keeps every check switched on and only adds one CA you trust on purpose, so a real attacker still gets an error.
What curl -k actually turns off
Without -k, curl’s man page says it verifies two things before any data moves: that the certificate contains a name matching the host in the URL, and that it is signed by a CA in the certificate store. With -k it skips that step and proceeds without checking. In practice that means:
- Still on: TLS encryption. A passive eavesdropper still sees nothing.
- Off: the chain to a trusted CA, the host name match and the expiry check. An active attacker who intercepts the connection can present any certificate and read or change the traffic, including passwords, API tokens and the script you are about to pipe into a shell.
- Not covered: an HTTPS proxy (
--proxy-insecureis separate) and DNS-over-HTTPS (--doh-insecure). For SFTP and SCP URLs,-kskips theknown_hostscheck instead.
Check for a stray insecure line in ~/.curlrc too: curl reads that file on every run, so one line there quietly turns verification off for everything. Start a command with -q to ignore the file for that run.
Read the error before you skip it
Each certificate error has its own fix, and several of them belong on the server, not in your command. These are the messages curl 7.88 prints with OpenSSL, the build in Debian 12; apart from the missing bundle (exit code 77) they end with exit code 60, “Peer certificate cannot be authenticated with known CA certificates”:
| Message | Cause | Fix |
|---|---|---|
SSL certificate problem: unable to get local issuer certificate | The server does not send its intermediate certificate, or a private CA signed it | Fix the chain on the server, or trust the private CA |
SSL certificate problem: self-signed certificate | A self-signed certificate (OpenSSL 1.1 spells it without the hyphen) | --cacert or pin its key |
SSL certificate problem: certificate has expired | Renewal failed, or your clock is ahead | Renew on the server; check the client's clock |
SSL certificate problem: certificate is not yet valid | The client's clock is behind | timedatectl status, then fix NTP |
SSL: no alternative certificate subject name matches target host name '192.0.2.10' | You used an IP or another name than the certificate holds | Use the real name with --resolve |
| exit code 77: “Problem reading the SSL CA cert” | The CA bundle is missing or unreadable | Install ca-certificates |
ERROR: cannot verify HOST's certificate, issued by ...: Unable to locally verify the issuer's authority. | The same as the local issuer case in curl | Same fixes |
For the browser side of the same failures, see Your connection is not private; for handshakes that fail before any certificate is checked, SSL handshake failed.
What a verified request looks like
-v shows which CA store curl used and whether verification passed. This is the TLS part of curl -svI https://example.com on Debian 12 on 21 October 2026:
* CAfile: /etc/ssl/certs/ca-certificates.crt
* CApath: /etc/ssl/certs
* SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384
* Server certificate:
* subject: CN=example.com
* subjectAltName: host "example.com" matched cert's "example.com"
* issuer: C=US; O=SSL Corporation; CN=Cloudflare TLS Issuing ECC CA 3
* SSL certificate verify ok.Run the same against the failing host. The CAfile line tells you which bundle to fix, and the subject, subjectAltName and issuer lines usually show the problem before the error does. -k changes the last line to SSL certificate verify result: ... continuing anyway., which is a useful way to read a broken certificate’s details without trusting it.
Trust a private CA or self-signed certificate properly
For an internal service, a staging box or a device with its own CA, give curl that CA instead of switching checks off. --cacert takes a PEM file with one or more CA certificates and replaces the default bundle for that call; --capath takes a directory (prepared with OpenSSL’s c_rehash), and the CURL_CA_BUNDLE environment variable sets the file for every call in a shell:
curl --cacert ./internal-ca.pem https://test.internal/api/health
export CURL_CA_BUNDLE=$HOME/internal-ca.pem # every curl in this shellFor a self-signed server certificate, the certificate itself can act as the CA file. Copy it from the server over SSH rather than downloading it over the network you do not trust yet, or compare its fingerprint with the one the server shows locally (openssl x509 -in cert.pem -noout -fingerprint -sha256). The name you use in the URL still has to be in the certificate.
To make every program on the machine trust the CA, add it to the system store. On Debian and Ubuntu, update-ca-certificates(8) requires PEM format and a .crt extension, one certificate per file:
sudo cp internal-ca.pem /usr/local/share/ca-certificates/internal-ca.crt
sudo update-ca-certificatessudo cp internal-ca.pem /etc/pki/ca-trust/source/anchors/internal-ca.pem
sudo update-ca-trustImport-Certificate -FilePath .\internal-ca.cer -CertStoreLocation Cert:\LocalMachine\RootLanguage runtimes do not always read the system store: Node.js wants NODE_EXTRA_CA_CERTS, Python’s requests uses its own bundle unless REQUESTS_CA_BUNDLE points elsewhere, and Java has its own keystore. That is why the cheat sheet above lists the per-tool option.
Pin the public key with --pinnedpubkey
For a device you will never get a proper certificate for (a router, a NAS, an appliance with a self-signed certificate), pinning is far better than -k. curl compares the server’s public key with a hash you supply and aborts before sending or receiving any data if it differs. Compute the hash once, from the certificate file:
openssl x509 -in device.pem -pubkey -noout \
| openssl pkey -pubin -outform der \
| openssl dgst -sha256 -binary \
| openssl enc -base64
BpRjT5he5PY5LIWuo86dxibaj8Hr+h/KDTX2e8jeFYM=curl -k --pinnedpubkey 'sha256//BpRjT5he5PY5LIWuo86dxibaj8Hr+h/KDTX2e8jeFYM=' https://192.0.2.10/Here -k is acceptable, because the libcurl documentation for the pinning option states that it is independent of peer verification: with verification off, the peer is still verified by its public key. A different key ends the transfer with exit code 90. Re-pin when the device generates a new key.
Test a new server before DNS points at it: --resolve
The most common reason people reach for -k on a server is testing it by IP before the domain moves: curl -k https://203.0.113.20/. That request tests almost nothing, because the certificate is for the domain, not the IP. --resolve sends the real host name (for SNI and the certificate check) to the address you choose, like a one-off hosts file entry:
curl -sSI --resolve example.com:443:203.0.113.20 https://example.com/
curl -sSI --connect-to example.com:443:new-lb.example.net:443 https://example.com/--connect-to does the same with a host name as the target, for example a load balancer; the man page notes that it only changes where curl connects, not the name it uses for SNI and certificate verification. Both keep every check on, so a pass here means the new server will pass once DNS switches. The curl examples cover the rest of the everyday flags.
If you run the server: fix the certificate
“Unable to get local issuer certificate” in curl while browsers show the site fine almost always means a missing intermediate certificate. Browsers often fill the gap from a cache; curl, scripts and payment callbacks do not. With Let’s Encrypt the fix is pointing the web server at fullchain.pem, not cert.pem:
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;Check what the server really sends with openssl s_client -connect example.com:443 -servername example.com -showcerts (the openssl commands guide explains the output) or paste the host into the SSL checker, which flags a missing intermediate. Expired certificates usually mean a renewal job that stopped running: sudo certbot renew --dry-run shows why.
If the client is the problem: update its CA store
Old systems and minimal container images fail against perfectly good certificates because their CA bundle is outdated or missing. Slim Debian and Ubuntu images often ship without ca-certificates at all, which ends in exit code 77 or a local issuer error on the first HTTPS request:
sudo apt-get update && sudo apt-get install -y ca-certificatessudo dnf update -y ca-certificatesOn Windows
Invoke-WebRequest and Invoke-RestMethod gained -SkipCertificateCheck in PowerShell 6.0; Microsoft Learn describes it as skipping all validation, including expiration, revocation and the trusted root, and as meant only for known test hosts with self-signed certificates. Windows PowerShell 5.1 has no such switch; the old workaround of overriding ServerCertificateValidationCallback turns checks off for the whole session, so avoid it. The curl.exe that ships with Windows uses the Windows certificate store and can fail with CRYPT_E_NO_REVOCATION_CHECK when the revocation server is unreachable (behind a strict firewall, for instance); --ssl-no-revoke skips only that check and keeps the rest, which beats -k. More on the Windows quirks in curl and wget on Windows.
On your own server, nobody should need -k
A public site or API on a VPS should present a certificate that every client accepts without flags: a free Let’s Encrypt certificate with the full chain, renewed automatically. nginx as a reverse proxy with SSL sets that up in one pass, and internal services that stay on a private CA get the CA file on the clients instead of -k in every script.
Frequently asked
How do I make curl ignore SSL certificate errors?
Add -k or --insecure: curl -k https://host. curl then skips the check of the certificate chain, the host name and the expiry date, but still encrypts the connection. Use it only to diagnose; for an internal server, pass its CA with --cacert ca.pem instead, which keeps every check on.
How do I ignore the certificate in wget?
Use wget --no-check-certificate URL. The safer alternative for a server with a private CA is --ca-certificate=/path/ca.pem, which keeps verification on and trusts only that extra CA.
Is curl -k safe?
Not for anything that matters. The connection is encrypted but not authenticated, so an attacker who can intercept it can present any certificate and read or change the traffic, including passwords and tokens. It is fine for a one-off look at a test server on a network you control; scripts should use --cacert or --pinnedpubkey.
How do I ignore certificate errors in PowerShell?
In PowerShell 6.0 and later, add -SkipCertificateCheck to Invoke-WebRequest or Invoke-RestMethod. Windows PowerShell 5.1 has no such switch. The better fix is to trust the CA: import its certificate into Cert:\LocalMachine\Root with Import-Certificate.