How Curl Handles POST to GET Redirects

When using the curl command-line tool to send an HTTP POST request, encountering a redirect (3xx status code) can alter how the subsequent request is made. This article explains how curl handles the conversion of a POST request to a GET request during a redirect, how different HTTP status codes influence this behavior, and how you can control these transitions using specific command-line flags.

Default Redirection Behavior in Curl

By default, curl does not follow redirects unless you explicitly instruct it to do so using the -L or --location flag. When this flag is active, curl’s reaction to a redirect depends entirely on the specific HTTP status code returned by the server.

Here is how curl handles method conversion for each major redirect status code:

303 See Other

The 303 status code is explicitly designed to direct the client to a new URI using a GET request, regardless of the original request method. When curl receives a 303 redirect after a POST, it always converts the request method to GET for the subsequent request.

301 Moved Permanently & 302 Found

According to the strict HTTP specifications, 301 and 302 redirects should not result in a method change. However, historical web browser behavior routinely converted these POST requests to GET requests. To align with standard web browser behavior, curl defaults to converting POST requests to GET requests when following 301 and 302 redirects.

307 Temporary Redirect & 308 Permanent Redirect

These status codes were introduced to eliminate ambiguity. They explicitly forbid the client from changing the request method. When encountering a 307 or 308 redirect, curl preserves the POST method and resends the original payload to the new location.


Overriding the Default Behavior

If you need curl to deviate from its default behavior and maintain the POST method during 301, 302, or 303 redirects, you can use specialized command-line flags.

Example Commands

To send a POST request, follow redirects, and allow curl to convert the request to GET (default behavior for 301/302/303):

curl -L -X POST -d "param1=value1" https://example.com/submit

To send a POST request and force curl to preserve the POST method through 301 and 302 redirects:

curl -L --post301 --post302 -X POST -d "param1=value1" https://example.com/submit