Web APIs Cheatsheet
Fetch and HTTP
Use this Web APIs reference while you build software engineering projects, review code for technical interview prep, or polish examples for a software engineer resume.
Basic Fetch
// GET (default) const res = await fetch('/api/data'); const json = await res.json(); // POST with JSON body const res = await fetch('/api/users', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ name: 'Alice' }), }); const data = await res.json();
fetch() Options
| Option | Type | Description |
|---|---|---|
method | string | 'GET' 'POST' 'PUT' 'PATCH' 'DELETE' 'HEAD' |
headers | object | Headers | Request headers |
body | string | Blob | BufferSource | FormData | URLSearchParams | ReadableStream | Request body (not allowed on GET/HEAD) |
mode | string | 'cors' (default) 'no-cors' 'same-origin' 'navigate' |
credentials | string | 'omit' 'same-origin' (default) 'include' |
cache | string | 'default' 'no-store' 'reload' 'no-cache' 'force-cache' 'only-if-cached' |
redirect | string | 'follow' (default) 'error' 'manual' |
referrerPolicy | string | 'no-referrer' 'origin' 'strict-origin-when-cross-origin' … |
signal | AbortSignal | Cancel the request |
keepalive | boolean | Keep request alive after page unload |
priority | string | 'high' 'low' 'auto' |
Response Object
| Property / Method | Returns | Notes |
|---|---|---|
res.ok | boolean | true when status 200–299 |
res.status | number | HTTP status code |
res.statusText | string | e.g. 'OK' |
res.headers | Headers | Iterable headers map |
res.url | string | Final URL after redirects |
res.redirected | boolean | Whether a redirect occurred |
res.type | string | 'basic' 'cors' 'opaque' … |
res.body | ReadableStream | Raw body stream |
res.bodyUsed | boolean | true once body consumed |
res.json() | Promise\<any\> | Parse body as JSON |
res.text() | Promise\<string\> | Body as text |
res.blob() | Promise\<Blob\> | Body as Blob |
res.arrayBuffer() | Promise\<ArrayBuffer\> | Body as binary |
res.formData() | Promise\<FormData\> | Body as FormData |
res.clone() | Response | Clone before consuming body twice |
Headers API
const headers = new Headers({ 'Content-Type': 'application/json' }); headers.set('Authorization', 'Bearer token'); headers.append('X-Custom', 'value'); headers.get('content-type'); // 'application/json' headers.has('Authorization'); // true headers.delete('X-Custom'); // Iterate for (const [key, val] of headers) { /* … */ } headers.forEach((val, key) => { /* … */ });
Request API
const req = new Request('/api/data', { method: 'GET', headers: { Accept: 'application/json' }, }); req.url; // full URL string req.method; // 'GET' req.headers; // Headers object req.clone(); // clone before passing to fetch fetch(req).then(/* … */);
Aborting Requests
const controller = new AbortController(); const { signal } = controller; fetch('/api/slow', { signal }) .then(res => res.json()) .catch(err => { if (err.name === 'AbortError') console.log('Request aborted'); }); // Cancel after 5 s setTimeout(() => controller.abort(), 5000); // Pass a reason controller.abort(new Error('User cancelled'));
// AbortSignal.timeout() — no controller needed const res = await fetch('/api/data', { signal: AbortSignal.timeout(3000), // ms });
Error Handling
fetch()only rejects on network failure; HTTP 4xx/5xx still resolve. Always checkres.ok.
async function apiFetch(url, options) { const res = await fetch(url, options); if (!res.ok) { const body = await res.text(); throw new Error(`HTTP ${res.status}: ${body}`); } return res.json(); }
Sending FormData and Files
const form = new FormData(); form.append('username', 'alice'); form.append('avatar', fileInput.files[0]); // Do NOT set Content-Type manually — browser sets multipart boundary await fetch('/api/upload', { method: 'POST', body: form });
Streaming Responses
const res = await fetch('/api/stream'); const reader = res.body.getReader(); const decoder = new TextDecoder(); while (true) { const { done, value } = await reader.read(); if (done) break; console.log(decoder.decode(value, { stream: true })); }
Streaming with async iteration (modern)
const res = await fetch('/api/stream'); for await (const chunk of res.body) { console.log(new TextDecoder().decode(chunk)); }
Uploading with Progress (XMLHttpRequest)
fetch()has no upload-progress API yet. UseXMLHttpRequestfor upload progress.
const xhr = new XMLHttpRequest(); xhr.upload.addEventListener('progress', e => { if (e.lengthComputable) console.log(e.loaded / e.total); }); xhr.open('POST', '/api/upload'); xhr.send(formData); xhr.onload = () => console.log(xhr.status, xhr.responseText);
XMLHttpRequest Quick Reference
const xhr = new XMLHttpRequest(); xhr.open('GET', '/api/data', true /* async */); xhr.responseType = 'json'; // '', 'arraybuffer', 'blob', 'document', 'json', 'text' xhr.timeout = 5000; // ms xhr.setRequestHeader('Accept', 'application/json'); xhr.onload = () => console.log(xhr.status, xhr.response); xhr.onerror = () => console.error('Network error'); xhr.ontimeout = () => console.error('Timeout'); xhr.onprogress = e => console.log(e.loaded, e.total); xhr.onreadystatechange = () => { // readyState: 0 UNSENT, 1 OPENED, 2 HEADERS_RECEIVED, 3 LOADING, 4 DONE }; xhr.send(null); // or body xhr.abort();
CORS Essentials
| Scenario | Headers Required |
|---|---|
| Simple cross-origin GET/POST (text/plain, form types) | Access-Control-Allow-Origin on response |
| Custom headers or PUT/DELETE (preflight) | Server must respond to OPTIONS with Access-Control-Allow-Methods, Access-Control-Allow-Headers |
| Cookies cross-origin | credentials: 'include' + server Access-Control-Allow-Credentials: true + specific (not *) origin |
// Include cookies / auth headers cross-origin fetch('https://api.example.com/data', { credentials: 'include' });
Common Patterns
// Retry with exponential backoff async function fetchWithRetry(url, opts, retries = 3) { for (let i = 0; i < retries; i++) { try { const res = await fetch(url, opts); if (!res.ok && res.status >= 500) throw new Error(res.status); return res; } catch (err) { if (i === retries - 1) throw err; await new Promise(r => setTimeout(r, 2 ** i * 500)); } } } // JSON helper const get = url => fetch(url).then(r => r.ok ? r.json() : Promise.reject(r)); // Base URL wrapper const api = (path, opts) => fetch(`https://api.example.com${path}`, { ...opts, headers: { Authorization: `Bearer ${token}`, ...opts?.headers }, });
Caching Strategies
cache value | Behavior |
|---|---|
'default' | Uses browser cache with HTTP semantics (ETags, max-age) |
'no-store' | Never cache; never use cached response |
'reload' | Always fetch from network; store result in cache |
'no-cache' | Validate with server (conditional request) even if cached |
'force-cache' | Return cached response even if stale |
'only-if-cached' | Return cache or fail (only with mode: 'same-origin') |
Server-Sent Events (EventSource)
const es = new EventSource('/api/events'); // named event es.addEventListener('update', e => console.log(JSON.parse(e.data))); // unnamed / message event es.onmessage = e => console.log(e.data); es.onerror = e => console.error(e); es.close(); // With credentials const es2 = new EventSource('/api/events', { withCredentials: true });