How to Send a cURL POST Request
Tutorials

Vilius Dumcius
Key Takeaways
-
cURL is a versatile command-line tool that lets you easily send POST requests to transfer data directly from your terminal.
-
Use the -d and --json flags to attach form data or JSON payloads to your request body for seamless server communication.
-
Transition from the terminal to modern development environments by implementing POST requests in languages like PHP, Python, and JavaScript.
cURL is a command-line tool that lets you send requests to a server. It comes pre-installed in most modern operating systems, so it’s a great starting point for many networking projects.
While there are applications that perform the same goal with a fancier UI (e.g., Postman ), cURL is more reliable and lower-level, making it a strong choice for automation and many other use cases when sending a POST request.
Getting Started With cURL
cURL comes pre-installed in Windows 10 (and onwards) and most MacOS operating systems. While many Linux distributions include cURL out of the box, you may sometimes need to install it yourself. On Debian or Ubuntu-based systems, you can do this by running:
sudo apt-get install curl
For older Windows versions, you can download cURL from their official website. Once you’ve installed cURL, you can begin sending requests.
Finally, verify that everything is installed correctly by opening the terminal and inputting:
curl --help
On Windows, it’s highly recommended to use the Command Prompt instead of PowerShell. PowerShell historically aliases the curl command to its own Invoke-WebRequest tool, which will cause standard cURL syntax to fail unless you specifically type curl.exe.
Sending a cURL POST Request
All cURL usage follows the same structure: invoking cURL itself, setting the request options, and the URL, followed by additional options such as headers.
curl [request options] [URL] [other options]
Some options, such as the aforementioned --help, allow you to perform actions without URLs, but they won’t be used to send a POST request. There are three requirements for a POST request:
1. -X and POST
The former indicates you intend to send a request, and the latter the request method.
2. -d and Some String
The former indicates that you intend to send some data, and the string value is the content. Every POST request has to have some data that’s being sent. cURL POST data can be any string; however, APIs usually have their formatting requirements, so you’ll have to read the documentation.
3. URL
Usually, the API you’re sending your POST requests to.
For testing purposes, we’ll be using the sample ReqBin API URL. To send the most basic POST request, simply type in:
curl -X POST https://reqbin.com/echo/post/json -d "YOUR_STRING"
Many APIs will require you to send data in JSON format. To do it, you must explicitly set the Content-Type header so the server knows how to read your data. cURL defaults to a standard format:
curl -X POST https://reqbin.com/echo/post/json -H "Content-Type: application/json" -d '{"KEY1":"VALUE1", "KEY2":"VALUE2"}'
Adjusting a cURL POST Request With Advanced Settings
Some APIs will give (or require) more options to fully utilize their capabilities. A common POST request method requirement is to add headers.
You can do that by adding an -H and supplying header information for your POST request:
curl -X POST https://reqbin.com/echo/post/json -d "YOUR_STRING" -H "Content-Type: application/json"
Furthermore, whenever you're configuring a modern cURL command for transferring data, you can leverage the --json flag to simplify the process significantly.
Since cURL functions as a versatile command-line tool, it automatically establishes the Content-Type and Accept HTTP headers to application/json, and it ensures your JSON data gets processed correctly by the HTTP server.
Consequently, you won't have to manually write out verbose header declarations, which ultimately makes sending your data much cleaner.
You can also supply information such as user agents (e.g., 'User-Agent: Chrome') and the accepted character set (e.g., 'Accept-Charset: utf-8'). While you can set the user agent with -H, cURL also has a dedicated and shorter -A flag for this specific purpose (e.g., -A "Chrome"). The -H option has to be included with each type of header:
curl -X POST https://reqbin.com/echo/post/json -d '{"KEY1":"VALUE1", "KEY2":"VALUE2"}' -H "Content-Type: application/json" -H "Accept-Charset: utf-8"
Additionally, many APIs will have some form of authentication before you submit any POST request. Usernames and passwords are a common option for providing basic authentication credentials, which can be included as such:
curl --user "USERNAME:PASSWORD" -X POST https://reqbin.com/echo/post/json -d '{"KEY1":"VALUE1", "KEY2":"VALUE2"}' -H "Content-Type: application/json"
Another common option used for authentication is to send a specific header with an API access token. It’ll usually look something like this:
curl -X POST https://reqbin.com/echo/post/json -d '{"KEY1":"VALUE1", "KEY2":"VALUE2"}' -H "Content-Type: application/json" -H "API-Access-Token: YOUR_TOKEN"
Finally, you can use cURL to POST data directly from a local file to a remote file. If you’re sending raw data like a JSON text file, use the -d flag combined with the @ symbol:
curl -X POST https://reqbin.com/echo/post/json -H "Content-Type: application/json" -d @path/to/data.json
Alternatively, if you are simulating a file upload via an HTML form (like an image or document), use the -F option, which automatically formats the request as multipart/form-data:
curl -F "file=@path/to/image.png" https://reqbin.com/upload
cURL POST Request With Body
When you're transferring data over the web, the request body becomes the primary vehicle for your payload, and you'll typically use the -d flag to send raw body data directly.
You can also append multiple -d flags within a single cURL command. cURL seamlessly combines these pieces by joining them with an ampersand (&), which is perfect for standard form data. Be careful not to do it with JSON payloads, as the injected ampersands will invalidate your JSON structure.
Alternatively, if your text-based form data proves too large for the command line, you can instruct cURL to load the request body from a local text file by using the @ symbol (e.g., -d @data.txt). Note that if you need to send binary files or image data in the raw request body, you must use --data-binary @image.png instead, because the standard -d flag strips newlines and will corrupt binary data.
It effectively transmits the local file's contents as a structured HTTP request payload to update a remote file. Just remember that to guarantee your form data reaches the server securely, you must ensure your destination URL uses https://.
Handling intricate form data requires precision, and you'll find that organizing your form data beforehand eliminates frustrating syntax errors. Properly structured form data consistently ensures backend systems process your information correctly.
cURL POST Request in PHP
If you're transitioning away from the standard command line and building applications in PHP, you'll find that utilizing PHP's built-in cURL functions provides a strong environment for executing an HTTP request.
You'll need to initialize the session and configure your POST method options by setting CURLOPT_POST to true, which formally assigns the HTTP request method. Then you can attach your JSON data or complex form data to the request body using CURLOPT_POSTFIELDS, and then you must specify the necessary HTTP headers with CURLOPT_HTTPHEADER to ensure proper content delivery.
Sending data via PHP requires careful formatting before you attach it to CURLOPT_POSTFIELDS. If you pass a raw PHP array, cURL automatically formats the request as a multipart/form-data file upload. To send standard form data or JSON, you must first convert your array into a string using http_build_query() or json_encode(), respectively.
Finally, executing the configured HTTP method requires careful attention to detail, so supplying the correct user credentials or any required authentication method ensures your script interacts flawlessly with the endpoint.
To properly verify the endpoint's response within your script after configuring the HTTP method, you must set the CURLOPT_RETURNTRANSFER option to true before executing. Otherwise, PHP will print the raw response directly to the screen instead of saving it to a variable. Always remember to run curl_close() after executing your request to free up your server's memory.
cURL POST Request in Python
Python's requests library offers a streamlined alternative to traditional terminal scripts, and it simplifies the process of sending an HTTP request tremendously. To initiate the HTTP method, you simply invoke requests.post(), and you can effortlessly pass your JSON data directly through the json parameter.
If you're managing standard form data, the library conveniently accepts dictionaries via the data parameter instead. Furthermore, handling the server's response is straightforward. While the library doesn't automatically parse the payload for you, it provides simple built-in methods like calling .json() on the response object to instantly decode a JSON response into a usable Python dictionary without needing a complex cURL command.
It handles making POST requests seamlessly, and it easily accommodates advanced setups like dealing with image data or document uploads. Instead of using dictionaries for files, you simply pass your opened file objects to the dedicated files parameter, which automatically formats the request as multipart/form-data.
Because the requests library verifies SSL certificates by default, submitting your form data remains secure and protects user privacy as long as you are sending it to a valid https:// endpoint.
cURL POST Request in JavaScript
Modern web development frequently relies on JavaScript's native fetch API, and it provides a versatile mechanism for executing calls directly from the browser. Whenever you're constructing the call, you must explicitly set the method property to POST, which properly defines the HTTP request method for the transaction.
After establishing the HTTP method, you'll stringify your JSON data to format the request body correctly, and you'll append specific headers to declare the application/json content type. When handling FormData or intricate image data, however, you must intentionally omit the Content-Type header so the browser can automatically generate and append the necessary multipart boundaries.
Passing multipart form data dynamically enhances interactive web applications significantly.
Error Handling
When troubleshooting a failed POST request, it's important to understand where the error is coming from. If cURL encounters a local issue (like a disconnected network), it will output its own error code directly in the terminal. If the request reaches the HTTP server but is rejected, however, the server generates an HTTP error response (like a 400 or 404), which you can read in the returned body.
For example, if you were to send a POST request to Google’s domain without any data, you’d receive:
<title>Error 411 (Length Required)!!1</title>
[...]
<p>POST requests require a <code>Content-length</code> header. <ins>That's all we know.</ins>
Similarly, a cURL POST request with some data will give you a different error, stating that you’re not allowed to do that:
<title>Error 405 (Method Not Allowed)!!1</title>
[...]
<p>The request method <code>POST</code> is inappropriate for the URL <code>/</code>.
<ins>That's all we know.</ins>
Some APIs may provide the generic HTTP errors , while others will have custom-made responses informing you on how to change the request.
Wrapping Up
While we have overviewed many of the options, there’s even more available in cURL’s documentation . In practice, however, you’ll mostly modify the following cURL POST example:
curl --user "USERNAME:PASSWORD"
-X POST https://reqbin.com/echo/post/json
d '{"KEY1":"VALUE1", "KEY2":"VALUE2"}'
-H "Content-Type: application/json"
Most APIs will ask you to include authentication, payload details (which are nested under -d), a header stating the content type and the URL of the endpoint. You can easily adjust the POST request above as necessary to match the requirements of the API.
If you want to learn more about cURL, we recommend our cURL GET request blog post.