CURLOPT_SSLCERT_BLOB(3)

πŸ’… CURLOPT_SSLCERT_BLOB(3) πŸ’…

okay so this one is from the libcurl Library Functions Manual, and bestie it is genuinely a slay β€” it's literally about handing curl your client certificate straight from memory instead of making it go find a file. no cap, this is the glow-up option. ✨


🌸 NAME 🌸

CURLOPT_SSLCERT_BLOB β€” SSL client certificate from memory blob

like, the cert lives in RAM. in a blob. iconic. 🫢


πŸŽ€ SYNOPSIS πŸŽ€

#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SSLCERT_BLOB,
                          struct curl_blob *stblob);

πŸ’– DESCRIPTION πŸ’–

So here's the vibe: you pass a pointer to a curl_blob structure, and that struct holds both a pointer and a size for your client certificate. pointer + size, that's the whole energy. πŸ¦‹

Now the format thing, and this is important so listen up:

  • the format must be "P12" on Schannel
  • the format must be "P12" or "PEM" on OpenSSL
  • the format must be "DER" or "PEM" on mbedTLS

and you tell curl which one it is with CURLOPT_SSLCERTTYPE(3). periodt. πŸ’…

if the blob is initialized with the flags member of struct curl_blob set to CURL_BLOB_COPY, then the application does not have to keep the buffer around after setting this. so curl copies it for you. the way that saves you from a whole use-after-free situation 😭 chef's kiss.

also this option is an alternative to CURLOPT_SSLCERT(3), which instead expects a filename as input. so like, same goal, different delivery method. main character energy either way. πŸ‘‘


✨ DEFAULT ✨

NULL

(nothing set, obviously. we start from nothing and we build 🌈)


🧚 PROTOCOLS 🧚

This functionality affects all TLS based protocols: HTTPS, FTPS, IMAPS, POP3S, SMTPS etc.

heads up bestie β€” this option works only with the following TLS backends: OpenSSL, Schannel, mbedTLS and wolfSSL. if your backend isn't on that list, it's giving not supported, sorry πŸ’€

πŸ“ EXAMPLE πŸ“

extern char *certificateData; /* point to data */
extern size_t filesize; /* size of data */

int main(void)
{
  CURL *curl = curl_easy_init();
  if(curl) {
    CURLcode result;
    struct curl_blob stblob;
    stblob.data = certificateData;
    stblob.len = filesize;
    stblob.flags = CURL_BLOB_COPY;
    curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
    curl_easy_setopt(curl, CURLOPT_SSLCERT_BLOB, &stblob);
    curl_easy_setopt(curl, CURLOPT_SSLCERTTYPE, "P12");
    curl_easy_setopt(curl, CURLOPT_KEYPASSWD, "s3cret");
    result = curl_easy_perform(curl);
    curl_easy_cleanup(curl);
  }
}

see how stblob.flags = CURL_BLOB_COPY; is right there? that's the one that means you can yeet the buffer afterwards. love that for you. πŸ”₯


⭐ AVAILABILITY ⭐

Added in curl 7.71.0

(vintage-ish but not ancient, we stan a modern classic πŸ’œ)


πŸ’€ RETURN VALUE πŸ’€

curl_easy_setopt(3) returns a CURLcode indicating success or error.

CURLE_OK (0) means everything was OK, non-zero means an error occurred, see libcurl-errors(3).

so like, check your return value, bestie. CURLE_OK = we ate. non-zero = go read the error page 😭


πŸ¦‹ SEE ALSO πŸ¦‹


mwah πŸ’‹ that's the page β€” brought to you by libcurl, dated 2026-10-12, and yeah the footer says CURLOPT_SSLCERT_BLOB(3) one more time because it loves a grand entrance. go forth and blob responsibly πŸŽ€βœ¨

πŸ“¦ where this page comes from