// apis · Web Platform Advent #1
The Fetch API in JavaScript: a practical guide
How to make HTTP requests in the browser with the Fetch API — GET, JSON, POST, error handling, and aborting requests — with runnable examples.
The Fetch API is the modern, promise-based way to make HTTP requests from the browser. It replaces the older XMLHttpRequest with a cleaner interface that works naturally with async/await and streams. Every current browser supports it.
A first GET request
fetch() returns a promise that resolves to a Response object. To read JSON from it, call response.json(), which itself returns a promise:
const res = await fetch('https://api.example.com/articles');
const data = await res.json();
console.log(data); The same thing without async/await, using .then() chains:
fetch('https://api.example.com/articles')
.then((res) => res.json())
.then((data) => console.log(data)); The gotcha: fetch does not reject on HTTP errors
This trips up almost everyone. A 404 or 500 response is still a successful fetch — the promise only rejects on a network failure (offline, DNS, CORS). You must check response.ok yourself:
const res = await fetch(url);
if (!res.ok) {
throw new Error(`HTTP ${res.status} ${res.statusText}`);
}
const data = await res.json();
fetch() call sends an HTTP request across the network to a server and waits for the response to travel back.Sending data with POST
Pass a second options argument to set the method, headers and body. For JSON, stringify the payload and set the Content-Type:
const res = await fetch('/api/articles', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ title: 'Hello', body: 'World' }),
});
const created = await res.json(); Aborting a request
Use an AbortController to cancel a request — useful for timeouts or when a component unmounts:
const controller = new AbortController();
const timeout = setTimeout(() => controller.abort(), 5000);
try {
const res = await fetch(url, { signal: controller.signal });
const data = await res.json();
} catch (err) {
if (err.name === 'AbortError') console.log('Request timed out');
} finally {
clearTimeout(timeout);
} Quick reference
| Task | How |
|---|---|
| Read JSON | await res.json() |
| Read text | await res.text() |
| Check success | res.ok / res.status |
| Send JSON | body: JSON.stringify(...) + Content-Type |
| Cancel | AbortController + signal |
That covers the everyday cases. The Fetch API also supports streaming response bodies, FormData uploads, and request/response cloning — but the patterns above handle the vast majority of real-world calls.