# GET vs POST

> Understand the fundamental differences between GET and POST HTTP methods. Learn about safety, idempotency, caching, request bodies, and when to use each.

Source: https://howhttpworks.com/compare/get-vs-post
Last reviewed: 2026-10-04

> **TL;DR:** Use GET when the request is a read and the URL should be shareable or cacheable. Use POST when the client is submitting data or triggering work with side effects.

## The Fastest Way To Decide

The easiest test is not "does this endpoint accept a body?" It is:

- is the client reading something
- or is the client submitting something that changes server state or triggers work

If it is a read, it should usually be **GET**. If it is a submission or action, it should usually be **POST**.

## The Core Difference

GET and POST are the two most-used HTTP methods, and they express different intent:

- **GET** retrieves a resource. It should have no side effects on the server.
- **POST** submits data to the server, typically creating a resource or triggering an action.

This distinction isn't just convention — it has real implications for caching, browser behavior, bookmarking, and API design.

## Safety and Idempotency

These two properties define how methods should behave:

| Property | GET | POST |
|---|---|---|
| Safe (no side effects) | ✅ Yes | ❌ No |
| Idempotent (same result if repeated) | ✅ Yes | ❌ No |
| Cacheable | ✅ Yes | Only with explicit freshness information and a `Content-Location` match; almost never done (RFC 9111 section 4) |

**Safe** means the request doesn't modify server state. A GET request should be readable without consequence — you can make it 100 times and the server state stays the same.

**Idempotent** means making the same request multiple times produces the same result as making it once. GET is idempotent: fetching `/users/42` ten times returns the same user ten times. POST is not: submitting an order form ten times creates ten orders.

## Request Structure

| | GET | POST |
|---|---|---|
| Parameters | Query string (`?key=value`) | Request body |
| Body | No defined semantics (RFC 9110 section 9.3.1); `fetch()` throws `TypeError: Request with GET/HEAD method cannot have body` and servers or proxies may reject or drop it | Normal |
| URL length limit | Yes (~2000 chars in practice) | No practical limit |
| Visible in URL | Yes | No |
| Saved in browser history | Yes (URL) | The URL, not the body |
| Bookmarkable | Yes | No |

GET parameters appear in the URL: `/search?q=http+methods&page=2`. This makes GET requests bookmarkable, shareable, and cacheable — but it also means sensitive data (passwords, tokens) must never go in a GET URL.

POST data goes in the request body, which is not stored in browser history and not visible in the URL bar. This makes POST appropriate for form submissions, file uploads, and any operation that changes server state.

## Caching

GET responses can be cached by browsers, CDNs, and proxies. A `Cache-Control: max-age=3600` on a GET response means the browser won't re-request that URL for an hour.

POST responses are cacheable only when they carry explicit freshness information, and a cache can reuse them only for later GET/HEAD requests to the URL in `Content-Location` (RFC 9111 section 4). In practice browsers and CDNs do not cache POST. If you need a cacheable read with a large input, the IETF HTTPAPI working group's safe `QUERY` method (draft) is designed for exactly that, but it is not yet widely supported.

## Browser Behavior On Refresh

When a user refreshes a page loaded via GET, the browser simply re-sends the GET request silently.

When a user refreshes a page that was the result of a POST (like a form submission), the browser shows a warning: "Resending this form will resubmit your data." This is the browser protecting the user from accidentally submitting a form twice.

The standard pattern to avoid this is the **POST/Redirect/GET** pattern: after a successful POST, redirect the user to a GET URL. The browser then loads the confirmation page via GET, and refreshing it is safe.

## When To Use Each

**Use GET when:**
- Fetching a resource (page, API data, file)
- The operation has no side effects
- You want the URL to be shareable or bookmarkable
- You want the response to be cacheable
- Building a search or filter interface

**Use POST when:**
- Creating a new resource
- Submitting a form
- Uploading a file
- Triggering an action with side effects (send email, process payment)
- The input is large or sensitive and shouldn't appear in URLs

## Common Mistakes

**Using GET for state-changing operations** — a crawler, prefetcher, or innocent page refresh can trigger destructive behavior you never meant to expose as a read.

**Using POST for every endpoint** — that throws away caching, bookmarking, and the semantic contract clients expect from the web.

**Putting sensitive data in GET parameters** — URLs leak into access logs, browser history, analytics tooling, and `Referer` headers. Bodies are not recorded in default access logs, but app logging, WAFs, and APM tools often capture them, so POST is not a privacy control.

## FAQ

### Can a GET request have a body?

HTTP does not forbid it, but RFC 9110 section 9.3.1 says the content has no generally defined semantics and that servers may reject the request. The browser `fetch()` API throws a `TypeError` if you try, and many CDNs and proxies drop or reject the body. Put parameters in the query string, or use POST, or the QUERY method (RFC 10008, see [QUERY](https://howhttpworks.com/methods/query)) where your stack supports it, when the input is too large.

### Is POST more secure than GET because parameters are not in the URL?

No. Over plain HTTP both are readable on the wire; over HTTPS both are encrypted. The real difference is that URLs end up in browser history, proxy and server access logs and `Referer` headers, while bodies do not by default. Application logs and WAFs frequently record bodies, so do not treat POST as hiding secrets.

### What is the POST/Redirect/GET pattern?

After a successful POST (e.g., form submission), redirect the user to a GET URL. This prevents the browser from showing a "resubmit form?" warning on refresh and makes the confirmation page bookmarkable.

### What is the difference between POST and PUT?

POST creates a new resource at a server-determined URL. PUT creates or replaces a resource at a client-specified URL. PUT is idempotent (calling it multiple times has the same effect); POST is not.

### Why do browsers convert POST to GET on 301 and 302 redirects?

Historical browser behavior converted POST to GET when following 301 and 302 redirects, even though the spec did not require it. Use 307 (temporary) or 308 (permanent) to preserve the original method across redirects.

## References

- [MDN Web Docs: GET](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/GET)
- [MDN Web Docs: POST](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST)
- [RFC 9110: HTTP Semantics — Method Definitions](https://www.rfc-editor.org/rfc/rfc9110#section-9)
