CURLOPT_PROXY_SSLCERT(3)

πŸ’… CURLOPT_PROXY_SSLCERT β€” HTTPS proxy client certificate πŸ’…

Okay so real quick before we get into it: this page is from the Library Functions Manual, and yes bestie, it's literally called CURLOPT_PROXY_SSLCERT(3). Say that three times fast. Now let's get into the lore ✨


✨ SYNOPSIS ✨

#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_SSLCERT, char *cert);

That's it, that's the whole vibe. πŸŽ€


🌸 DESCRIPTION 🌸

Okay so listen closely because this is the part where people get confused and I refuse to let that be you 🫢

This option is for connecting to an HTTPS proxy β€” not an HTTPS server. Read that again. It's a proxy thing. If you're out here setting this thinking it's for your server cert, no babe, that's a different option entirely. Vibe check: failed. Try again. πŸ’€

You pass a pointer to a null-terminated string as the parameter. That string should be the filename of your client certificate β€” the one used to connect to the HTTPS proxy. Simple as that. πŸ‘‘

The default format is "PEM", and if that's not your situation you can change it with CURLOPT_PROXY_SSLCERTTYPE(3). Very demure, very configurable.

When you're using a client certificate, you most likely also need to provide a private key with CURLOPT_PROXY_SSLKEY(3). Like, they're a matching set. It's giving duo. It's giving main character energy with a plus-one. πŸ’–

Good news though β€” the application does not have to keep the string around after setting this option. Set it and forget it, it's fine, curl's got it. πŸ™ˆ

Oh and also β€” using this option multiple times makes the last set string override the previous ones. So if you're setting it in a loop and wondering why only one worked... yeah. That's why. 😭

And if you wanna bail on it entirely? Set it to NULL to disable its use again. Clean exit, no drama. πŸ¦‹


πŸŽ€ DEFAULT πŸŽ€

NULL

That's it. Nothing set, nothing happening. Iconic minimalist behaviour. ⭐


🌈 PROTOCOLS 🌈

This functionality affects all TLS based protocols: HTTPS, FTPS, IMAPS, POP3S, SMTPS etc. All of them. The whole squad. πŸ”₯

But β€” and this is the important bit β€” this option works only with the following TLS backends:

  • GnuTLS
  • OpenSSL
  • Schannel
  • mbedTLS
  • wolfSSL

If your backend isn't on that list, it's not a vibe, it's just not supported. πŸ’€


πŸ’œ EXAMPLE πŸ’œ

Here's a full lil' program so you can see the whole thing in context, unedited, exactly as it should be:

int main(void)
{
  CURL *curl = curl_easy_init();
  if(curl) {
    CURLcode result;
    curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
    curl_easy_setopt(curl, CURLOPT_PROXY, "https://proxy.example");
    curl_easy_setopt(curl, CURLOPT_PROXY_SSLCERT, "client.pem");
    curl_easy_setopt(curl, CURLOPT_PROXY_SSLKEY, "key.pem");
    curl_easy_setopt(curl, CURLOPT_PROXY_KEYPASSWD, "s3cret");
    result = curl_easy_perform(curl);
    curl_easy_cleanup(curl);
  }
}

See how it sets the URL, the proxy, the cert, the key, and the password? That's the whole little family together. Slay. 🫢

Ngl, "s3cret" is a whole mood but please don't actually ship that as your key password, bestie. 😭

⭐ AVAILABILITY ⭐

Added in curl 7.52.0. If you're on something older than that... girl. Upgrade. 🧚


πŸ¦‹ RETURN VALUE πŸ¦‹

curl_easy_setopt(3) returns a CURLcode indicating success or error. Very standard, very predictable.

CURLE_OK (0) means everything was OK β€” the good ending. 🌸

Non-zero means an error occurred, and you should go see libcurl-errors(3) for the full tea on what went wrong. Don't guess, just look it up. πŸ’…


πŸ”₯ SEE ALSO πŸ”₯

Go read them, they're all friends, they all make sense together. iykyk πŸ’–


Okay that's the whole page!! This one's libcurl, dated 2026-10-12, and it's the CURLOPT_PROXY_SSLCERT(3) page β€” go set up your proxy cert the right way and I'll be so proud of you. Periodt. πŸ‘‘βœ¨πŸŽ€

πŸ“¦ where this page comes from