An AJAX request uses the same HTTP methods as any other web client. The method communicates intent: GET reads, POST submits a new processing request or creates a subordinate resource, PUT replaces a known resource representation, PATCH applies a partial change, and DELETE requests removal. The server contract, not the button label, determines the correct method.
After this lesson, you can select a method, send query parameters or a body in the right place, reason about safe and idempotent operations, and design retry behavior that does not duplicate a write.
AJAX requests use standard HTTP methods. Choosing the right method is important for RESTful API design and correct server-side handling.
| Method | Purpose | Has Body? | Idempotent? |
|---|---|---|---|
| GET | Retrieve data | No | Yes |
| POST | Create a resource | Yes | No |
| PUT | Replace a resource entirely | Yes | Yes |
| PATCH | Partially update a resource | Yes | No |
| DELETE | Remove a resource | Optional | Yes |
| HEAD | Like GET but no response body | No | Yes |
// ---- GET Request ----
// Query parameters are appended to the URL
const params = new URLSearchParams({ search: 'javascript', page: 1 });
const xhrGet = new XMLHttpRequest();
xhrGet.open('GET', `/api/posts?${params}`, true);
xhrGet.onload = () => console.log(JSON.parse(xhrGet.responseText));
xhrGet.send(); // GET has no body
// ---- POST Request ----
// Data is sent in the request body
const xhrPost = new XMLHttpRequest();
xhrPost.open('POST', '/api/posts', true);
// Tell the server we're sending JSON
xhrPost.setRequestHeader('Content-Type', 'application/json');
xhrPost.onload = function () {
if (xhrPost.status === 201) {
console.log('Created:', JSON.parse(xhrPost.responseText));
}
};
// Serialize data to JSON and send in the body
xhrPost.send(JSON.stringify({
title: 'My New Post',
body: 'Post content here',
userId: 1
}));
const headers = { 'Content-Type': 'application/json' };
// ---- PUT - replace entire resource ----
fetch('/api/posts/1', {
method: 'PUT',
headers,
body: JSON.stringify({ title: 'Updated Title', body: 'Updated body', userId: 1 })
}).then(res => res.json()).then(console.log);
// ---- PATCH - update specific fields only ----
fetch('/api/posts/1', {
method: 'PATCH',
headers,
body: JSON.stringify({ title: 'Only Title Changed' })
}).then(res => res.json()).then(console.log);
// ---- DELETE - remove a resource ----
fetch('/api/posts/1', {
method: 'DELETE'
}).then(res => {
if (res.ok) console.log('Post deleted successfully');
});
// ---- HEAD - check if resource exists without downloading body ----
fetch('/api/posts/1', { method: 'HEAD' }).then(res => {
console.log('Status:', res.status);
console.log('Content-Type:', res.headers.get('Content-Type'));
});
Request headers provide additional information to the server - such as the content type, authentication tokens, or custom metadata. Use setRequestHeader() with XHR or the headers option with fetch().
// ---- XHR: setRequestHeader() ----
const xhr = new XMLHttpRequest();
xhr.open('POST', '/api/secure-endpoint', true);
// Must be called AFTER open() and BEFORE send()
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.setRequestHeader('Authorization', 'Bearer eyJhbGciOiJIUzI1NiJ9...');
xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest'); // common AJAX identifier
xhr.setRequestHeader('Accept', 'application/json');
xhr.onload = () => console.log(xhr.responseText);
xhr.send(JSON.stringify({ action: 'getData' }));
// ---- Fetch: headers option ----
fetch('/api/secure-endpoint', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer eyJhbGciOiJIUzI1NiJ9...',
'X-Requested-With': 'XMLHttpRequest',
'Accept': 'application/json'
},
body: JSON.stringify({ action: 'getData' })
}).then(res => res.json()).then(console.log);
GET should retrieve a representation without causing the requested business state to change. Put filters, pagination, and sorting in the URL query string so the request can be linked, cached, logged, and repeated. Do not put credentials or sensitive personal data in the URL because URLs appear in history, logs, analytics, and referrer data.
HEAD asks for the same metadata as GET without a response body, while OPTIONS can describe communication options and participates in browser CORS preflight. Application code rarely needs to send a preflight manually; the browser creates it when a cross-origin request requires permission checks.
POST is commonly used when the server chooses the new resource identifier or the operation does not fit replacement semantics. PUT targets a known URI and replaces its representation according to the API contract. PATCH sends a partial update format that the server explicitly supports. DELETE is idempotent in intent: repeating it should not create an additional deletion effect, even if later status codes differ.
Send JSON with a matching Content-Type header and serialize the object once. A successful create commonly returns 201 and a Location header; an accepted asynchronous operation may return 202. Do not assume every successful write returns JSON or every API uses the same status convention.
Safe methods can normally be retried when a transient connection failure occurs. Idempotent write methods are easier to retry than non-idempotent operations, but only when the server contract really preserves that property. For important POST operations such as payments, use an API-supported idempotency key rather than guessing whether a timeout occurred before or after the server committed the work.
A browser CORS error does not mean changing GET to POST will help. The server must allow the requesting origin, method, and headers. Diagnose the network panel and response headers instead of disabling browser security or using no-cors, which produces an opaque response the script cannot inspect.
Try this next
0 of 2 completed
Explore 500+ free tutorials across 20+ languages and frameworks.