ScreenshotNeo

BlogHow-to

How to Solve the cURL (60) Error When Using a Proxy

Fix cURL error 60 behind a proxy by finding the failing TLS connection and configuring the correct trusted CA without disabling verification.

By the ScreenshotNeo team1 October 20268 min read

cURL error 60 means certificate verification failed. It does not, by itself, mean that the proxy is unreachable. When a proxy is involved, determine which TLS connection failed, then trust the correct CA certificate while keeping hostname and peer verification enabled.

There can be two separate TLS hops:

  • cURL to the destination: common when an HTTP proxy creates a CONNECT tunnel to an HTTPS site.
  • cURL to the proxy: relevant when the proxy URL itself starts with https://.

The trust setting for one hop does not automatically fix the other.

What error 60 means

Typical messages include SSL certificate problem: unable to get local issuer certificate. cURL could not build and validate a certificate chain from the peer certificate to a trusted CA in the certificate store used by that cURL build. Causes include:

  • An outdated or missing CA bundle.
  • A private or corporate CA that is not in the default trust store.
  • TLS inspection by a managed proxy, which replaces the origin certificate with one signed by an organization CA.
  • An incomplete server certificate chain.
  • An expired certificate or a hostname mismatch.
  • cURL using a different proxy or CA store than you expected.

cURL’s SSL certificate documentation explains its trust model and CA options: curl.se/docs/sslcerts.html.

Step 1: inspect the actual failing connection

Run the same request with verbose output:

curl -v -x http://proxy.example:8080 https://example.com/

For a proxy requiring credentials, avoid putting secrets in shell history. Prefer a .netrc entry or an environment variable supported by your deployment process:

curl -v -x http://proxy.example:8080 --proxy-user "$PROXY_USER:$PROXY_PASSWORD" https://example.com/

Look for:

  • The proxy address cURL actually selected.
  • Whether cURL sends an HTTP CONNECT request.
  • The certificate subject and issuer shown for the failing peer.
  • The CA file or directory cURL reports.
  • The point where verification fails.

Do not publish verbose logs containing proxy credentials, authorization headers, cookies, URLs with secrets, or internal hostnames.

Step 2: check proxy environment variables

cURL can select a proxy from protocol-specific variables such as HTTPS_PROXY or https_proxy, and from ALL_PROXY. A protocol-specific variable takes precedence when both apply. Inspect the environment used by the same process that runs cURL:

env | grep -iE '^(http|https|all|no)_proxy='

To bypass a proxy for one host, use NO_PROXY:

NO_PROXY=example.com curl -v https://example.com/

To force a known proxy for one command, pass it explicitly:

curl -v --proxy http://proxy.example:8080 https://example.com/

See cURL’s proxy environment variable documentation for precedence and syntax: everything.curl.dev/usingcurl/proxies/env.html.

Step 3: fix trust for the destination server

Use this path when the proxy is HTTP and the certificate failure occurs after the CONNECT tunnel is established, or when the origin certificate is signed by a private CA.

Use a CA bundle for one transfer

Obtain the approved CA certificate or bundle from the organization that operates the destination or proxy. Verify its provenance through that organization’s trusted process, then pass it with --cacert:

curl --cacert /path/to/approved-ca-bundle.pem \
  --proxy http://proxy.example:8080 \
  https://internal.example/

The PEM file must contain a CA that legitimately signs the server’s certificate chain. A leaf certificate copied from an error message is not a replacement for a trusted CA.

Configure a default CA source

For supported cURL builds, the CA source can also be configured with environment variables:

export CURL_CA_BUNDLE=/path/to/approved-ca-bundle.pem
curl --proxy http://proxy.example:8080 https://internal.example/

Some builds support SSL_CERT_FILE and SSL_CERT_DIR. Their behavior depends on the TLS backend and build configuration, so verify with your installed version and platform documentation.

Step 4: fix trust for an HTTPS proxy

If the proxy URL is HTTPS, cURL verifies the proxy certificate separately from the destination certificate. Configure the CA for that proxy connection with --proxy-cacert:

curl --proxy https://proxy.example:8443 \
  --proxy-cacert /path/to/proxy-ca.pem \
  https://example.com/

If the destination also uses a private CA, supply both trust sources:

curl --proxy https://proxy.example:8443 \
  --proxy-cacert /path/to/proxy-ca.pem \
  --cacert /path/to/origin-ca-bundle.pem \
  https://internal.example/

Recent cURL versions may support --proxy-ca-native to use the platform’s native trust store for the proxy connection. Check curl --help all and the SSL backend in your installed build before relying on it.

Step 5: obtain and install the right corporate CA

With TLS inspection, the proxy intentionally presents certificates issued by an organization-controlled root or intermediate CA. Ask the team that manages the proxy for the approved CA and installation instructions. Confirm the certificate fingerprint through a separate trusted channel.

Then choose the narrowest configuration that fits your deployment:

Scope Approach Use when
One command --cacert or --proxy-cacert You need a controlled test or one integration.
One user or service CURL_CA_BUNDLE, supported certificate directory, or runtime setting Several commands share the same approved CA.
Operating system Install the CA using your platform’s documented trust-store procedure Many applications must trust the organization CA.
Application only Configure the application’s libcurl/TLS settings The application embeds libcurl and does not inherit shell settings.

Platform and TLS-backend differences

There is no universal installation command. cURL built with Schannel on Windows uses the Windows certificate store. Other builds commonly use a file-based CA bundle, while some TLS backends can use a native platform store. On Apple systems, behavior depends on whether the build uses Apple SecTrust.

Check the build before choosing a native-store option:

curl --version
curl --help all | grep -E 'ca-native|proxy-ca|cacert'

The command-line cURL configuration also may not affect PHP, Python, a container image, or another program using libcurl. Check that runtime’s libcurl version, TLS backend, CA file, and CA directory separately.

Retest without weakening verification

After configuring the CA, rerun the request with verbose output:

curl -v --proxy http://proxy.example:8080 \
  --cacert /path/to/approved-ca-bundle.pem \
  https://example.com/

Confirm that:

  • The intended proxy is selected.
  • The expected CA file or native store is used.
  • The certificate chain validates.
  • The hostname matches the requested host.
  • No --insecure or -k option is present.

Common errors and fixes

Symptom Likely cause Fix
unable to get local issuer certificate Missing issuer CA or incomplete chain Use the approved CA bundle with --cacert; ask the server owner to send the complete chain.
Failure occurs while connecting to an https:// proxy Proxy certificate is untrusted Use --proxy-cacert or the supported proxy native-store option.
Failure occurs after CONNECT Origin certificate is untrusted Use --cacert for the destination CA.
Works in a browser but not cURL Browser and cURL use different trust stores Identify cURL’s TLS backend and configure its CA source explicitly.
Works in a shell but not PHP or another app The runtime uses different libcurl settings Inspect and configure that runtime’s CA file, directory, and proxy settings.
Changing HTTPS_PROXY has no effect https_proxy, ALL_PROXY, or process-level configuration wins Print the environment, unset conflicting variables, and pass --proxy explicitly.
Hostname mismatch Certificate is for another hostname or inspection is misconfigured Correct DNS/proxy routing or obtain a certificate containing the requested hostname.
Certificate expired Server or proxy certificate is out of date Have the responsible administrator renew it; do not bypass verification.
CA option is reported as unknown Older cURL version or different build Check curl --version, upgrade through your platform process, or use the options supported by that build.

Why -k is not a fix

curl -k and curl --insecure disable certificate and hostname verification. Encryption may still be present, but cURL no longer confirms that the peer is the intended server. cURL explicitly recommends avoiding this, especially in production: curl.se/docs/sslcerts.html.

Use it only for a tightly controlled experiment when you understand the exposure, then remove it and configure the correct CA before deployment.

Performance, reliability, and operational notes

  • CA lookup: A local CA bundle avoids downloading trust data during each request. Keep it managed and updated.
  • Connection reuse: Reusing a cURL handle can reduce repeated proxy and TLS handshakes in applications using libcurl.
  • Retries: Retry transient proxy connection failures, but do not retry indefinitely on certificate errors. A trust failure is usually deterministic.
  • Logging: Keep verbose diagnostics in a protected environment and redact credentials, cookies, authorization headers, and private URLs.
  • Containers: Install the approved CA in the image or mount it at runtime, then point the process to the same path on every replica.
  • Rotation: Plan for corporate CA rotation by allowing an overlap period with old and new approved certificates.
  • Cost: Correct CA configuration avoids failed requests and repeated manual diagnostics. The CA itself is normally supplied by the organization operating the proxy or server.

Or skip the browser setup

If your goal is to capture a website image or PDF rather than debug a proxy connection, ScreenshotNeo provides a website screenshot API. It accepts one GET request and returns a PNG, JPEG, WebP, or PDF. Before capture it accepts cookie or consent banners and removes more than 60 known consent platforms, newsletter popups, and chat widgets. Bot checks, blank pages, failed loads, timeouts, and cache hits are not billed, and response headers identify the page verdict and billing result.

cURL:

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp

Python:

import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)

Node.js:

const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);

See the ScreenshotNeo API documentation for the request options. It also supports full-page and element capture, device presets, dark mode, retina scale, custom CSS and JavaScript, waits, request blocking, headers, cookies, user agents, timezone and geolocation, resizing, TTL caching, signed links, asynchronous jobs, webhooks, bulk capture, PDF settings, usage data, and an MCP server for AI agents.

There are 1,000 free screenshots each month with no card. Paid plans start at $5 for 3,000 screenshots. Create a free ScreenshotNeo account.

FAQ

Does error 60 prove that the proxy is down?

No. It reports a certificate verification failure. The proxy may be reachable while cURL rejects the proxy or destination certificate.

Which option should I use for a normal HTTP proxy?

Usually --cacert for the destination certificate. Use --proxy-cacert when the proxy URL itself uses HTTPS and its certificate is the failing peer.

Can I fix this by updating cURL?

Updating can refresh a bundled CA store or add options, but it cannot make an untrusted private CA trusted automatically. You still need the correct CA configuration.

Why does the same command behave differently on two machines?

cURL versions, TLS backends, native stores, CA bundle paths, proxy environment variables, and system clocks can differ. Compare curl --version, verbose output, and active environment variables.

How do I know whether the server chain is incomplete?

Compare the certificate chain shown in verbose output with the chain provided by the server administrator. If the server omits an intermediate CA, the durable fix is for the server owner to configure the complete chain.