fetch and APIs, talking to a real backend
fetch is how JavaScript talks to APIs in 2026. It is built into every browser, every Node version since 18, every modern runtime. No axios required unless you really want it.
It is also the source of one of the most common bugs in early JS code. We will cover that too.
The simplest GET
const res = await fetch('https://api.example.com/orders');
const data = await res.json();Two awaits. The first awaits the HTTP response. The second awaits the body being parsed as JSON. res.json() is itself async because the body may still be streaming.
Need text? Use res.text(). Need a binary blob? Use res.blob().
POST with a JSON body
const res = await fetch('https://api.example.com/orders', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ restaurant: 'MTR', total: 320 }),
});methoddefaults toGET. SetPOST,PUT,PATCH,DELETEas needed.headersis a plain object. TheContent-Typeheader tells the server what shape your body is in.bodymust be a string for JSON.JSON.stringifyis mandatory. Forget it and your server will get[object Object].
The fetch gotcha that catches everyone
fetch does not reject on a 404 or 500 response. It only rejects on a network failure (DNS, connection refused, CORS block). A 500 from the server is still a "successful" response in fetch's view.
const res = await fetch(url);
if (!res.ok) {
throw new Error(`API failed: ${res.status}`);
}
const data = await res.json();Check res.ok (true for 200-299) or res.status explicitly. Every. Single. Time.
If you skip the
res.okcheck, your code will silently treat error pages as data and fail in a confusing way later.
CORS, the browser bouncer
CORS (Cross-Origin Resource Sharing) is a browser security feature. By default, your JavaScript at myapp.com cannot read responses from api.someoneelse.com. The browser blocks it unless that server explicitly allows you with an Access-Control-Allow-Origin header.
This is a server-side fix, not a client one. If you control the API, add the header. If you do not, route the request through your own backend. There is no magic fetch flag that disables CORS in a browser, and that is by design.
AbortController for cancellable requests
User typed in a search box, then typed again. You want to cancel the first request. That is what AbortController is for.
const controller = new AbortController();
const res = await fetch('/api/search?q=biryani', { signal: controller.signal });
// later, somewhere:
controller.abort();The aborted fetch rejects with an AbortError. Catch it and move on. Almost every real search UI uses this pattern.
Quick recap
fetch(url, options), thenawait res.json()for the body.- Always check
res.ok. Fetch does not throw on 4xx or 5xx. - CORS is a server-side header. Cannot be bypassed in the browser.
- Use
AbortControllerto cancel stale requests.
Next lesson: the DOM, which is where all this fetched data finally meets the user.
Free tools you can use while you learn
Watching quietly. Tap me if you want a tip.
Try this (0 of 1 done)
- 1
Use async/await to fetch from https://api.github.com/zen and log it.
show answer
(async () => { const r = await fetch('https://api.github.com/zen'); const text = await r.text(); console.log(text); })();