Syntax
fetch(url, options).then(response => response.json())Breaking down the syntax
await fetch(url)- Waits for a Response, not the parsed body.
response.ok- True for status codes 200 through 299.
await response.json()- Reads and parses JSON. Invalid JSON can throw.
How it works
Fetch requests a resource asynchronously. Check the HTTP status, then read the response body in the format you expect.
Start with a small example
Run the first example, then change one value and predict the result.
Apply the idea
Compare the alternatives below before using this pattern in your own project.
Examples
Load a demo lesson
Prints Arrays without relying on an external service.
async function loadLesson() {
const url = "data:application/json," + encodeURIComponent(JSON.stringify({ title: "Arrays" }));
try {
const response = await fetch(url);
if (!response.ok) throw new Error(`HTTP ${response.status}`);
const lesson = await response.json();
console.log(lesson.title);
} catch (error) {
console.log("Could not load lesson:", error.message);
}
}
loadLesson();- Prints Arrays without relying on an external service.
- Replace the data URL with an API URL when connecting a real service.
Handle an unsuccessful status
Simulates HTTP 404 without a network request.
async function checkResponse() {
const response = new Response("Not found", { status: 404 });
try {
if (!response.ok) throw new Error(`HTTP ${response.status}`);
console.log(await response.text());
} catch (error) {
console.log("Could not load lesson:", error.message);
}
}
checkResponse();- Simulates HTTP 404 without a network request.
- The explicit check throws and the catch prints a failure message.
Basic GET Request
Fetching and parsing JSON data.
fetch("https://api.example.com/users/1")
.then(response => {
if (!response.ok) {
throw new Error(`HTTP error: ${response.status}`);
}
return response.json();
})
.then(user => console.log(user))
.catch(error => console.log("Fetch failed:", error.message));POST Request with async/await
Sending data with a request, and awaiting the result.
async function createUser(userData) {
try {
const response = await fetch("https://api.example.com/users", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(userData)
});
if (!response.ok) {
throw new Error(`Server responded with ${response.status}`);
}
return await response.json();
} catch (error) {
console.log("Failed to create user:", error.message);
}
}
createUser({ name: "Alice", email: "alice@example.com" });Best practices
- Always check response.ok before parsing - fetch() only rejects on network failures, not on HTTP error statuses like 404 or 500
- Wrap fetch calls in try/catch (with async/await) or add a .catch() to handle network failures gracefully
- Set the Content-Type header explicitly when sending JSON, and remember to JSON.stringify() the body
- Use AbortController to cancel a fetch request if it is no longer needed, such as when a user navigates away
Runtime & versions
Browsers and JavaScript runtimes. Feature availability depends on the language and runtime version used by your project; consult the official reference below.
ECMAScript specificationWhen should I use this?
Load JSON data. Check unsuccessful HTTP statuses. Handle errors with useful feedback.
Common mistakes
Assuming HTTP errors reject fetch
A 404 can still resolve the promise; check the status explicitly.
Incorrect
const data = await response.json();Corrected
if (!response.ok) throw new Error(`HTTP ${response.status}`);
const data = await response.json();Compare approaches
- json(): Parse structured JSON.
- text(): Read plain text.
Explore deeper
Real APIs
The first demo uses a local data URL; the second simulates a response. Neither tests a remote server. Real cross-origin requests require the server to allow your origin with CORS. no-cors does not make an opaque response readable.
Body and data validation
A response body is normally consumed once. HTTP success does not guarantee valid JSON or the data shape you need. Never put private API credentials in frontend code.