CURLOPT_HEADERFUNCTION(3)
β¨ CURLOPT_HEADERFUNCTION β¨
bestie, welcome to the libcurl header callback page π
this one lives in the Library Functions Manual and honestly? it's a whole vibe.
πΈ NAME πΈ
CURLOPT_HEADERFUNCTION β the callback that receives header data π
π¦ SYNOPSIS π¦
#include <curl/curl.h>
size_t header_callback(char *buffer,
size_t size,
size_t nitems,
void *userdata);
CURLcode curl_easy_setopt(CURL *handle, CURLOPT_HEADERFUNCTION,
header_callback);
π DESCRIPTION π
okay so first thing: you pass a pointer to your callback function, and it needs to match that prototype up there exactly. no freestyling the signature, bestie π
this callback gets invoked by libcurl as soon as it has received header data. and listen β the header callback is called once for each header, and only complete header lines get passed on to the callback. parsing headers? genuinely easy to do with this callback. buffer points to the delivered data, and the size of that data is nitems; size is always 1. two things to keep in your head: the header line you get is not null-terminated, and you do not modify the passed-in buffer. periodt π
ββοΈ
the pointer named userdata is the one you set with the CURLOPT_HEADERDATA(3) option.
your callback should return the number of bytes actually taken care of. if that amount differs from the amount passed to your callback function, it signals an error condition to the library π¬ that makes the transfer get aborted and the libcurl function used returns CURLE_WRITE_ERROR.
you can also abort the transfer by returning CURL_WRITEFUNC_ERROR. (that's since 7.87.0 β¨)
a complete HTTP header passed to this function can be up to CURL_MAX_HTTP_HEADER (100K) bytes, and it includes the final line terminator.
if this option is not set, or if it's set to NULL, but CURLOPT_HEADERDATA(3) is set to anything but NULL β then the function used to accept response data is used instead. that means the function specified with CURLOPT_WRITEFUNCTION(3), or if it's not specified or NULL β the default, stream-writing function. iykyk π«Ά
β οΈ important to note, bestie: the callback is invoked for the headers of all responses received after initiating a request, not just the final response. this includes all responses that occur during authentication negotiation. if you need to operate on only the headers from the final response, you gotta collect headers in the callback yourself and use HTTP status lines, for example, to delimit response boundaries. no cap.
for an HTTP transfer, the status line and the blank line preceding the response body are both included as headers and passed to this function.
when a server sends a chunked encoded transfer, it may contain a trailer. that trailer is identical to an HTTP header, and if such a trailer is received it's passed to the application using this callback as well. several ways to detect it's a trailer and not an ordinary header: 1) it comes after the response-body. 2) it comes after the final header line (CR LF) 3) a Trailer: header among the regular response-headers mentions what header(s) to expect in the trailer. detective mode fr π
for non-HTTP protocols like FTP, POP3, IMAP and SMTP, this function gets called with the server responses to the commands that libcurl sends.
a more convenient way to get HTTP headers might be to use curl_easy_header(3). just saying π
π§ LIMITATIONS π§
libcurl does not unfold HTTP "folded headers" (deprecated since RFC 7230). a folded header is a header that continues on a subsequent line and starts with a whitespace. such folds are passed to the header callback as separate ones, even though strictly they're just continuations of the previous lines. it's giving deprecated for a reason π
π DEFAULT π
Nothing. literally nothing, bestie.
β PROTOCOLS β
this functionality affects ftp, http, imap, pop3 and smtp
π EXAMPLE π
static size_t header_callback(char *buffer, size_t size,
size_t nitems, void *userdata)
{
/* received header is 'nitems' bytes in 'buffer' NOT NULL-TERMINATED */
/* 'userdata' is set with CURLOPT_HEADERDATA */
return nitems;
}
int main(void)
{
CURL *curl = curl_easy_init();
if(curl) {
curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, header_callback);
curl_easy_perform(curl);
}
}
π AVAILABILITY π
added in curl 7.7.2 β a true icon of the era π
π₯ 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).
π«Ά SEE ALSO π«Ά
and that's the whole page, bestie π this was libcurl, dated 2026-10-12, and the manual name is CURLOPT_HEADERFUNCTION(3) β slay, go forth and parse those headers β¨π¦
π¦ where this page comes from
- fedora 44: libcurl-devel 8.18.0-14.fc44 Β· curl
- fedora 44: libcurl-devel 8.18.0-14.fc44 Β· curl
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms