Fetch API
The Fetch API is the standard way to make HTTP requests in JavaScript. It replaces the older XMLHttpRequest approach with a cleaner, Promise-based interface.
GET request
The default request method is GET. Pass a URL to fetch() and it returns a Promise that resolves to a Response object.
fetch('https://api.github.com/users')
.then((response) => response.json())
.then((data) => console.log(data))
.catch((err) => console.error(err));
POST request
To send data, pass a second argument to fetch() with the method, headers, and body.
const options = {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ title: 'New post', body: 'Post content' }),
};
fetch('https://jsonplaceholder.typicode.com/posts', options)
.then((response) => response.json())
.then((data) => console.log(data));
Set Content-Type to application/json when sending JSON. Without it, the server may not parse the body correctly.
The Response object
fetch() resolves to a Response object. It contains information about the server’s response.
fetch('https://api.github.com/users').then((response) => {
console.log(response.status); // 200
console.log(response.statusText); // OK
console.log(response.ok); // true (status 200-299)
console.log(response.url); // the URL that was fetched
});
To extract the body, call one of these methods (each returns a Promise):
response.json(): parse the body as JSONresponse.text(): parse the body as plain textresponse.blob(): for binary data like images
Handling errors
fetch() only rejects its Promise on network failure (no internet connection, DNS error). An HTTP error like a 404 or 500 does not cause a rejection; the Promise still resolves, but response.ok is false.
This surprises most beginners. Always check response.ok before parsing the body.
async function getUsers() {
try {
const response = await fetch('https://api.github.com/users');
if (!response.ok) {
throw new Error(`HTTP error: ${response.status}`);
}
const data = await response.json();
return data;
} catch (err) {
console.error('Failed to fetch users:', err.message);
}
}
Check response.ok first, then call response.json(). If you call .json() on an error response, you may get the server’s error body or a parse error, and neither is what you want.
Sending headers
Use the headers option to send additional headers, such as an authorization token.
const response = await fetch('/api/data', {
headers: {
'Authorization': 'Bearer my-token',
'Content-Type': 'application/json',
},
});
Using async/await
async/await makes fetch code easier to follow, especially when chaining multiple requests.
async function fetchData() {
try {
const response = await fetch('https://api.github.com/users');
if (!response.ok) {
throw new Error(`HTTP error: ${response.status}`);
}
const data = await response.json();
console.log(data);
} catch (err) {
console.error('Fetch failed:', err.message);
}
}
fetchData();
Cancelling a request
Use AbortController to cancel a fetch request. This is useful for search-as-you-type, where you want to cancel the previous request when the user types a new character.
const controller = new AbortController();
fetch('/api/data', { signal: controller.signal })
.then((res) => res.json())
.then((data) => console.log(data))
.catch((err) => {
if (err.name === 'AbortError') {
console.log('Request was cancelled');
} else {
console.error('Fetch error:', err.message);
}
});
// Cancel the request before it completes
controller.abort();
FAQ
Why doesn’t fetch() throw on 404 errors?
fetch() only rejects when the network itself fails (you are offline, the DNS lookup fails, the connection is refused). A 404 is a valid HTTP response from the server. The request completed successfully; the server just replied with “not found.” Always check response.ok to catch HTTP errors.
How do I send a JWT token with my request?
Add an Authorization header with the token:
const token = 'your-jwt-token';
const response = await fetch('/api/protected', {
headers: {
Authorization: `Bearer ${token}`,
},
});
What to read next
- async/await : the cleanest way to write fetch logic
- Promises : what fetch() returns under the hood
- AJAX : the concept behind HTTP requests in the browser