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:

GET /blog/?name1=value1&name2=value2 HTTP/1.1
Host: carsonified.com

and in the body of POST requests:

POST /blog/ HTTP/1.1
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:

  1. GET requests can be cached
  2. GET requests can remain in the browser history
  3. GET requests can be bookmarked
  4. GET requests can be distributed & shared
  5. 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:

  1. 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.*
  2. 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.

Free Workshops

Watch one of our expert, full-length teaching videos. Choose from either HTML, CSS or Wordpress.

Start learning

Treehouse

Our mission is to bring affordable Technology education to people everywhere, in order to help them achieve their dreams and change the world.

Comments

78 comments on “The Definitive Guide to GET vs POST

  1. 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.

    • 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/

      • 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?

      • 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.

  2. 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

  3. Pingback: Enlaces de la semana (V) | Mareos de un geek

  4. 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.

    • @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).

      • >>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.

      • 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.

    • 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?

      • 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?

  5. Pingback: a few great links, not much today but really delicous! « Adrian Zyzik’s Weblog

  6. 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

  7. 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.)

  8. 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:

    The great thing about web development is that, driven by the desire to achieve goals, so much can be self-taught through trial & error, experimentation, tutorials, forums and mailing lists etc.
    Not only does this mean that you don’t need a formal education to become a developer, but it also means that you can bring great ideas to digital life – even if you never imagined you’d develop.
    As great as this might be, a negative consequence of goal-driven self-teaching is that goals often get achieved through subpar, and even incorrect, means.
    One commonly found example is the misuse of GET over POST and vice versa.

  9. @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.

    • 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.

      • Yes. XMLHTTP POST sends header/body in 2 separate tcp/ip packets, making GET more responsive.

        I thought this was old news :(

    • 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.

  10. Pingback: test » Blog Archive » Carsonified » The Definitive Guide to GET vs POST

  11. 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.

  12. Pingback: Daily Links for Saturday, August 15th, 2009

  13. Pingback: The Definitive Guide to GET vs POST | Design Newz

  14. 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

  15. 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.

    • 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.

    • 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.

  16. Pingback: La guia definitiva sobre GET vs POST | aNieto2K

  17. Pingback: La guia definitiva sobre GET vs POST : Blogografia

  18. Pingback: Weekly Web Nuggets #72 : Code Monkey Labs

  19. Pingback: GET 與 POST | TechNow 當代科技 - web host by CommuniLink

  20. Pingback: ¿Cuando usar POST y cuando usar GET? « Darkchicles Microsoft Student Partner

  21. 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.

  22. Pingback: Compartiendo desde delicious. 11 de Agosto – 18 de Agosto | David Táboas

  23. Pingback: Интересното от 18.08.2009 | DevStorming.com

  24. Pingback: UnLugar » Blog Archive » ¿Usar GET o POST?

  25. Pingback: jrcetic (jrcetic) 's status on Wednesday, 19-Aug-09 09:07:57 UTC - Identi.ca

  26. Pingback: Diferencias entre GET y POST - The n4gash Blog

  27. Pingback: Ennuyer.net » Blog Archive » Rails Reading - August 19, 2009

  28. Pingback: links for 2009-08-22 at DeStructUred Blog

  29. Pingback: [ mkhairul.com ] » GET vs POST

  30. Pingback: XMLHttpRequest (XHR) Uses Multiple Packets for HTTP POST? || Joseph Scott

  31. Pingback: GET y POST: La Guia Definitiva « The New Cult of Dead Cow

  32. Pingback: Get vs Post la guia definitiva | Blog XYOX

  33. Pingback: Revue de presse | Simple Entrepreneur

  34. 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

  35. Pingback: Mes favoris du 29-10-09 au 30-10-09

  36. Pingback: Qué método elegir, GET o POST? | Otro Blog Más

  37. Pingback: PHP: Hafta 3 | UBenzer | Umut Benzer | O da kim?

  38. POST /Microsoft-Server-ActiveSync?Cmd=Sync&User=user%40domain.domDeviceId=androidc259148960&DeviceType=Android HTTP/1.1

    This little line was taken from my active sync device as it was talking to the server. The rest of the HTTP header followed with the body having some active sync traffic. What do?!

  39. The difference is that GET sends data open and POST hidden (in the http-header).

    So get is better for non-secure data, like query strings in Google. Auth-data shall never be send via GET – so use POST here. Of course the whole theme is a little more complicated… who wants to read more, try this: http://bit.ly/gXpgzY

    I hope that helped a little.

  40. Pingback: How to develop web applications – primary web development concepts 1.0 « Programmer's point of view…

  41. Pingback: Homepage

  42. Pingback: toronto-accountatn.ca

  43. Pingback: case in vendita

  44. Pingback: AgEN bOlA

  45. Pingback: WebRequest: Post verse Get ← ZGLE.com

  46. “query strings are transferred openly in GET requests” – Unless you are using HTTPS, POST is no more secure than GET. An observer can still see the unencrypted data stream of the POST request.
    If you are using HTTPS, both the query string and the message body are sent securely, so both methods are essentially equivalent.

    • Even with HTTPS, URL’s may be still be stored in logs on servers, which may store things like credit card information in violation of security laws.

  47. Pingback: CodeIgniter Form validation With $_GET | Shibbir Ahmed