Send request data
Submit forms and files
Choose URL-encoded form data or multipart form data and upload a local file deliberately.
10 minute lesson
HTML-style forms commonly send data in one of two encodings. URL-encoded data packs fields into name=value pairs, the same format as a query string, sent as the request body. Multipart data splits the body into parts separated by a boundary, each with its own headers. Multipart is the normal choice when a field contains a file, because files are binary and do not survive URL encoding gracefully.
curl has one option for each: --data for URL-encoded, --form for multipart.
A simple form
For text-only fields, URL-encoded is what most login and search forms use:
curl --data 'title=Lab notes' --data 'author=mina' https://httpbin.org/post
The echo shows both fields under form, and the Content-Type header reads application/x-www-form-urlencoded.
A form with a file
Create a small file, then send one text field and one file:
echo 'first line of my notes' > notes.txt
curl --form 'title=Lab notes' --form '[email protected]' https://httpbin.org/post
The response should show a form value and file content separately:
{
"files": {
"attachment": "first line of my notes\n"
},
"form": {
"title": "Lab notes"
}
}
That split is your verification. title arrived as an ordinary field, and attachment arrived as a file part with its content intact. curl builds the multipart boundary and per-part headers for you — the fiddly parts of the format you never want to write by hand.
The @ prefix reads a local file and uploads it as a file part. If you want the file’s content as a plain text field instead, use < rather than @. And when the server cares about the file’s MIME type, state it: --form '[email protected];type=text/plain'.
The mistake to avoid
Check the path and destination before running a command copied from elsewhere. @ means “read this file from my disk and send it over the network” — pasted blindly, a command like --form 'config=@~/.ssh/id_ed25519' uploads your private key to whoever runs the server. curl also fails with 26 when the file does not exist, so a typo in the path shows up as a read error, not a silent empty upload.
One more trap: mixing --data and --form in the same command does not work. A request body has one content type. Pick the encoding the server expects and stick to it.
Lesson completed