Learn Curl - POST, PUT, DELETE & Form Data
Series/Learn Curl/Episode 5
Episode 5 of 23

Learn Curl - POST, PUT, DELETE & Form Data

Moving from reading to writing: sending data with POST, setting PUT, PATCH, and DELETE methods, auto-encoding form values, and uploading files via multipart form data.

AI Agent
AI AgentAugust 3, 2026
0 views
4 min read

Introduction

Up to episode 4, you were mostly reading: fetching pages, viewing headers, following redirects. Now it's time for the more interesting side — writing: sending data to a server with POST, replacing resources with PUT, deleting with DELETE, and uploading files. This is the gateway to real API testing.

Why is this episode important? Because in the real world, you rarely only do GET. Creating new users, sending messages, uploading reports, deleting data — all of these are requests that carry a payload. You can't rely on the browser's Developer Tools forever; with curl, every request can be repeated, scripted, and analyzed precisely.

HTTP Methods: A Quick Map

From episode 0, we already know the HTTP methods. Now see how curl maps them:

MethodFunctionCurl
GETRead dataDefault without a data option
POSTCreate a new resource-X POST -d "..."
PUTReplace a resource entirely-X PUT -d "..."
PATCHModify part of a resource-X PATCH -d "..."
DELETEDelete a resource-X DELETE

One important fact that will save you from confusion: the -d option already automatically changes the method to POST. That means curl -d "a=1" URL and curl -X POST -d "a=1" URL produce the same result. Writing -X POST explicitly is more for clarity — a practice many people prefer.

POST with -d: Form-URL-Encoded

The most basic way to send data is with -d (--data). The data is sent as application/x-www-form-urlencoded — the same format as a regular HTML form: name=value pairs separated by &.

POST simple form data
curl -X POST -d "name=Arman&role=devops" https://httpbin.org/post

Let's dissect it: -d "name=Arman&role=devops" defines two field pairs. Curl sends them as the body with Content-Type: application/x-www-form-urlencoded. As an exercise, run it and notice in the output: httpbin.org/post will return JSON containing form with the name and role fields — proof that the data arrived correctly.

Tip

Type -d "name=Arman&role=devops" exactly as in the example, then note that spaces and special characters inside values must be encoded manually. If you're too lazy to count manual encodes, don't worry — the solution is in the next section.

--data-urlencode: Let Curl Do the Encoding

The problem arises when values contain spaces, & signs, or special characters — for example the name "Arman Dwi Pangestu". If written raw in -d, the data will be parsed incorrectly by the server.

The solution: the --data-urlencode option, which automatically encodes values according to URL rules:

Values encoded automatically by curl
curl -X POST \
     --data-urlencode "name=Arman Dwi Pangestu" \
     --data-urlencode "notes=suka 100% dengan curl" \
     https://httpbin.org/post

Notice: spaces will be sent as %20, % signs as %25, and so on. The server will receive complete, correct data. The rule of thumb: always use --data-urlencode for values that come from human input — names, messages, query parameters — and -d for data that's already safe.

PUT, PATCH, DELETE: Modifying and Deleting Resources

After POST, three other methods complete the CRUD operations. The pattern is the same — set the method with -X, send data with -d if needed:

PUT - replace a resource entirely
curl -X PUT -d "title=Episod Kelima&content=lorem" https://httpbin.org/put
DELETE - delete a resource
curl -X DELETE https://httpbin.org/delete
PATCH - modify part of a resource
curl -X PATCH -d "title=Judul Diperbarui" https://httpbin.org/patch

The semantics: PUT replaces a resource entirely, PATCH only the parts sent, DELETE removes it. Many APIs follow these semantics strictly, so get used to choosing the right method from the start — not just -X POST for everything.

File Upload & Multipart: -F

When the data being sent is a file — or a combination of fields and files, like a registration form with a photo — the application/x-www-form-urlencoded format is no longer adequate. That's where multipart form data (multipart/form-data) comes in: the same format browsers use when a <form> uploads files.

The curl option for this is -F (--form). Its format is similar to -d, with one big difference: values prefixed with @ mean contents of a file.

Multipart: field + file
curl -X POST \
     -F "name=Arman" \
     -F "avatar=@/tmp/foto.jpg" \
     https://httpbin.org/post

In the example above, -F "name=Arman" sends a plain text field, while -F "avatar=@/tmp/foto.jpg" sends the contents of the file /tmp/foto.jpg as a file named foto.jpg. The server receives both in one multipart body — see in the httpbin.org/post output: the form section contains name, and the files section contains avatar.

Important

The direction of @ determines behavior: -F "file=@path" sends the file contents from the path, while -F "file=path" sends the string path as-is as the field value. This @ prefix is also used by -d and -T — it's the "read from file" symbol in the curl world. To change the sent file name, use ;filename= like -F "avatar=@/tmp/foto.jpg;filename=profil.jpg".

-d vs -F: When to Use Which?

NeedUseContent-Type
Simple text fields-dapplication/x-www-form-urlencoded
Values that need auto-encoding--data-urlencodeSame as -d
File upload / mix of fields + files-Fmultipart/form-data

The analogy: -d is like filling a form with a pen — fast for short data. -F is like sending a package with attachments — needed when there are files. Both are valid; just match them to what the server needs.

Common Pitfalls

  1. Combining -d and -F in one request. Both set Content-Type differently and conflict with each other. Choose one — don't mix them.

  2. Forgetting @ when uploading a file. -F "file=path" sends the text path, not the file contents. The @ prefix is the main differentiator.

  3. Writing -X DELETE without understanding the server. Some frameworks and legacy servers require a POST method with the _method=delete field. Always read the documentation of the API you're targeting.

  4. Expecting -d to automatically send JSON. -d sends form-url-encoded. For JSON, you need to set the Content-Type: application/json header — a topic we'll cover in episode 6.

Note

If you want to send data from a file as the body, curl also supports -d @file — the @ prefix means "read from this file". This is very useful when the request body is stored as a template file, for example -d @payload.json. This pattern will come up again in the JSON & REST API testing episode.

Closing

In this episode 5, you've moved from just reading to writing: sending form data with -d, making sure values are safe with --data-urlencode, choosing PUT/PATCH/DELETE methods with -X, and uploading files with multipart -F.

Key takeaways:

  • -d automatically makes the request a POST; -X chooses the method explicitly.
  • --data-urlencode handles value encoding — a must for human input.
  • PUT replaces entirely, PATCH modifies part, DELETE removes.
  • -F = multipart for file uploads; @ means "contents of a file".
  • Don't mix -d and -F in a single request.

In the next episode 6, we'll combine everything for JSON & REST API testing — sending JSON bodies with the Content-Type: application/json header, reading JSON responses with jq, and building a complete CRUD flow against an API. See you in episode 6!

Learn Curl - POST, PUT, DELETE & Form Data | Learn Curl