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.
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.
| Fixture condition | Status output and curl exit | What to investigate |
|---|---|---|
| Correct hostname and approved CA file | connect=200 target=200, exit 0 | TLS and the small response succeeded in this test. Check the real endpoint’s expected body separately. |
| CA absent from trust, or an unrelated CA file | connect=200 target=000, exit 60 | Identify the issuing CA and the trust configuration used by this curl build. |
| Correct CA, wrong destination hostname | connect=200 target=000, exit 60 | The trusted issuer does not make a certificate valid for another hostname. |
| CA file path does not exist | connect=200 target=000, exit 77 | Correct the local file path, format and access; this is a local CA-loading problem. |
| Wrong gateway password | connect=407 target=000, exit 56 | Use the 407 authentication checks. A CA file cannot fix this refusal. |
| Destination returns HTTP 403 after valid TLS | connect=200 target=403, exit 0 | Read 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 --versionand 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.
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.