CURLINFO_CERTINFO(3)

πŸ’… CURLINFO_CERTINFO πŸ’…

Okay bestie, so this is a page from the Library Functions Manual β€” it's CURLINFO_CERTINFO(3) and it's literally all about peeking at the TLS certificate chain. Grab a snack, we're getting into it. πŸŽ€

✨ NAME ✨

CURLINFO_CERTINFO β€” the TLS certificate chain, bestie. That's the whole vibe.

🌸 SYNOPSIS 🌸

#include <curl/curl.h>

CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_CERTINFO,
                           struct curl_certinfo **chainp);

πŸ¦‹ DESCRIPTION πŸ¦‹

So here's the tea: you pass in a pointer to a struct curl_certinfo * and curl sets it to point at a struct holding all the info about the server's certificate chain β€” but only if you had CURLOPT_CERTINFO(3) enabled when the request was made. No cap, that part is non-negotiable. πŸ™ˆ

struct curl_certinfo {
  int num_of_certs;
  struct curl_slist **certinfo;
};

The certinfo struct member is an array of linked lists of certificate information. The num_of_certs struct member is the number of certificates β€” which is also the number of elements in the array. Iconic, honestly. πŸ’–

Each certificate's list has items with textual information in the format "name:content" β€” think "Subject:Foo", "Issuer:Bar", etc. The items in each list vary depending on the SSL backend and the certificate, so don't come for me if yours looks different. 🫢

🧚 PROTOCOLS 🧚

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

This option works only with the following TLS backends: GnuTLS, OpenSSL, Rustls and Schannel.

⭐ EXAMPLE ⭐

Here's the demo, and yes you can copy it straight up, it's giving main character energy:

int main(void)
{
  CURL *curl = curl_easy_init();
  if(curl) {
    CURLcode result;
    curl_easy_setopt(curl, CURLOPT_URL, "https://www.example.com/");

    /* connect to any HTTPS site, trusted or not */
    curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
    curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);

    curl_easy_setopt(curl, CURLOPT_CERTINFO, 1L);

    result = curl_easy_perform(curl);

    if(!result) {
      int i;
      struct curl_certinfo *ci;
      result = curl_easy_getinfo(curl, CURLINFO_CERTINFO, &ci);

      if(!result) {
        printf("%d certs!\n", ci->num_of_certs);

        for(i = 0; i < ci->num_of_certs; i++) {
          struct curl_slist *slist;

          for(slist = ci->certinfo[i]; slist; slist = slist->next)
            printf("%s\n", slist->data);
        }
      }
    }
    curl_easy_cleanup(curl);
  }
}

Also go look at the certinfo.c example, it's in the repo and it slays. πŸ’…

Heads up: that example turns off CURLOPT_SSL_VERIFYPEER and CURLOPT_SSL_VERIFYHOST on purpose β€” because it connects to any HTTPS site, trusted or not. It's a demo move, not a "do this in prod" move. πŸ’€

🌈 HISTORY 🌈

  • GnuTLS support added in 7.42.0.
  • Schannel support added in 7.50.0.
  • mbedTLS support added in 8.9.0.

πŸ‘‘ AVAILABILITY πŸ‘‘

Added in curl 7.19.1. She's been around a minute. ✨

πŸ’œ RETURN VALUE πŸ’œ

curl_easy_getinfo(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). Periodt. πŸ’…

πŸ”₯ SEE ALSO πŸ”₯


That's the whole page, bestie β€” go forth and read those certs. πŸ“

Big love from the libcurl gang, page dated 2026-10-12, documented under the libcurl banner. Mwah. πŸ’–

πŸ“¦ where this page comes from