GET or POST: What Happens When a Form Is Submitted

Two methods, two very different places for your data. Learn which to use, what is safe in a URL, and why neither is encrypted on its own.

Concept

The method attribute decides how the collected values travel to the server. There are two practical choices and the difference matters more than most beginners expect.

GETPOST
Values travel inThe URL, as a query stringThe request body
Visible in the address barYesNo
Bookmarkable and shareableYesNo
In browser historyYesNo
Logged by servers and proxiesYesPath only
Length limitPractical limit around 2000 charactersEffectively none
File uploadsImpossibleYes
Cached by browsersYesNo
Re submitted on reloadSilentlyWith a warning

What each looks like

<form action="/search" method="get">
  <label for="q">Search</label>
  <input type="search" id="q" name="q">
  <select name="sort">
    <option value="relevance">Relevance</option>
    <option value="date">Newest</option>
  </select>
  <button type="submit">Search</button>
</form>
GET /search?q=brass+lamp&sort=date HTTP/1.1
Host: example.com
<form action="/login" method="post">
  <label for="user">Username</label>
  <input type="text" id="user" name="user" autocomplete="username">
  <label for="pass">Password</label>
  <input type="password" id="pass" name="pass" autocomplete="current-password">
  <button type="submit">Sign in</button>
</form>
POST /login HTTP/1.1
Host: example.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 34

user=meera&pass=correct-horse-staple

The rule for choosing

Use GET when the form asks a question. Use POST when it changes something.

Behind that is a specification concept: GET is meant to be safe and idempotent. Safe means it does not change server state; idempotent means repeating it produces the same result. Search, filter, sort, paginate - all safe, all GET.

Anything that creates, updates, deletes, sends, pays or logs in must be POST. Not only for privacy, but because agents that assume GET is safe will act on that assumption. Browsers prefetch GET URLs, crawlers follow them, and antivirus software and email scanners open links in messages. A delete action behind a GET link will eventually be triggered by a machine that was only looking.

The three practical consequences of GET

The values are in the URL, permanently

They appear in the address bar, in browser history, in server access logs, in proxy logs and in the referrer header sent to any third party script on the resulting page. A password submitted by GET ends up in log files on machines you do not control.

There is a length limit

The specification sets none, but browsers and servers do - roughly two thousand characters is the safe ceiling. A long form silently truncates or fails.

Reload resubmits without asking

Which is exactly right for a search and exactly wrong for a payment.

The double submission problem

After a POST, pressing reload prompts the browser to send it again - the familiar Confirm form resubmission dialog. The standard fix is the Post Redirect Get pattern:

1. Browser POSTs the form to /orders
2. Server saves the order
3. Server responds 303 See Other, Location: /orders/1043/thank-you
4. Browser follows with a GET
5. Reloading now repeats a harmless GET

This is a server side pattern, but it is the direct consequence of the markup choice and every form handler should implement it.

Neither method is encrypted

A persistent misconception is that POST is secure. It is not. Over plain HTTP, both methods send the values in readable text - GET in the request line, POST in the body - and anyone on the network path can read either.

HTTPS is what protects the data, and it protects both equally: the URL, the headers and the body are all encrypted. POST is preferable for sensitive values not because it is encrypted but because it keeps them out of URLs, and URLs leak into places that outlive the request.

enctype

ValueUse
application/x-www-form-urlencodedThe default. Fine for text.
multipart/form-dataRequired for file uploads.
text/plainDebugging only. Never in production.

Example: the same page using both

<!-- filter: a question, so GET. The result is shareable. -->
<form action="/products" method="get">
  <label for="cat">Category</label>
  <select id="cat" name="category">
    <option value="lamps">Lamps</option>
    <option value="vessels">Vessels</option>
  </select>
  <button type="submit">Filter</button>
</form>

<!-- add to cart: changes state, so POST -->
<form action="/cart/add" method="post">
  <input type="hidden" name="product_id" value="kettle-2l">
  <input type="hidden" name="csrf_token" value="...">
  <label for="qty">Quantity</label>
  <input type="number" id="qty" name="quantity" value="1" min="1" max="10">
  <button type="submit">Add to cart</button>
</form>

The filter produces a URL a reader can bookmark and send to someone else. The cart action does not, which is correct - nobody should be able to add to a cart by following a link.

Important rules

  • method defaults to get if omitted.
  • GET discards any existing query string in the action URL and replaces it.
  • Only get and post are available from HTML forms. Other verbs require scripting.
  • File uploads require POST with multipart/form-data.
  • Values are URL encoded either way: a space becomes + or %20, an at sign becomes %40.
  • Every state changing POST needs a CSRF token.

Common mistakes

  • A login form using GET, putting the password in the address bar and in the logs.
  • A delete action behind a GET link, triggered by a crawler or a prefetch.
  • Omitting method and unintentionally getting GET.
  • Believing POST is encrypted.
  • No Post Redirect Get, so reload creates a duplicate record.
  • Missing enctype on an upload form.
  • Putting a long body of text through GET and hitting the URL limit.

Best practices

  • Write method explicitly on every form.
  • GET for reading, POST for writing, with no exceptions for convenience.
  • Serve every form over HTTPS.
  • Implement Post Redirect Get for every POST handler.
  • Include a CSRF token in every state changing form.
  • Keep GET parameter names short and readable; they are part of the URL people share.

Practice

  1. Build one form and submit it with both methods. Compare the address bar and the Network panel each time.
  2. Submit a GET form with a value containing a space, an ampersand and an at sign. Read the encoding.
  3. Submit a POST form and press reload. Describe the dialog, then design the redirect that removes it.
  4. Explain in two sentences why a delete link behind GET is dangerous even on a page only staff can reach.

Useful resources

Hand picked references for this topic
Written by Lorens Mishra

Default administrator account created by the installer.

Continue reading

All HTML notes →

Discussion

0 comments
Sign in to join the discussion.

No comments yet. Be the first to say something.