CURLOPT_POSTREDIR(3)

πŸ’… CURLOPT_POSTREDIR(3) β€” the curl manual, bestie edition ✨

okay so you're in the Library Functions Manual for curl, and today's main character is CURLOPT_POSTREDIR β€” literally the option that decides how your POST behaves when a redirect tries to humble it. πŸŽ€


🌸 NAME 🌸

CURLOPT_POSTREDIR β€” how to act on an HTTP POST redirect

✨ SYNOPSIS ✨

#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_POSTREDIR,
                          long bitmask);

πŸ¦‹ DESCRIPTION πŸ¦‹

So you pass in a bitmask and it controls how libcurl acts on redirects after POSTs that get a 301, 302 or 303 response back. Bestie, it's a whole little bitfield situation and every bit is doing its own thing:

  • a parameter with bit 0 set (value CURL_REDIR_POST_301) tells the library to respect RFC 7231 (section 6.4.2 to 6.4.4) and not convert POST requests into GET requests when following a 301 redirection
  • setting bit 1 (value CURL_REDIR_POST_302) makes libcurl maintain the request method after a 302 redirect
  • setting bit 2 (value CURL_REDIR_POST_303) makes libcurl maintain the request method after a 303 redirect

and the value CURL_REDIR_POST_ALL is a convenience define that sets all three bits at once β€” the "just do all of it" icon that it is πŸ‘‘

The non-RFC behavior is, quote unquote, ubiquitous in web browsers, so the library does the conversion by default to maintain consistency. BUT β€” and this is the plot twist β€” a server may require a POST to remain a POST after such a redirection. So this option is meaningful only when setting CURLOPT_FOLLOWLOCATION(3). No followlocation, no redirect, no drama, this whole thing just vibing unused. πŸ™ˆ

πŸ“ DEFAULT πŸ“

0

🌈 PROTOCOLS 🌈

This functionality affects http only. that's it. that's the protocol. πŸ’…

🧚 EXAMPLE 🧚

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

    /* a silly POST example */
    curl_easy_setopt(curl, CURLOPT_POSTFIELDS, "data=true");

    /* example.com is redirected, so we tell libcurl to send POST on 301,
       302 and 303 HTTP response codes */
    curl_easy_setopt(curl, CURLOPT_POSTREDIR, CURL_REDIR_POST_ALL);

    curl_easy_perform(curl);
  }
}

πŸ’œ HISTORY πŸ’œ

ngl the lore here is kind of iconic:

  • this option was known as CURLOPT_POST301 up to 7.19.0 β€” because back then it only supported the 301, that was its whole personality
  • CURL_REDIR_POST_303 was added in 7.26.0 ✨
  • the CURL_REDIR_* macros became long types in 8.16.0 β€” prior to this version a long cast was necessary when passed to curl_easy_setopt(3)

⭐ AVAILABILITY ⭐

Added in curl 7.19.1

πŸ”₯ RETURN VALUE πŸ”₯

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

CURLE_OK (0) means everything was OK β€” slay. Non-zero means an error occurred, so go see libcurl-errors(3) and figure out what went down. 😭

🌸 SEE ALSO 🌸


and that's the page, bestie 🫢 this was libcurl, dated 2026-10-12, filed under CURLOPT_POSTREDIR(3) β€” go keep those POSTs POSTing, mwah πŸ’–

πŸ“¦ where this page comes from