Skip to content

Guides · Connect and debug

Fix proxy certificate errors in curl

An HTTPS request can reach a proxy and open a tunnel, then fail its certificate check. Identify the connection and the exact certificate error before changing trust settings. A successful tunnel alone does not establish a successful HTTPS request.

Short answers

Why does curl report error 60 through a proxy?

curl could not verify a peer certificate. For HTTPS through a plain HTTP CONNECT proxy, this is the TLS connection to the destination. The error text helps distinguish an unknown issuer, a hostname mismatch or a certificate validity problem; code 60 alone does not identify the repair.

Does CONNECT 200 mean the certificate is valid?

No. It means the proxy accepted the tunnel. TLS verification happens afterwards in the shown HTTP-proxy example. Our local tests returned connect=200 and target=000 for both an untrusted certificate and a wrong hostname.

Should I turn certificate verification off?

Keep it enabled. Correct the hostname, server certificate or trust configuration responsible for the failure. An unknown certificate from an unexpected network needs investigation before you trust it.

Which CA option should I use?

For the HTTPS destination, curl uses --cacert for an approved PEM CA file. --proxy-cacert applies to TLS with an HTTPS proxy. An http:// proxy has no separate proxy TLS certificate, even when the destination URL uses https://.

Locate the failed connection

For the HTTP gateway in the setup documentation, the sequence is: connect to the gateway, authenticate, request an HTTP CONNECT tunnel, then verify the HTTPS destination inside it. A gateway password and a trusted certificate solve different problems.

An HTTPS proxy adds an earlier TLS connection between the client and the proxy, with its own certificate. Only use an https:// proxy address when that endpoint supports it. Changing the scheme on a plain HTTP port does not add TLS support. The curl HTTPS-proxy documentation explains that extra connection.

Run one bounded status check

Use a small HTTPS endpoint you are allowed to test. The example uses the configured echo endpoint and writes the body to the null device. Replace the full username from your dashboard and enter its password at curl’s terminal prompt. The immediately following printf preserves the meaning of the shell exit status.

Requires an interactive terminal. On Windows use curl.exe and adapt shell continuations, the null device and exit-status syntax. No redirect or automatic retry is requested.

POSIX shell: keep TLS verification enabledsh
curl --disable --silent --show-error --noproxy '' \
  --connect-timeout 5 --max-time 15 --max-filesize 65536 \
  -x "http://gw.portproof.org:7000" \
  --proxy-user "FULL_PROXY_USERNAME" \
  -o /dev/null -w 'connect=%{http_connect} target=%{response_code}\n' \
  https://api.portproof.org/v1/echo-ip
printf 'curl exit=%s\n' "$?"

Keep the exact error text for your own investigation. Do not share a credential-bearing URL, shell trace or verbose log. The transfer limits do not impose a password-entry deadline. This small request still uses proxy traffic; the curl test guide explains how to check the expected response body afterwards.

Results from our local HTTP CONNECT and HTTPS fixture
Fixture conditionStatus output and curl exitWhat to investigate
Correct hostname and approved CA fileconnect=200 target=200, exit 0TLS and the small response succeeded in this test. Check the real endpoint’s expected body separately.
CA absent from trust, or an unrelated CA fileconnect=200 target=000, exit 60Identify the issuing CA and the trust configuration used by this curl build.
Correct CA, wrong destination hostnameconnect=200 target=000, exit 60The trusted issuer does not make a certificate valid for another hostname.
CA file path does not existconnect=200 target=000, exit 77Correct the local file path, format and access; this is a local CA-loading problem.
Wrong gateway passwordconnect=407 target=000, exit 56Use the 407 authentication checks. A CA file cannot fix this refusal.
Destination returns HTTP 403 after valid TLSconnect=200 target=403, exit 0Read the destination’s access requirements. Without --fail, a completed HTTP error response can still give curl exit 0.

000 means no HTTP status was recorded, not a server response. Error text and client versions matter. For DNS, connection refusal or a timeout before CONNECT, follow connection troubleshooting. For a refused tunnel, use the CONNECT guide.

Repair the cause named by the error

Unknown issuer or incomplete chain
Check whether the server should use public trust or an approved organisational CA. A server missing an intermediate certificate needs a server-side fix. If an organisation intentionally inspects TLS, ask its administrator for the approved CA through an established channel. Do not trust a certificate merely because the failing connection presented it.
Hostname mismatch
Compare the URL’s hostname with the name the service is meant to use. Correct a mistyped URL or have the service operator repair its certificate. Substituting an IP address for a hostname can introduce this failure.
Expired or not yet valid
Check the device clock and certificate dates. Correct a wrong local clock or ask the operator to renew or replace the certificate. Adding its issuer does not make an expired certificate valid.
Works in a browser, fails in curl or your application
Record curl --version and the application runtime. Trust stores and TLS backends can differ. Inspect the failing client’s configured CA location rather than assuming that browser success proves identical trust or routing.

The curl certificate guide describes native and file-based trust. An unexpected issuer or a change seen only on one network deserves review with that network’s administrator before adding trust. Keep your application’s verification enabled while resolving the discrepancy.

Test an already approved CA file

Use this only when you have established that the destination is meant to chain to that CA. Replace the path with its approved PEM file. This option applies to this curl invocation; it does not install a CA into the operating system. Leave it out for ordinary public-trust destinations unless their documented configuration requires it.

Process-level destination CA checksh
curl --disable --silent --show-error --noproxy '' \
  --connect-timeout 5 --max-time 15 --max-filesize 65536 \
  --cacert "/path/to/approved-ca.pem" \
  -x "http://gw.portproof.org:7000" \
  --proxy-user "FULL_PROXY_USERNAME" \
  -o /dev/null -w 'connect=%{http_connect} target=%{response_code}\n' \
  https://api.portproof.org/v1/echo-ip
printf 'curl exit=%s\n' "$?"

For a separately supported HTTPS proxy, --proxy-cacert controls trust for the proxy’s TLS connection; --cacert controls the destination. Neither changes the expected hostname. Do not replace the HTTP gateway shown above with an HTTPS scheme unless its endpoint documentation requires it.

What we checked

On 22 October 2026 we ran eight synthetic loopback checks with curl 8.7.1: trusted CA, absent CA, unrelated CA, wrong hostname with the correct CA, missing CA file, wrong proxy password, destination HTTP 403, and a successful repeat with the correct CA. The fixture used a temporary test CA and an HTTP CONNECT proxy. Certificate verification stayed enabled; no OS trust store changed. Failed TLS and authentication cases sent no destination HTTP request, and gateway credentials did not reach the destination.

The fixture supplied synthetic credentials non-interactively and replaced the gateway, destination and CA paths. It did not test a live Portproof connection, HTTPS-proxy TLS, expired certificates or every operating system. Those sections are documentation-based guidance, not additional fixture results. Official curl references were checked on the same date. After a repair, repeat the small check in the actual client you use.