CURLOPT_CAINFO_BLOB(3)

πŸ’… CURLOPT_CAINFO_BLOB(3) πŸŽ€

okay bestie, welcome to the libcurl manual page for CURLOPT_CAINFO_BLOB β€” yes it's a Library Functions Manual page, yes it's iconic, let's go ✨

✨ NAME ✨

CURLOPT_CAINFO_BLOB β€” your Certificate Authority (CA) bundle, but make it PEM format πŸ¦‹

🌸 SYNOPSIS 🌸

#include <curl/curl.h>

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

πŸ’– DESCRIPTION πŸ’–

So what you're doing here is passing a pointer to a curl_blob struct, right? That struct holds the info (a pointer and a size) about a memory block containing binary data of PEM encoded content β€” and that content holds one or more certificates you'll use to verify the HTTPS server with. No cap, that's the whole vibe. πŸ‘‘

Here's the slay detail: 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. Copy it and forget it, main character energy fr fr πŸ’…

Also, if CURLOPT_SSL_VERIFYPEER(3) is zero and you avoid verifying the server's certificate, then CURLOPT_CAINFO_BLOB(3) is not needed. Like, at all. Skip it. πŸ€·β€β™€οΈ

🚨 lowkey important: this option overrides CURLOPT_CAINFO(3). It's giving "there can only be one" β€” so know which one you're actually setting bestie.

πŸ“ DEFAULT πŸ“

NULL

🌈 PROTOCOLS 🌈

This functionality affects all TLS based protocols: HTTPS, FTPS, IMAPS, POP3S, SMTPS etc. basically the whole secure squad 🫢

This option works only with the following TLS backends: GnuTLS, OpenSSL, Rustls, Schannel, mbedTLS and wolfSSL. Check your backend bestie, iykyk ⭐

🧚 EXAMPLE 🧚

#include <string.h>

int main(void)
{
  char *strpem = "PEMDATA"; /* strpem must point to a PEM string */
  CURL *curl = curl_easy_init();
  if(curl) {
    CURLcode result;
    struct curl_blob blob;
    curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
    blob.data = strpem;
    blob.len = strlen(strpem);
    blob.flags = CURL_BLOB_COPY;
    curl_easy_setopt(curl, CURLOPT_CAINFO_BLOB, &blob);
    result = curl_easy_perform(curl);
    curl_easy_cleanup(curl);
  }
}

see how blob.flags = CURL_BLOB_COPY is right there? that's the moment, that's the whole thing πŸ”₯

πŸ¦‹ HISTORY πŸ¦‹

This option is supported by the mbedTLS backend (since 7.81.0), the Rustls backend (since 7.82.0), the wolfSSL backend (since 8.2.0), the GnuTLS backend (since 8.18.0), and also the OpenSSL and Schannel backends. Look at this timeline, it's giving growth arc πŸ’œ

πŸ‘‘ AVAILABILITY πŸ‘‘

Added in curl 7.77.0. vintage-ish but not vintage, we love a classic πŸŽ€

πŸ’€ RETURN VALUE πŸ’€

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

CURLE_OK (0) means everything was OK 😌 β€” and non-zero means an error occurred, so go see libcurl-errors(3) for the tea. Don't ignore the non-zero, bestie, that's how you end up crying at 3am 😭

⭐ SEE ALSO ⭐


and that's the page!! 🫢 this came to you from libcurl, dated 2026-10-12, titled CURLOPT_CAINFO_BLOB(3) β€” go forth and verify those certs, you absolute icon πŸŒŸπŸ’–

πŸ“¦ where this page comes from