LearnThe Definitive Guide to GET vs POST

writes on August 14, 2009

Share with your friends


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

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.


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.

83 Responses to “The Definitive Guide to GET vs POST”

  1. I you try to display an HTTP request; please don’t forget the *two* line feeds between the head and the body.

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

      • It seems the comment form ate my comment.

        Per RFC 2396, section 3 a URI is defined as:

        [scheme] :// [authority] [path] ? [query]

    • There is a limit to query string length with GET (varies by container, but I believe Apache is 2KB, for example), but there is no ‘parameter’ limit with with POST. The REST approach fails horribly in this regard, and instead the API should have been standardized around action words and all requests should have been of type POST.

      For example, standardized action prefixes such as “create”, “get”, “update”, “delete”:


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


  4. Simon Willison on August 14, 2009 at 11:50 am said:

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

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

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

  8. So, to make sure we get things right, I present to you the definitive guide of choosing between GET and POST.

  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.

    • 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. Simon Willison is totally right. If you’re modifying server-side state then use a 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. 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

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

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

  14. I believe this article my have caused more problems than it attempted to solved. Interesting attempt, though.

  15. Verry nice explained

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

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


    Except for FF, all browsers implement AJAX POST using 2 packets.

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

  19. gagnelteboalp on December 10, 2009 at 2:08 pm said:


  20. 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…

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

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

  23. Thanks for the info.

  24. Greg Brown on June 5, 2013 at 9:29 am said:

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

  25. umairaslambhatti on June 19, 2013 at 3:07 am said:

    Nicely writtern , I found a bit different in MCTS asp.net book as


  26. Superb blog! Do you have any suggestions for
    aspiring writers? I’m hoping to start my own blog soon but I’m
    a little lost on everything. Would you recommend starting with a free platform
    like WordPress or go for a paid option? There are so many options out
    there that I’m totally confused .. Any ideas? Bless

    My web page Eloboost

  27. pasaros por aqui que merece la pena por
    la variedad de modelos

Leave a Reply

Learn to code with Treehouse

Start your 14 day free trial today and get access to hundreds of video courses in web development, design and business!

Learn more