CURLOPT_CAINFO(3)

πŸ’… CURLOPT_CAINFO β€” like, the whole manual, but make it make sense

okay bestie so this is CURLOPT_CAINFO(3) from the Library Functions Manual, and it's genuinely one of those options you need to know if you're doing anything TLS. sit down, grab a strawberry drink πŸ“, and let me tell you about the file that holds your certificates ✨


✨ NAME ✨

CURLOPT_CAINFO β€” literally the path to your Certificate Authority (CA) bundle πŸŽ€


🌸 SYNOPSIS 🌸

#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_CAINFO, char *path);

that's it. that's the whole vibe. you hand it a char * and it slays πŸ’…


πŸ¦‹ DESCRIPTION πŸ¦‹

So you pass a char pointer to a null-terminated string that names a file β€” and that file is holding one or more certificates that you're gonna use to verify the peer with. that's the whole job, no cap πŸ”₯

now here's the little loophole πŸ‘€: if CURLOPT_SSL_VERIFYPEER(3) is zero and you're avoiding verifying the server's certificate anyway, then CURLOPT_CAINFO(3) doesn't even have to point at an accessible file. like, it can be pointing at nothing, bestie, because you already decided not to verify. do with that what you will πŸ™ˆ

by default this option is set to the system path where libcurl's CA certificate bundle is assumed to be stored β€” and that path was established at build time. so it's not magic, it's just... pre-agreed, iykyk.

(Schannel) okay Windows girlies listen up 🫢 β€” this option is supported for Schannel on Windows 7 or later, but we genuinely recommend not using it until Windows 8, since it works better starting then. and if the option is not set, curl just uses the certificates in the Windows' store of root certificates (that's the default for Schannel). iconic of it honestly πŸ‘‘

the application does not have to keep the string around after setting this option. it doesn't need to babysit it, it's fine, it's independent now 🧚

if you use this option multiple times, the last set string overrides the previous ones. and if you set it to NULL, you disable its use again. so yes, you can undo it. slay.

and if you ever wanna know what the default value actually is, you can figure it out with CURLINFO_CAINFO(3) β€” that's literally what it's for ⭐


πŸŽ€ DEFAULT πŸŽ€

Built-in system specific. and when curl is built with Schannel, this option is not set by default πŸ’€


🌈 PROTOCOLS 🌈

this functionality affects all TLS based protocols: HTTPS, FTPS, IMAPS, POP3S, SMTPS etc. β€” etc!! the whole squad πŸ‘‘

and good news: all TLS backends support this option. every single one. no backend erasure here πŸ’–


πŸ’œ EXAMPLE πŸ’œ

here's the whole thing in action, don't touch the code, it's perfect:

int main(void)
{
  CURL *curl = curl_easy_init();
  if(curl) {
    curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
    curl_easy_setopt(curl, CURLOPT_CAINFO, "/etc/certs/cabundle.pem");
    curl_easy_perform(curl);
    curl_easy_cleanup(curl);
  }
}

the way that "/etc/certs/cabundle.pem" is just sitting there being the whole point of the page 😭🫢


🧚 HISTORY 🧚

Schannel support was added in libcurl 7.60. periodt.


⭐ AVAILABILITY ⭐

Added in curl 7.4.2 β€” yes, that's old old, it's been around forever, main character energy since day one πŸ‘‘


πŸ’… RETURN VALUE πŸ’…

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

  • CURLE_OK (0) means everything was OK β€” the good ending 🌸
  • non-zero means an error occurred β€” and you can go look it up in libcurl-errors(3) πŸ”

πŸ”₯ SEE ALSO πŸ”₯

all bangers, read them all, no skips πŸ’–


ngl the takeaway is: give curl a path to your CA bundle, don't overthink it, and if you're on Schannel just... wait for Windows 8. trust 🫢

and that's the page!! brought to you by libcurl, dated 2026-10-12, filed under CURLOPT_CAINFO(3) πŸŽ€βœ¨ go forth and verify your peers, bestie πŸ’œ

πŸ“¦ where this page comes from