What changes when an HTML <form> uses method="get" instead of method="post", and how do you choose between them?
answer
- query string versus request body
- the URL is the result, or it is not
- GET replaces the action's existing query
- only a body can carry a file
- reads repeat safely, writes should not
basics
~20 sWith method="get" the browser puts the form's entries in the URL query string, so the result is bookmarkable and reloadable; with method="post" it puts them in the request body, which supports file uploads and keeps values out of the URL and history.
solid answer
~40 sBoth methods build the same entry list; they differ in where it goes. `method="get"` serializes it into the action URL's query string — and *replaces* any query already in `action`, which is why a hardcoded `?page=2` in the action disappears and has to be a hidden input instead. That makes the result linkable, bookmarkable and safe to reload, so it is the right choice for search and filter forms. `method="post"` sends the entries as a request body, which is what lets you use `enctype="multipart/form-data"` for file uploads and keeps values out of the URL bar, browser history and referrers. It is the choice for anything that changes state, since reloading a GET result re-runs it invisibly while reloading a POST result prompts the user. `enctype` is ignored for GET entirely.
go deeper
Know that GET puts the fields in the URL after a question mark and POST puts them in the request body, and that logins and uploads use POST.
Explain that both build the same entry list, that GET overwrites the action URL's query, that enctype only applies to POST, and why file uploads need a body.
Argue the choice from effects: reads are repeatable and deserve an addressable URL; writes get POST plus post/redirect/get so reloads never resubmit. Call out URL leakage into history, logs and referrers.
Set the house rule so endpoints and forms agree on which submissions are safe to repeat, and make sure link prefetching, retries and caching layers cannot silently re-trigger a state change.
## Same entries, different destination Whichever method you pick, the browser first constructs the same entry list of name/value pairs from the named, enabled controls. `method` decides only how that list travels. **GET.** The list is percent-encoded as `name=value` pairs joined by `&` and becomes the query component of the action URL. The browser then navigates there. ```html <form action="/search" method="get"> <input type="search" name="q"> <button>Search</button> </form> ``` Submitting with `q=forms` requests `/search?q=forms`. **POST.** The list is placed in the request body, encoded according to `enctype`, and the URL stays exactly as written in `action`. ## The gotcha: GET discards the action's existing query This one bites nearly everyone once. Given `action="/search?page=2"`, a GET submission does **not** append to the existing query — it replaces the whole query with the serialized entry list, so the request is `/search?q=forms` and `page=2` is gone. The fix is to make the parameter part of the form: ```html <form action="/search" method="get"> <input type="hidden" name="page" value="2"> <input type="search" name="q"> </form> ``` POST does not have this problem: the action URL, query and all, is used verbatim, and the entries ride in the body. ## What each one buys you GET's real property is that **the resulting page is fully described by its URL**. That makes it shareable, bookmarkable, addressable by a link, and cacheable; the back and forward buttons move through result pages sensibly, and a reload just re-runs a read. This is exactly what you want for search, filtering, sorting and pagination — the form is a way of composing a URL. POST's properties are the mirror image. Values are not in the URL, so they do not land in bookmarks, browser history, or the referrer sent to third-party resources on the next page. There is no practical length ceiling from URL limits. And crucially, only POST can carry a body, which is what makes `enctype="multipart/form-data"` — and therefore file uploads — possible. Reloading the resulting page makes the browser warn before resubmitting, a friction that is appropriate when the submission changed something. Setting `enctype` on a GET form does nothing at all; there is no body to encode. ## The decision rule Use GET when the submission *reads* — it should be safe to repeat, and repeating it must have no side effects. Use POST when the submission *writes*: creating, updating, deleting, sending money, logging in. The rule is about the effect, not about sensitivity: putting a password in a GET form is bad because it lands in history and logs, but even a harmless write belongs in POST, because things that repeat safely and things that do not should not look the same to the browser, to a link prefetcher, or to a user who hits reload. A practical corollary for state-changing forms is the post/redirect/get pattern: handle the POST, then redirect to a GET-addressable result page, so the user's reload re-runs a read instead of the write. ## Related markup you should know - A submit button can override the form for its own activation with `formmethod`, so one button in a GET search form can POST to a different endpoint. - `method` and `action` are readable from script as `form.method` and `form.action`, which is how you reuse the markup's intent when you take submission over with `fetch`. - Whatever you choose, the method is a hint about intent, not a security boundary. A POST body is exactly as forgeable as a query string; both are user input and both must be validated server-side. ## Common misreadings "POST is encrypted" is false — only HTTPS encrypts anything, and it encrypts the URL of a GET request too. "GET has a 255-character limit" is folklore; there is no limit in the markup, only practical ceilings imposed by browsers, servers and proxies, which is a reason to prefer POST for large payloads but not a fixed number to quote.
- Why do search and filter forms almost always use GET even when the query is long?Because the point of a search result is that it has an address. With GET the whole query lives in the URL, so users can bookmark it, share it, link to it from a report, and use back/forward across result pages; a reload simply re-runs the read. POST would make identical results unreachable by URL and turn every reload into a resubmission prompt.
- A form has action="/reports?year=2026" and method="get", and the year parameter keeps disappearing. Why?GET replaces the action URL's entire query with the serialized entry list, so `year=2026` is discarded on submit. Move it into the form as `<input type="hidden" name="year" value="2026">`, and it will be serialized alongside the other entries. POST would have kept the action's query intact, since its entries travel in the body.
- Is POST a security measure compared with GET?No. A POST body is user-controlled and just as easy to forge as a query string, so both need server-side validation and authorization. What POST genuinely avoids is *leakage by URL*: values do not appear in the address bar, browser history, bookmarks, server access logs or referrers. That is a privacy and hygiene win, not an authenticity guarantee.
saying these in an interview costs you the question
- Says POST is encrypted while GET is plain text
- Quotes a fixed character limit for GET form data
- Expects GET to append to a query already in the action
- Uses GET for actions that change server state
- Thinks setting enctype changes anything on a GET form