Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
form-data vs -urlencoded

Nice answer on stackoverflow to the question of when to use one or the other content-types for POSTing data, viz. application/x-www-form-urlencoded and multipart/form-data.

“The moral of the story is, if you have binary (non-alphanumeric) data (or a significantly sized payload) to transmit, use multipart/form-data. Otherwise, use application/x-www-form-urlencoded.”


Matt Bridges' answer in full:

The MIME types you mention are the two Content-Type headers for HTTP POST requests that user-agents (browsers) must support. The purpose of both of those types of requests is to send a list of name/value pairs to the server. Depending on the type and amount of data being transmitted, one of the methods will be more efficient than the other. To understand why, you have to look at what each is doing under the covers.

For application/x-www-form-urlencoded, the body of the HTTP message sent to the server is essentially one giant query string -- name/value pairs are separated by the ampersand (&), and names are separated from values by the equal symbal (=). An example of this would be:

MyVariableOne=ValueOne&MyVariableTwo=ValueTwo

According to the specification:

[Reserved and] non-alphanumeric characters are replaced by `%HH', a percent sign and two hexadecimal digits representing the ASCII code of the character

That means that for each non-alphanumeric byte that exists in one of our values, it's going to take three bytes to represent it. For large binary files, tripling the payload is going to be highly inefficient.

That's where multipart/form-data comes in. With this method of transmitting name/value pairs, each pair is represented as a "part" in a MIME message (as described by other answers). Parts are separated by a particular string boundary (chosen specifically so that this boundary string does not occur in any of the "value" payloads). Each part has its own set of MIME headers like Content-Type, and particularly Content-Disposition, which can give each part its "name." The value piece of each name/value pair is the payload of each part of the MIME message. The MIME spec gives us more options when representing the value payload -- we can choose a more efficient encoding of binary data to save bandwidth (e.g. base 64 or even raw binary).

Why not use multipart/form-data all the time? For short alphanumeric values (like most web forms), the overhead of adding all of the MIME headers is going to significantly outweigh any savings from more efficient binary encoding.

The moral of the story is, if you have binary (non-alphanumeric) data (or a significantly sized payload) to transmit, use multipart/form-data. Otherwise, use application/x-www-form-urlencoded.

POST examples with curl

For details and more examples, see the POST section of the official tutorial.


In the examples below, suppose we need to POST data to https://foo.io/users/joyrexus/shoes, the canonical address for the shoes resource (a "collection" resource, in REST-speak) of a particular user (joyrexus):

URL=https://foo.io/users/joyrexus/shoes

Url-encoded

curl -d "brand=nike" -d "color=red" -d "size=11" $URL

curl --data "brand=nike&color=red&size=11" $URL

Multipart

curl --form "image=@nikes.png" --form "brand=nike" --form "color=red" --form "size=11" $URL

curl -F "image=@nikes.png" -F "brand=nike" -F "color=red" -F "size=11" $URL

Change the name field of a file upload part by setting filename=:

curl -F "image=@nikes.png;filename={desired-name}.png" -F "brand=nike" -F "color=red" -F "size=11" $URL

Specify Content-Type by using type=:

curl -F "image=@nikes.png;filename={desired-name}.png;type=image/png" -F "brand=nike" -F "color=red" -F "size=11" $URL

Sans data

curl --data '' $URL

curl -X POST $URL

curl --request POST $URL
@mboo2005

This comment has been minimized.

Copy link

mboo2005 commented Jan 4, 2016

Good

@redochka

This comment has been minimized.

Copy link

redochka commented Apr 8, 2016

Thank you!

@manters2000

This comment has been minimized.

Copy link

manters2000 commented May 20, 2016

Great sample and explanation.

@ankush981

This comment has been minimized.

Copy link

ankush981 commented Nov 30, 2016

Nice explanation!

@mdsaleemj

This comment has been minimized.

Copy link

mdsaleemj commented Dec 8, 2016

Nice explanation.Great !!!

@wellington1993

This comment has been minimized.

Copy link

wellington1993 commented Jan 5, 2017

Nice! Tanks!

@chandrajob365

This comment has been minimized.

Copy link

chandrajob365 commented Jul 26, 2017

Great explanation with examples

@joyrexus

This comment has been minimized.

Copy link
Owner Author

joyrexus commented Sep 5, 2017

@relativist

This comment has been minimized.

Copy link

relativist commented Oct 5, 2017

Please help me to encode filename of request. following request suite for only english chars:
curl -X POST http://someUrl.com
-H 'content-type: multipart/form-data; charset=utf-8; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW'
-F data='@/home/user/Downloads/tmp/Бамбук.xls'

@udayashankarsk

This comment has been minimized.

Copy link

udayashankarsk commented Oct 9, 2017

please explain. what is mean by "application/x-www-form-urlencoded"?

@maduhshan

This comment has been minimized.

Copy link

maduhshan commented Apr 3, 2018

nice explanation

@Heunsig

This comment has been minimized.

Copy link

Heunsig commented Aug 17, 2018

Thanks

@cigzigwon

This comment has been minimized.

Copy link

cigzigwon commented May 5, 2019

I just got a response from an API based in perl and it is non-urlencoded and is separated by line.... when is this acceptable? I say NEVER!

@jorgeas80

This comment has been minimized.

Copy link

jorgeas80 commented Jun 4, 2019

Many thanks. Really useful.

It would be great to do the same using Python requests library. Need to force multipart/form-data witohout sending a file using requests.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.