14 August 2009
The Definitive Guide to GET vs POST
Unfortunately there is a lot misuse of GET over POST and vice versa. Both HTTP methods can achieve the same goals, but an incorrect choice between them can lead to unexpected and potentially harmful outcomes.
So, to make sure we get things right, I present to you the definitive guide of choosing between GET and POST.
Editor’s Note: Mike McDerment of FreshBooks.com will be teaching a 1/2 day workshop on ‘How to Build a Web App from A-Z’ at The Future of Web Apps.
Note: Remember that query strings (i.e. name/value pairs) get transferred in the URL of GET requests:
Host: carsonified.com
and in the body of POST requests:
Host: carsonified.com
name1=value1&name2=value2
GET vs POST Basics
In between new additions to our vocabularies (think “idempotent“), sections 9.1, 9.3 & 9.5 of RFC 2616 help us to conclude the first rule of GET vs POST…
Rule #1: Use GET for safe actions and POST for unsafe actions.
The RFC instructs internet browsers to make users aware that, when reissuing a previously made POST request, that the action (e.g. placing an order) is potentially unsafe. Hence the existence of dialogue boxes like this:
However, whilst browser compliance with this RFC instruction might explain why POST should be used for unsafe actions, why shouldn’t we use POST for safe ones?
Simply put, because GET requests are more useable:
- GET requests can be cached
- GET requests can remain in the browser history
- GET requests can be bookmarked
- GET requests can be distributed & shared
- GET requests can be hacked (ask Jakob!)
Note: If you need the best of both worlds, an unsafe action can be made safe by making it idempotent, so that it makes no difference how many times it’s requested. You do this by giving the request a unique ID and using server-side validation to ensure that a request with that ID hasn’t already been processed. In fact, if you’re in search of excellence, all unsafe actions should be made idempotent as nothing can stop users from ignoring warnings.
GET vs POST Extended
Rule #2: Use POST when dealing with sensitive data.
Because query strings are transferred openly in GET requests, we have to consider our security and that of our users when dealing with sensitive data like passwords or credit card numbers:
- Our users… because they may not realise that they are sharing sensitive data when they share a URL or that it can be viewed in the browser history by other people using the same computer.*
- Ourselves… because we may be breaking laws by unexpectedly storing data that we’re not allowed to (like credit card CV2s) in log files.
* This doesn’t apply when working within an AJAX environment.
Rule #3: Use POST when dealing with long requests.
Although the RFC doesn’t lay down any length-related guidelines, Internet Explorer – with its insistence on finding ways to make things difficult for us – enforces a maximum URL length of 2,048 characters.
Rule #4: Use GET in AJAX environments.
When using XMLHttpRequest, browsers implement POST as a two-step process (sending the headers first and then the data). This means that GET requests are more responsive – something you need in AJAX environments.
Summary
Although rules usually exist for good reasons, it’s good to know the logic behind them so they can be embraced fully. I, myself, hate rules that don’t have explanations and I hope that the above helps to justify the rules of GET vs POST.
Choosing between methods is a systematic process which should be part of second nature. Until then, this little workflow can be used:

We're big fans of 


Yoan Blanc
# August 14, 2009 - 9:09 am
I you try to display an HTTP request; please don’t forget the *two* line feeds between the head and the body.
Fahed
# August 14, 2009 - 2:33 pm
Agreed. The second line break got lost along the way.
Ricky Martin
# August 19, 2009 - 9:08 am
i liked the idea
Vincent Robert
# August 14, 2009 - 9:52 am
Wait wait wait! You can use query variables in the URI for POST requests too. The important thing to remember is that the URI is used to identify a resource while posted content is intended to be processed by the resource.
Which means you can POST “first=Vincent&last=Robert” to “/users?country=FR”. This is a way to say to the resource “list of users from France” to process (maybe add in this case) this user content.
I think REST describes it right. GET is only about URIs, it is about getting the representation of a resource identified by a URI. Now some prefer pretty URIs but using query variables is perfectly legal in HTTP.
POST is about processing. It is about sending content to a resource for processing. Again, this resource can have a URI using query variables.
Jason Karns
# August 14, 2009 - 12:53 pm
I’d like to second what Vincent said about POST and GET. Querystrings are not tied to one particular type of request. All types of HTTP requests (POST, PUT, DELETE, et. al.) can have querystrings. The querystring is part of the URI and is NOT passed in the body as per the article. The querystring and the POST body are two separate pieces. True, they are both name/value pairs, but please don’t conflate the two.
For further reading… http://www.sitepoint.com/blogs/2009/02/05/on-get-and-post/
Fahed
# August 14, 2009 - 2:26 pm
Hi Jason,
Thanks for your comment.
You’ve got me a bit lost on the following statement, though:
“The query string is part of the URI and is NOT passed in the body as per the article.”
Are you referring to GET, POST or both?
Jason Karns
# August 18, 2009 - 1:08 am
As you mentioned, Fahed, replies can’t nest deeper than 3 levels, so I’m replying to myself ;-)
As I mentioned in my first comment/reply “The query string is part of the URI and is NOT passed in the body as per the article.” I am referring to all HTTP Requests, irrespective of method (GET, POST, PUT, DELETE, or other). All HTTP Requests target a URI. Per RFC 2396 (section 3), a URI is defined as: ://?
So all Requests have URIs and all URIs ‘may’ have querystrings, including POSTs. There is no difference between GET and POST as to how the querystring is handled. A POST request’s body is comprised of the name/value pairs of a serialized form element. In order to generate a POST request that contains a querystring separate from the body, create a form where the @action attribute is such: “handler.php?article=DefinitiveGuide”. If you were to inspect the body of this post request via Fiddler (or other) you’ll notice that the body does not contain an ‘article’ key (unless also specified as a form field). This can lead to some interesting server-side code, especially if you have querystring keys colliding with form fields of the same name. PHP makes this even more confusing by naming its querystring autoglobal $_GET which doesn’t neccisarily imply a GET request. Given my previous form example, $_GET would contain a key for ‘article’ and $_POST would contain the fields of the form. See this post on SitePoint regarding GET/POST with PHP in particular: http://www.sitepoint.com/blogs/2009/02/05/on-get-and-post/
I don’t disagree with any other point in your article. I even agree with your security point in GET. As Robert Taylor said “Securing data is a multi-faceted vigil”. Simply preventing browser auto-complete of sensitive information is one (if minor) defense. But I digress…
My only reason for posting is to illuminate yet another misconception regarding GET/POST and the ever lovely querystring.
Feel free to email me or twitter (@jasonkarns) with further discussion.
Jason Karns
# August 18, 2009 - 1:11 am
It seems the comment form ate my comment.
Per RFC 2396, section 3 a URI is defined as:
[scheme] :// [authority] [path] ? [query]
Michael
# August 14, 2009 - 10:25 am
I think it is helpful to take the method’s name literally. “POST” is for posting something to a webserver, data that should go (persistently) “into” the application (e.g. database or so). “GET” in contrast is a request for getting something “out” of the application while the data (parameters) given with the request is just “meta-information” to tell the server which data should be returned.
If you follow this rule whenever possible, it’s very likely that you choose the correct HTTP method.
Cheers,
Michael
Fahed
# August 14, 2009 - 2:31 pm
That’s quite a good guideline which I quite like; it should keep you safe *most*, but not all, of the time.
Enlaces de la semana (V) | Mareos de un geek
# August 14, 2009 - 11:47 am
[...] La guía definitiva del GET y el POST. [...]
Simon Willison
# August 14, 2009 - 11:50 am
I don’t think it’s a good idea to use GET instead of POST in Ajax requests if the request is changing state on the server. Ajax applications should be thought of as clients to a web service, and no good web service should accept GET requests for modifying state.
Sensitive data should be transferred over HTTPS – using POST instead of GET there provides no additional protection at all.
Chris
# August 14, 2009 - 12:32 pm
@Simon Willison:
“Sensitive data should be transferred over HTTPS – using POST instead of GET there provides no additional protection at all.”
Yes it does. As fahed explained there’s also the risk that other users on the same browser see the history entries. In case you use POST the data isn’t stored in the browser’s history (or elsewhere in the browser).
Ben
# August 14, 2009 - 1:54 pm
>>In case you use POST the data isn’t stored in the browser’s history (or elsewhere in the browser).
Actually this is not true per se. Try submitting a form (e.g. a contact form) in Firefox. Single text entires are remembered by the browser – double click that text field again after submitting and you can see the previous entries that have been submitted.
Simon Willison
# August 14, 2009 - 3:00 pm
Good point about GET being potentially visible in the browser history even if used over SSL – but if you’re accepting sensitive information (credit cards etc) you’re almost certainly using it to update state on your server so you should be using POST anyway.
Fahed
# August 14, 2009 - 2:40 pm
Hi Simon,
Thanks for your comments.
Can you further explain why “no good web service should accept GET requests for modifying state”? As long as the action can be idempotent, why not use GET and make the application more responsive as, after all, responsiveness is the primary objective of using AJAX in the first place?
Simon Willison
# August 14, 2009 - 3:03 pm
How can you have an action that is idempotent but doesn’t modify state on the server?
The HTTP 1.1 RFC says “In particular, the convention has been established that the GET and HEAD methods SHOULD NOT have the significance of taking an action other than retrieval.” – http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html
Do you have any further information to back up your claim that GET is more responsive than POST? Do you just mean that GET requests can be cached?
a few great links, not much today but really delicous! « Adrian Zyzik’s Weblog
# August 14, 2009 - 12:05 pm
[...] of Blogging 6 jQuery growl-like notification systems webtoolkit4.me 50 Amazing Ramen Noodle Recipes Carsonified The Definitive Guide to GET vs POST 20 Beautiful Examples of Urban Decay Photography 25 Detailed Tutorials for Coding Up Your Web [...]
Ben
# August 14, 2009 - 1:59 pm
Just to reiterate what Simon Willison points out above. The Rule #2:
>> Because query strings are transferred openly in GET requests, we have to consider our security and that of our users when dealing with sensitive data like passwords or credit card numbers
is actually a misnomer. There is no difference in security between POST and GET. The major difference in “security” is that POSTed data is not visible in a URL. Both are open to packet sniffing. Posted variables can also be accessed through a browser like Firefox’s history (see my comment above).
The only true way of protecting sensitive data is through SSL.
More here: http://stackoverflow.com/questions/198462/get-versus-post-in-terms-of-security
Fahed
# August 14, 2009 - 2:37 pm
Just to touch on the security point… I took it as a given that all sensitive data would be passed over using SSL.
My point was that, even if SSL was being used, passing sensitive data over GET would keep it exposed to other users of the browser.
As angry as it makes me to see my credit card details show when hitting the down arrow on a previously filled credit card field, it would make me much angrier if the address bar’s auto-search would show my card details to someone typing in a URL in the address bar. (Much like the time the address bar decided to show my wife a matrimonial site I was looking at for a potential client.)
Fahed
# August 14, 2009 - 2:48 pm
Another point I’d like to make is that I do agree with most/many of the comments here and that Michael’s guideline (which most follow) should keep developers safe most of the time.
I think that a lot of confusion has arisen from Ryan chopping out the original intro to this article (which he justly did due to its length). My goal was to be most comprehensive and counter for the fact that rules without justified explanations do not stand with everybody (with me being one such person).
To put things into context, I developed an application a few months back which simply returned the date-restricted results of a database. Because the site had a rigid object-orientated form processor that was geared towards accepting POST, I went with the flow and used POST instead of GET. Although I always followed the simple “GET to get and POST to post” guideline, I deviated in this occasion because i thought “why not?”.
This article, therefore, aimed to fully explain all the options available so that myself, and others who might end up in my position, don’t deviate and are aware of the different possibilities (like the single-click opt-out link at the bottom of emails which action a process and not a resource, and the idea of using GET in AJAX instead of POST).
For reference, here’s the original intro:
MRDIN.COM
# August 14, 2009 - 3:12 pm
So, to make sure we get things right, I present to you the definitive guide of choosing between GET and POST.
Fahed
# August 14, 2009 - 3:13 pm
@Simon #comment-13475
(Unfortunately, nesting only goes 2 or 3 levels deep.)
“How can you have an action that is idempotent but doesn’t modify state on the server?”
Apologies, what i meant to say was, “if you could make the action safe”; something which you can do through validation.
“Do you have any further information to back up your claim that GET is more responsive than POST?”
Yes. When using XMLHttpRequest, browsers implement POST as a two-step process, sending the headers first and then the data, whilst GET is just one.
“The HTTP 1.1 RFC says “In particular, the convention has been established…”
These specifications must be implemented by browsers, servers etc. We, as developers, are simply using it for guidance on how things work, rather than pure instruction. We’re free to break such conventions if we see fit, and that does occasionally occur. RFC, for example, doesn’t take into consideration query lengths, usability or security. Sticking to it like glue, therefore, (IMHO) is not required as long as we understand it and its implications.
David
# August 14, 2009 - 4:46 pm
Can you define “two-step process”? Two TCP connections? Because the difference between headers and data in HTTP is just an extra carriage-return. The overhead of that carriage-return is minimal, to say the least.
Fahed
# August 14, 2009 - 5:44 pm
Yes. XMLHTTP POST sends header/body in 2 separate tcp/ip packets, making GET more responsive.
I thought this was old news :(
Yaron
# August 16, 2009 - 4:46 pm
The discussion of idempotent/safe/validated misses a point (in favour of POST for all cases where you change something). POST already provides an important service in making sure that you can send it accidentally by following a link or typing the URL. Remember the problems when some Google extension started to do extensive pre-fetching.
All you need is to have a link pointing to your “delete whatever” action, and you’re losing control.
You can, of course, send back a verify screen. But if the verify screen also uses GET, then any sort of bot/browser/extension/other-program can follow that one as well. So you have to use POST in the verification screen. And if you’re using POST anyway, why not use POST to begin with and spare everyone a verification screen that may not be needed?
Again, GETs can happen in unplanned situations. POSTs don’t happen by mistake, and don’t happen accidentally by otherwise well behaving software. It’s a mistake to allow your server to change state after a GET request, since you can never know that the GET request was genuine/intentional.
John Topley
# August 14, 2009 - 4:22 pm
Simon Willison is totally right. If you’re modifying server-side state then use a POST.
test » Blog Archive » Carsonified » The Definitive Guide to GET vs POST
# August 14, 2009 - 10:02 pm
[...] » The Definitive Guide to GET vs POST via [...]
Matt Auckland
# August 15, 2009 - 12:04 am
It is always important to remember that you cannot trust a user, meaning validate everything. No matter if that’s in a contact form or a CMS.
Further more, if you’re building a clean url function for say a blog, then add an extra level of validation/security to your htaccess file. Such as a rule to only accept letters and numbers and dashes. Rules such as that will add additional protection before the incoming request reaches your script.
Of course no amount of input sanitization can help you if your server is insecure, so why not invest in a good security package, and turn off all unused services and firewall ports.
Daily Links for Saturday, August 15th, 2009
# August 15, 2009 - 11:42 am
[...] Carsonified » The Definitive Guide to GET vs POST [...]
The Definitive Guide to GET vs POST | Design Newz
# August 15, 2009 - 3:31 pm
[...] The Definitive Guide to GET vs POST [...]
The Definitive Guide to GET vs POST | Choose Daily
# August 15, 2009 - 4:13 pm
[...] The Definitive Guide to GET vs POST [...]
Robert Taylor
# August 15, 2009 - 4:16 pm
Just a quick comment on the bullet point “GET requests can be hacked” — so may POST requests. In fact, there are extensions for Firefox that make doing so trivial and make converting from GET to POST and back automatic. Better yet, nothing about GET or POST itself protects any data transmission (both are clear text — encryption is another matter altogether), source verification (referring page, source IP, etc., are not factored by GET or POST). Bottom line, security will not be hurt or enhanced by use of GET or POST.
Another point, using POST doesn’t mean you’re not storing sensitive information. You can enable POST logging in Apache and other web servers. Besides, once the data is transmitted via GET or POST it’s probably used by some program and that is another point at which the data could be stored. Securing data is a multi-faceted vigil than depends little on which HTTP protocol one uses.
Want to discuss more? Email me: rjamestaylor @ gmail
Fahed
# August 15, 2009 - 4:23 pm
Agreed on both points.
With regards to the first, though, I was referring to a different definition of “hacked”… see http://www.useit.com/alertbox/990321.html
Subbu Allamaraju
# August 15, 2009 - 7:26 pm
1. Your Rule #2 is misguided. Please don’t circulate such myths about security. If you want security, either use encrypted URIs or switch to SSL.
2. Your Rule #4 is incorrect. All HTTP requests have the same format – a request line, headers, and optionally body. GET requests do have headers.
Fahed
# August 16, 2009 - 6:17 am
Take it easy!
1. My point assumes that SSL is already in use (i.e. a given) – check my comments above.
Also, what exactly are “encrypted URIs” and how would you go about using them?
2. My claim is based on research done by Iain Lamb, cofounder of the Oddpost webmail startup that was acquired by Yahoo! and eventually became the basis for the all-new Yahoo! Mail.
His research showed “rather baffling finding: POST requests, made via the XMLHTTP object, send header and body data in separate tcp/ip packets [and therefore,] xmlhttp GET performs better when sending small amounts of data than an xmlhttp POST.”
That is why Yahoo includes the use of GET instead of POST as one of their high performance speed optimisation rules.
Andrew Ingram
# August 18, 2009 - 12:30 am
Just a quick point that encrypting the URLs by itself isn’t necessarily secure, because a potential hacker has access to the same black box (the site) for encrypting the URLs as the victim. If you have the ability to create your own encypted string it becomes much easier to exploit any weaknesses in the algorithms.
In reality, it’s always safter to stick with established methods of securing traffic such as SSL (or its successors) rather than trying to implement your own security layer. Unless you’re a real security genius you’re likely to end up making things less secure.
Joseph Scott
# August 27, 2009 - 3:58 pm
I was curious about this 2 packet claim with XHR over HTTP POST as well. I ran tests on several browsers to see if this was the case – http://josephscott.org/archives/2009/08/xmlhttprequest-xhr-uses-multiple-packets-for-http-post/
Bottom line: all of the browsers I tested except for Firefox will use 2 packets to send this data instead of just 1.
bryanl
# August 16, 2009 - 4:04 pm
I believe this article my have caused more problems than it attempted to solved. Interesting attempt, though.
Fahed
# August 16, 2009 - 4:07 pm
Lol! You can say that again!
La guia definitiva sobre GET vs POST | aNieto2K
# August 17, 2009 - 1:09 pm
[...] publica un artículo sobre las diferencias entre GET y POST muy interesante. ← Wordpress 2.9 con papelera de [...]
La guia definitiva sobre GET vs POST : Blogografia
# August 17, 2009 - 1:41 pm
[...] ThinkVitamin publica un artículo sobre las diferencias entre GET y POST muy interesante. [...]
Weekly Web Nuggets #72 : Code Monkey Labs
# August 17, 2009 - 5:45 pm
[...] The Definitive Guide to GET vs. POST: Fahed Bizzari has put together a very nice guide to choosing between GET and POST requests. [...]
Ivan Mišić
# August 17, 2009 - 8:11 pm
Verry nice explained
GET 與 POST | TechNow 當代科技 - web host by CommuniLink
# August 18, 2009 - 12:46 am
[...] 較早前讀到一篇《The Definitive Guide to GET vs POST》,簡釋了一下 GET 和 POST 的優缺。並總結了 4 [...]
¿Cuando usar POST y cuando usar GET? « Darkchicles Microsoft Student Partner
# August 18, 2009 - 6:53 am
[...] y cuando usar GET?, si al final hacen lo mismo. Pues bien en el twitter recomendaban este enlace The Definitive Guide to GET vs POST y aunque el texto del autor me pareció un poco confuso, si imagen dice mas que mil palabras [...]
Simon Willison
# August 18, 2009 - 11:39 am
That Iain Lamb quote is the first I’ve heard of that performance issue – very interesting. I’d like to know which browsers it affects.
I don’t think it should affect the decision of whether to use GET or POST for the vast majority of cases. Ajax autocomplete is the most performance critical Ajax interaction, and that uses GET already. This might be a consideration for real-time collaboration applications (MobWrite / EtherPad etc) but for everything else I’d stick to the HTTP standard defined rules of which verb to use.
Compartiendo desde delicious. 11 de Agosto – 18 de Agosto | David Táboas
# August 18, 2009 - 5:05 pm
[...] Carsonified » The Definitive Guide to GET vs POST – [...]
Интересното от 18.08.2009 | DevStorming.com
# August 18, 2009 - 6:36 pm
[...] • The Definitive Guide to GET vs POST [...]
UnLugar » Blog Archive » ¿Usar GET o POST?
# August 18, 2009 - 11:01 pm
[...] Impresionante guía sobre los métodos POST o GET del protocolo HTTP. Y cuando conviene utilizar uno y otro, y las ventajas/desventajas de cada uno de estos métodos a la hora de enviar datos del cliente a nuestra aplicación. [...]
jrcetic (jrcetic) 's status on Wednesday, 19-Aug-09 09:07:57 UTC - Identi.ca
# August 19, 2009 - 9:08 am
[...] http://carsonified.com/blog/dev/the-definitive-guide-to-get-vs-post/ [...]
Diferencias entre GET y POST - The n4gash Blog
# August 19, 2009 - 11:57 am
[...] [...]
Ennuyer.net » Blog Archive » Rails Reading - August 19, 2009
# August 19, 2009 - 8:01 pm
[...] Carsonified » The Definitive Guide to GET vs POST [...]
links for 2009-08-22 at DeStructUred Blog
# August 23, 2009 - 2:03 am
[...] Carsonified » The Definitive Guide to GET vs POST (tags: webdev Programming forms tips web http HTML) [...]
[ mkhairul.com ] » GET vs POST
# August 23, 2009 - 10:37 pm
[...] good definitive guide on GET vs POST at [...]
XMLHttpRequest (XHR) Uses Multiple Packets for HTTP POST? || Joseph Scott
# August 27, 2009 - 3:55 pm
[...] recent Think Vitamin article, The Definitive Guide to GET vs POST, mentioned something that I hadn’t seen before about XMLHttpRequest (XHR). Their Rule #4 [...]
GET y POST: La Guia Definitiva « The New Cult of Dead Cow
# August 29, 2009 - 6:57 pm
[...] Traducido de: Carsonified [...]
Fahed
# August 31, 2009 - 3:03 pm
For anyone still wondering about AJAX POST using 2 TCP packets and AJAX GET only using 1, Joseph Scott has checked it and detailed his findings:
http://josephscott.org/archives/2009/08/xmlhttprequest-xhr-uses-multiple-packets-for-http-post/
Except for FF, all browsers implement AJAX POST using 2 packets.
Get vs Post la guia definitiva | Blog XYOX
# September 2, 2009 - 1:27 am
[...] maneras mas comunes de enviar datos o contenido en los formularios o a traves de simples enlaces, Carsonified nos muestra una guia, comparando el deselvolvimiento de cada uno de estos metodos. Posted in Tutoriales Tags: [...]
Revue de presse | Simple Entrepreneur
# October 29, 2009 - 5:11 am
[...] The definitive guide to GET vs POST Probablement pas le guide définitif sur le sujet (comme annoncé), mais une très bonne présentation des différences entre ces deux méthodes HTTP. Pour être un peu plus complet, il aurait fallu aborder REST… [...]
ויטמין
# October 29, 2009 - 9:04 am
There is no difference in security between POST and GET. The major difference in “security” is that POSTed data is not visible in a URL. Both are open to packet sniffing
Mes favoris du 29-10-09 au 30-10-09
# October 30, 2009 - 8:29 am
[...] The Definitive Guide to GET vs POST [...]
Qué método elegir, GET o POST? | Otro Blog Más
# November 9, 2009 - 7:54 am
[...] través de Carsonified, leo un artículo interesante llamado “La Guía Definitiva de GET vs POST“, que no [...]
PHP: Hafta 3 | UBenzer | Umut Benzer | O da kim?
# November 24, 2009 - 9:13 pm
[...] GET mi POST mu? Aradaki farklar, kullanım örnekleri [...]
gagnelteboalp
# December 10, 2009 - 2:08 pm
Uncoriegrouro
rwof
adenner
# March 10, 2010 - 8:10 pm
You appear to have a dead link to the image that is in your summary. http://www.onlineassociates.ae/wp-content/images/external/carsonified-get-post.gif returns a 404 not found error.
Otherwise a good article, I confess that I have used gets where posts should have been used before…