AJAX cheat sheet
A scannable AJAX reference: 11 short snippets across 6 topics, each linking back to the lesson it came from.
At a glance
| Topic | What it covers | |
|---|---|---|
| Requests with fetch | Idempotency is what makes retries safe: repeating a PUT or DELETE leaves the same state, while repeating a POST usually | lesson |
| Bodies, headers and status codes | Some headers can never be set from script: Host, Content-Length, Cookie and Origin belong to the browser. On the way | lesson |
| XMLHttpRequest and the gaps in fetch | The original transport API, upload progress with xhr.upload, and an honest comparison of when XMLHttpRequest is still | lesson |
| Same-origin policy, CORS and credentials | An origin is the scheme, host and port together. The policy does not stop a script from sending a cross-origin request | lesson |
| Caching and conditional requests | A validator lets the server answer a full request with 304 Not Modified and an empty body. You keep the parsing work | lesson |
| Debugging network problems | The console message names the cause once you read it as three parts: the request, the response headers, and the missing | lesson |
Quick snippets
Requests with fetch
A minimal request
const res = await fetch('/api/tasks?limit=20', {
headers: { Accept: 'application/json' },
credentials: 'same-origin'
});
if (!res.ok) throw new Error('HTTP ' + res.status); // fetch does not throw on 404 or 500
const data = await res.json(); // the body can be read once
Sending data
await fetch('/api/tasks', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ title: 'Ship it' })
});
const fd = new FormData(form); // multipart; no header needed
await fetch('/upload', { method: 'POST', body: fd });
await fetch('/api/tasks/7', { method: 'DELETE' });Full lesson: Requests with fetch →
Bodies, headers and status codes
Request and response headers
const res = await fetch('/api/me', {
headers: {
'Accept': 'application/json',
'Authorization': 'Bearer ' + token,
'X-CSRF-Token': getCsrfToken()
}
});
res.headers.get('content-type'); // 'application/json; charset=utf-8'
res.headers.get('cache-control');
res.headers.get('link'); // pagination, when the API sends it
Reading the response body
const res = await fetch('/report.csv');
const text = await res.text(); // any text payload
const blob = await res.blob(); // binary; feed it to a download link
const buf = await res.arrayBuffer(); // bytes for decoding yourself
const data = await res.json(); // JSON.parse on the body text
// stream a large body instead of buffering all of it
const reader = res.body.getReader();
const { value, done } = await reader.read();
Status codes worth branching on
async function request(url, init) {
const res = await fetch(url, init);
if (res.status === 204) return null;
if (res.status === 401) { await refresh(); return request(url, init); }
if (res.status === 429) {
const wait = Number(res.headers.get('retry-after') || 5);
throw new Error('rate limited, retry in ' + wait + 's');
}
if (!res.ok) throw new Error('HTTP ' + res.status);
return res.json();
}Full lesson: Bodies, headers and status codes →
XMLHttpRequest and the gaps in fetch
Upload progress
const xhr = new XMLHttpRequest();
xhr.upload.onprogress = event => {
if (event.lengthComputable) {
bar.value = Math.round((event.loaded / event.total) * 100);
}
};
xhr.upload.onload = () => console.log('sent');
xhr.onload = () => console.log('response', xhr.status);
xhr.open('POST', '/upload');
xhr.send(file);
Choosing between them
// both transports cancel the same way from the caller's point of view
xhr.send();
xhr.abort(); // fires onabort, then onloadend
const ac = new AbortController();
fetch(url, { signal: ac.signal }).catch(err => {
if (err.name !== 'AbortError') throw err;
});
ac.abort();Full lesson: XMLHttpRequest and the gaps in fetch →
Same-origin policy, CORS and credentials
What the same-origin policy really does
// same origin: CORS never enters the picture
await fetch('/api/me');
// cross-origin, credentials omitted by default
await fetch('https://api.example.com/me');
// cross-origin with cookies: the server must opt in too
await fetch('https://api.example.com/me', {
credentials: 'include',
headers: { 'X-Request-Id': crypto.randomUUID() }
});
Simple and preflighted requests
OPTIONS /me HTTP/1.1
Host: api.example.com
Origin: https://app.example.com
Access-Control-Request-Method: PUT
Access-Control-Request-Headers: content-type, x-csrf-token
HTTP/1.1 204 No Content
Access-Control-Allow-Origin: https://app.example.com
Access-Control-Allow-Methods: GET, POST, PUT, DELETE
Access-Control-Allow-Headers: Content-Type, X-CSRF-Token
Access-Control-Max-Age: 600
Vary: OriginFull lesson: Same-origin policy, CORS and credentials →
Caching and conditional requests
Cache-Control and freshness
// the browser handles freshness for you when the server allows it
const res = await fetch('/api/config'); // may come from the HTTP cache
res.headers.get('age'); // seconds since the response was generated
res.headers.get('cache-control');
// bypass the cache deliberately: a pull-to-refresh, an after-write reload
await fetch('/api/tasks', { cache: 'no-store' });
await fetch('/api/tasks', { cache: 'reload' });
// force revalidation and accept a 304
await fetch('/api/tasks', { cache: 'no-cache' });Full lesson: Caching and conditional requests →
Debugging network problems
Reading a CORS failure correctly
# reproduce without CORS: curl is not a browser and ignores the policy
curl -i -X OPTIONS 'https://api.example.com/me' \
-H 'Origin: https://app.example.com' \
-H 'Access-Control-Request-Method: PUT' \
-H 'Access-Control-Request-Headers: content-type'
# if the headers are missing here, the problem is on the server, not in your code
curl -i 'https://api.example.com/me' -H 'Origin: https://app.example.com'Full lesson: Debugging network problems →
FAQ
Is this AJAX cheat sheet free to use?
Yes. No sign-up and no tracking: the page is static, every example is on the page itself, and you can print it or save it as a one-page reference.
Where do the examples come from?
Every snippet is taken from the 6 lessons of the AJAX course on this site, and each section links back to the lesson it was pulled from.
How do I go deeper than a cheat sheet?
Open the full AJAX course — it carries the worked explanations, the edge cases and the exercises behind every line here.
Related cheat sheets
HTML CSS JavaScript TypeScript HTML DOM JSON
Last refreshed 2026-09-27.