How to Make a POST Request with curl

By 

Updated on

5 min read

curl POST

curl is a command-line utility for transferring data from or to a remote server using one of the supported protocols. It is installed by default on Windows, macOS, and most Linux distributions.

System administrators, developers, and other users use curl to test APIs , view response headers, and make HTTP requests.

This article explains how to use curl to make POST requests.

Making a POST Request

The HTTP POST method is used to send data to the remote server. The general form of the curl command for making a POST request is as follows:

Terminal
curl -X POST [options] [URL]

The -X option specifies which HTTP request method to use when communicating with the remote server. In most cases, you do not need to set -X POST explicitly because curl automatically uses POST when you provide data with the -d or -F options.

Sending Form Data

A typical POST request is sent via an HTML form, and the data is encoded in the application/x-www-form-urlencoded format. The data keys and values are encoded in key-value pairs, separated by the & symbol and with = between the key and the value.

To send a POST request with curl, use the -d (--data) option to specify the data:

Terminal
curl -d 'name=linuxize&email=linuxize@example.com' https://example.com/form/

In the example above, we are sending data to the remote server consisting of two key-value pairs: name=linuxize and email=linuxize@example.com.

You can also send the data using multiple -d options:

Terminal
curl -d 'name=linuxize' -d 'email=linuxize@example.com' https://example.com/form/

When sending data with the -d option, you should correctly URL-encode all non-alphanumeric characters in both keys and values. For instance, if you are sending a name with spaces (“John Doe”), the command will look like this:

Terminal
curl -d 'name=John%20Doe' https://example.com/form/

Manually encoding the data can be inconvenient. The --data-urlencode option tells curl to encode the provided data automatically:

Terminal
curl --data-urlencode 'name=John Doe' https://example.com/form/

When you use --data-urlencode, only the value part is encoded. curl expects the key to be already URL encoded.

If you are sending a large number of key-value pairs, you can store the data in a file and pass it to curl with the @ prefix:

Terminal
curl -d @form_data.txt https://example.com/form/

When the data starts with @, curl reads the data from the specified file on the local system.

Sending Multipart Form Data

The content type multipart/form-data is used when the form data contains binary files or other large payloads.

To create a multipart POST request, use one or more -F (--form) options followed by key=value pairs. When the -F option is used, curl sends the data using the multipart/form-data Content-Type.

The following example shows how to make a POST request to a form that has “name” and “image” fields:

Terminal
curl -F 'name=linuxize' -F 'image=@photo.jpg' https://example.com/form/

Uploading Files

To POST a file with curl, add =@ before the file location. The file can be an archive, image, document, or any other type:

Terminal
curl -F 'image=@/home/user/Pictures/wallpaper.jpg' https://example.com/upload/

Sending JSON Data

JSON is a text-based data format commonly used for data transfers between web services and APIs.

You can send JSON data using the --json option:

Terminal
curl --json '{"website": "linuxize.com"}' https://example.com/api/

curl sends the JSON data as-is, so make sure it is in valid JSON format. The --json option automatically sets the Content-Type and Accept headers to application/json.

You can use multiple --json options in one command:

Terminal
curl --json '{"name": "John"}' --json '{"age": "36"}' https://example.com/api/

The JSON data can also be read from a local file:

Terminal
curl --json @json_data.txt https://example.com/api/

If you are using curl in a script, you can pipe JSON data from another command:

Terminal
echo '{"website": "linuxize.com"}' | curl --json @- https://example.com/api/

The @- part tells curl to read the body from standard input.

Quick Reference

TaskSyntax
POST form datacurl -d 'key=value' URL
POST multiple fieldscurl -d 'k1=v1' -d 'k2=v2' URL
URL-encode datacurl --data-urlencode 'key=value' URL
POST data from filecurl -d @file.txt URL
Multipart form uploadcurl -F 'file=@photo.jpg' URL
POST JSONcurl --json '{"key":"val"}' URL
POST JSON from filecurl --json @data.json URL
POST JSON from stdinecho '{}' | curl --json @- URL

Troubleshooting

HTTP 415 Unsupported Media Type
The server expects a different content type. For JSON, use --json or add -H 'Content-Type: application/json'. For form data, use -d for URL-encoded data or -F for multipart data.

HTTP 400 Bad Request
The payload is malformed or missing required fields. Validate the JSON syntax, ensure all required fields are present, and double-check URL encoding for special characters.

curl: (6) Could not resolve host
The URL is invalid or DNS cannot resolve it. Verify the URL spelling and check your network or DNS configuration.

curl: (35) SSL connect error
This usually indicates a TLS negotiation problem. Ensure the system time is correct and that the server supports modern TLS. As a last resort for testing, add -k, but do not use it in production.

FAQ

What is the difference between -d and -F in curl?
The -d option sends data as application/x-www-form-urlencoded, which is the default encoding for HTML forms. The -F option sends data as multipart/form-data, which is required for file uploads.

Do I need to use -X POST with curl?
No. When you provide data with -d, -F, or --json, curl automatically uses the POST method. You only need -X POST when sending a POST request with no body.

How do I send a POST request with authentication?
Use the -u option for basic authentication: curl -u username:password -d 'data' URL. For bearer tokens, use -H 'Authorization: Bearer TOKEN'.

What curl version supports the --json option?
The --json option was introduced in curl 7.82.0 (March 2022). For older versions, use -d '{"key":"value"}' -H 'Content-Type: application/json' instead.

Conclusion

Use the -d option to send URL-encoded form data, -F for multipart form data and file uploads, and --json for JSON payloads. For more information, visit the curl Documentation page.

If you have any questions or feedback, feel free to leave a comment.

Tags

Linuxize Weekly Newsletter

A quick weekly roundup of new tutorials, news, and tips.

About the authors

Dejan Panovski

Dejan Panovski

Dejan Panovski is the founder of Linuxize, an RHCSA-certified Linux system administrator and DevOps engineer based in Skopje, Macedonia. Author of 800+ Linux tutorials with 20+ years of experience turning complex Linux tasks into clear, reliable guides.

View author page