HTTP Methods
An HTTP method is the first word of every request line: it tells the server what the client wants done with the target resource, the thing the URI identifies, such as an order. GET /orders/42 asks for order 42, while DELETE /orders/42 asks the server to remove it. The URI is the same; the meaning, the expected response and the risk are completely different.
RFC 9110, the HTTP Semantics standard, defines GET, HEAD, POST, PUT, DELETE, CONNECT, OPTIONS and TRACE, and RFC 5789 adds PATCH. Each method has a defined meaning and two properties testers rely on: whether it is safe and whether it is idempotent. This lesson covers the seven that web applications and APIs use every day.
Why it matters
The method is a promise to every program between the user and the server. Crawlers and link-preview services follow GET links, browsers prefetch pages, and HTTP clients may resend an idempotent request when a connection drops. That is harmless only while the application keeps the promise: a crawler can trigger a delete action placed behind a GET link.
For a tester, methods become a ready-made list of expectations for every endpoint: what must not change state, what may be sent twice and which methods must be refused. Duplicate orders, updates that wipe fields and regular users who can delete records are often found by changing only the method or by sending the same request twice.
The seven methods you will test
The responses below are typical; the API contract states the exact codes. RFC 9110 also defines CONNECT (a tunnel through a proxy) and TRACE (echoes the request for diagnostics), rarely tested inside an application. Method names are case-sensitive; the standard ones are uppercase.
GETretrieves a representation of the resource, meaning its current state in a format such as JSON or HTML, usually with200 OK. Content sent in a GET has no defined meaning in RFC 9110, and some servers reject it.HEADis GET without the response body. The server should send the same headers as for GET, so a client can check existence, size or type without downloading. Every general-purpose server must support GET and HEAD.POSTsends content for the resource to process by its own rules: create an order in/orders, submit a form, start an action such as/orders/42/cancel. A POST that creates something should answer201 Createdwith aLocationheader.PUTcreates or replaces the resource with the complete state in the body:200or204when it replaced,201when it created.PATCH(RFC 5789) applies the changes described in a patch document, so only what the document names changes.Content-Typenames the format, for exampleapplication/merge-patch+json.DELETEremoves the resource: typically204 No Content,200with a message, or202 Acceptedwhen the deletion is queued. As with GET, content sent in a DELETE request has no defined meaning.OPTIONSasks which methods and features the resource supports; the answer is in headers such asAllow. Browsers also send it on their own as a CORS preflight, covered in the CORS lesson.
Safe and idempotent: two promises in RFC 9110
A method is safe when its meaning is read-only: the client neither requests nor expects a change of state on the server. GET, HEAD, OPTIONS and TRACE are safe. Logging the request or counting a page view is still allowed. RFC 9110 gives the example of a link like page?do=delete: if following it deletes data, the resource is at fault, not the crawler that followed it.
A method is idempotent when sending the same request several times has the same intended effect on the server as sending it once. PUT, DELETE and every safe method are idempotent; POST is not, and PATCH is not in general. Setting an address twice leaves one address; "add one item" sent twice adds two. Idempotency concerns the server state, not the response: a second DELETE may return 404 and still be correct.
RFC 9110 allows an idempotent request to be repeated automatically when the connection fails before the response arrives, and says a client should not automatically retry a non-idempotent one unless it knows the request is in fact idempotent or was never applied. Safe does not mean secure: a GET still needs authorization, and sensitive data does not belong in its URI, which servers, proxies and browsers record.
| Method | Saferead-only meaning | Idempotentrepeating = same effect | Request body | Typical success response |
|---|---|---|---|---|
GETread | Yes | Yes | No defined meaning | 200 OKwith the representation |
HEADheaders only | Yes | Yes | No defined meaning | 200 OKsame headers as GET, no body |
OPTIONSwhat is supported | Yes | Yes | No defined use | 200 or 204with Allow |
PUTcreate or replace | No | Yes | The complete new state | 200 or 204201 if it created |
DELETEremove | No | Yes | No defined meaning | 204, 200 or 202202 if queued |
POSTprocess content | No | No | Content to process | 201 Createdwith Location, when it creates |
PATCHpartial change | No | Not in generala specific patch can be | A patch document | 200 or 204 |
Properties as defined in RFC 9110, PATCH in RFC 5789. Status codes are the typical ones; the API contract states the exact codes.
Text version
Method Safe Idempotent Request body Typical success response
------- ---- -------------- ------------------- -------------------------------
GET yes yes no defined meaning 200 + the representation
HEAD yes yes no defined meaning 200, same headers as GET, no body
OPTIONS yes yes no defined use 200 or 204 + Allow
PUT no yes full new state 200 or 204; 201 if it created
DELETE no yes no defined meaning 204, 200, or 202 if queued
POST no no content to process 201 + Location if it created
PATCH no not in general patch document 200 or 204What to test for each method
Turn each promise into test conditions. After every request check two things: the response, and the state of the resource, read back with a separate GET or from the database.
- GET and HEAD: nothing changes, however often you send them. HEAD returns the same status and headers as GET with an empty body. Look for actions hidden in GET links, such as
?action=cancel. - POST: send the same request twice, as a double-click or a retry would, and test the duplicate rule agreed with the team: reject, merge or accept. Some APIs accept a client-generated key, often in an
Idempotency-Keyheader, to recognise a repeat. - PUT: send it twice and expect one stored state. Leave out an optional field: expect it to be cleared, or the request rejected, as the contract says; quietly keeping the old value means PUT is applied as a partial update.
- PATCH: compare the whole resource before and after; fields you did not send must not change. An unsupported patch format should get
415 Unsupported Media Type, with anAccept-Patchheader as RFC 5789 recommends. - DELETE: a following GET returns
404, a repeated DELETE changes nothing else, and related data is handled as the requirement says. - Unsupported methods: expect
405 Method Not Allowedwith anAllowheader, which RFC 9110 makes mandatory, or501 Not Implementedfor a method the server does not recognise. A200or500is a defect, and OPTIONS should list the methods that really work. - Authorization per method: a user who may GET a record is not necessarily allowed to PUT or DELETE it. Repeat the write methods with a less privileged account; the OWASP API Security Top 10 (2023) calls this risk Broken Function Level Authorization. Test only systems you own or have written permission to test.
Worked example: one endpoint, every method
An address-book API documents GET, HEAD, OPTIONS, PUT, PATCH and DELETE on /v1/addresses/{id}, and address 7 belongs to user A. Instead of one vague "update address" test, the tester writes one row per promise and checks the stored state as well as the status code in every row:
- Row 4 separates PUT from PATCH: keeping the old city would mean PUT is applied as a partial update.
- Row 8 runs while address 7 still exists; a
204there means user B can delete another user's data, a critical authorization defect.
# Request (as user A unless stated) Expected result
1 GET /v1/addresses/7, sent twice 200 both times, same body, nothing changed
2 HEAD /v1/addresses/7 200, same headers as GET, empty body
3 PUT /v1/addresses/7 (full body), twice 200 or 204 both times, one stored address
4 PUT /v1/addresses/7 without "city" 4xx (city is required), address unchanged
5 PATCH /v1/addresses/7 {"zip": "12271"} 200, only zip changed; street and city kept
6 POST /v1/addresses/7 405 + Allow: GET, HEAD, OPTIONS, PUT, PATCH,
DELETE
7 OPTIONS /v1/addresses/7 200 or 204, Allow lists the same six methods
8 DELETE /v1/addresses/7 as user B 403 or 404, address 7 still exists
9 DELETE /v1/addresses/7 204, then GET returns 404
10 DELETE /v1/addresses/7 again 404 as documented, no other address affectedCommon mistakes
- Reading "safe" as "secure". Safe only means the client asks for no change; a GET still needs authentication and authorization.
- Sending each POST only once. Double submissions and retries are a common source of duplicate orders and payments.
- Expecting identical responses from an idempotent method. A repeated DELETE may return
404; idempotency is about the state on the server. - Treating PUT and PATCH as interchangeable, and never checking the fields that were not sent.
- Testing only the methods the user interface calls. Any client can send any method, so check that unlisted ones get
405withAllow.
The QA perspective
Methods are a review checklist before any code runs. For each endpoint in a story or API contract, list its methods and ask: what changes on the server, may the request be repeated, and what does a duplicate do? Ask the web and mobile developers whether their clients retry after a timeout; on mobile networks a resent POST is a real scenario.
Name the method in every test case and bug report: "update the address" could be PUT or PATCH, and a request without its method cannot be replayed. For endpoints with roles, keep a small method × role table with the expected status in each cell, and run it again whenever permissions change.
Practice exercise
Review the methods of a shop cart API
You are testing a shop API on staging. Using the contract excerpt and the six observations below, state whether each documented method is safe and idempotent, then decide for each observation whether it is a defect, what should happen instead, and why.
Contract excerpt
GET /v1/cart read the cart
POST /v1/cart/items add an item, body {"sku": "A1", "qty": 1}
PUT /v1/cart/items/{sku} set the quantity of an item, body {"qty": 2}
DELETE /v1/cart/items/{sku} remove an item
PATCH /v1/profile change some profile fields
GET /v1/coupons/apply?code=X apply a coupon to the cart
Observations
a PUT /v1/cart/items/A1 {"qty": 2}, sent twice -> quantity is 4
b Opening /v1/coupons/apply?code=SAVE10 twice -> discount applied twice
c HEAD /v1/cart -> 200 with the full JSON body
d DELETE /v1/cart (not in the contract) -> 500 Internal Server Error
e PATCH /v1/profile {"phone": "0550000000"} -> 200, "email" is now null
f POST /v1/cart/items, retried after a timeout -> the same item appears twice- Mark every contract line as safe or not, and idempotent or not.
- Compare each observation with what its method promises, and write the expected behaviour or a question for the team.
- Order the defects by risk.
Show the model answer
Safe and idempotent by their method: both GET lines, although the coupon line describes a change of state (see b). Idempotent but not safe: PUT and DELETE. Neither: POST, and PATCH in general.
a) Defect. PUT sets the state, so two identical requests must leave quantity 2; this server adds instead.
b) Design defect. Applying a coupon changes state, so it must not sit behind a GET, where crawlers, link previews and prefetching can trigger it. Expected: an unsafe method such as POST /v1/cart/coupons. Even then, the same code applied twice should not double the discount unless the coupon rules allow it.
c) Defect. A HEAD response must not contain a body, and its headers should match those of GET.
d) Defect. Expected 405 Method Not Allowed with an Allow header listing the supported methods, not a server error.
e) Defect. PATCH must change only the fields sent; clearing the e-mail is data loss and may lock the user out.
f) Not automatically a defect, because POST is not idempotent. Ask whether the client should retry a POST at all and whether adding an existing SKU should merge quantities, then test the agreed rule.
Risk order: e (data loss), b (discounts triggered by automated tools), a (wrong quantities and totals), then d and c; f stays open until the team answers.
Frequently asked questions
What is the difference between PUT and PATCH?
PUT sends the complete new state of the resource and replaces what is there, or creates it. PATCH sends only a description of changes, such as a new value for one field. Sending the same PUT twice always leaves the same state; PATCH is not idempotent in general, because a change like "add 1 to the quantity" accumulates.
Can a GET request have a body?
HTTP message framing allows it, but RFC 9110 says content in a GET has no generally defined meaning, cannot change what the request means, and may make some servers reject the request. Put the inputs of a GET in the URI, as the next lesson on path and query parameters shows, or use POST when a search needs a large structured body.
Is POST only for creating resources?
No. POST asks the resource to process the content by its own rules: creating an item, submitting a form, starting a job or running a complex search. 201 Created with Location is expected only when it creates a resource; otherwise 200, 202 or 204, as the contract documents.
Why do I see OPTIONS requests in DevTools that nobody wrote?
Browsers send them as CORS preflights: before certain cross-origin requests, for example a PUT, a DELETE or a request with custom headers, the browser asks the server whether the real request is allowed. If the preflight fails, the real request is never sent. The CORS lesson explains this in detail.
References
- RFC 9110: HTTP SemanticsThe meaning of HTTP methods, header fields, status codes and content negotiation, independent of the wire version.
- RFC 5789: PATCH Method for HTTPThe PATCH method for partial updates, as opposed to PUT replacing a whole resource.
- HTTP request methods — MDNThe HTTP request methods (GET, POST, PUT, PATCH, DELETE and others) and which of them are safe, idempotent and cacheable.
- OWASP API Security Top 10 (2023)The ten most common API weaknesses: broken object-level authorization, broken authentication, unrestricted resource consumption and more.
Practise with Mutqan tools
Compose and send HTTP requests (method, URL, headers, auth, body) and inspect the response — a lightweight Postman in your browser.
Test REST endpoints with full control over method, headers and JSON body, then assert on status, headers and JSON paths.
Build cURL commands from method, URL, headers, body and auth options.
See exactly what your client sends: method, headers, query, body, IP and TLS info.
Look up any HTTP status code with its meaning, RFC reference and when to use it.
Go deeper
Your progress on this topic
Not started
Mark the topic complete when you have studied it and done the exercise.
Sign in to track your progress
Mark topics complete, continue where you left off and unlock specialisation exams.