JavaScript Fetch API
fetch(url) asks the browser to send an HTTP request. It immediately returns a Promise that normally resolves to a Response; it does not return parsed JSON.
Response first, data second
Awaiting fetch gives you status, headers, and a body stream. Calling response.json() reads that body text, parses it as JSON, and returns another Promise whose value is JavaScript data.
The two stages
Keep transport and parsing separate. A response may have a useful status even when its body is not JSON.
📊 From request to data
| Expression | Result | Meaning |
|---|---|---|
| fetch(url) | Promise<Response> | request started |
| await fetch(url) | Response | status, headers, body stream |
| response.json() | Promise<any> | body reading and parsing |
| await response.json() | JavaScript data | parsed object or value |
fetch returns a Promise
This self-contained snippet uses a Blob URL only to demonstrate the return type. A Blob URL is an in-memory browser resource, not a same-origin HTTP endpoint.
const blob = new Blob(['{"drink":"lida tea"}'], { type: "application/json" });
const url = URL.createObjectURL(blob);
const ticket = fetch(url);
console.log(ticket instanceof Promise);
ticket.finally(() => URL.revokeObjectURL(url));
The log is true. For a real app, replace the Blob URL with an HTTP path such as /data/drink.json.
Await Response, then JSON
The next snippet creates the same local resource and performs both awaits.
async function loadDrink() {
const blob = new Blob(['{"drink":"lida tea"}'], { type: "application/json" });
const url = URL.createObjectURL(blob);
try {
const response = await fetch(url);
if (!response.ok) throw new Error("HTTP " + response.status);
const data = await response.json();
console.log(data.drink);
} finally {
URL.revokeObjectURL(url);
}
}
loadDrink();
The log is lida tea. With a real /data/drink.json file, its body would be {"drink":"lida tea"} and the reading steps would be identical.
HTTP errors need an explicit test
fetch usually resolves even when an HTTP server answers 404 or 500. Network failures can reject, but bad HTTP status alone normally does not. Inspect response.ok or response.status.
const response = new Response("Not found", {
status: 404,
statusText: "Not Found"
});
console.log(response.ok);
console.log(response.status);
The constructed response prints false and 404, exactly the properties you would inspect after an HTTP fetch. Avoid parsing an error page as JSON unless its API contract promises JSON.
json returns another Promise
Calling json() starts asynchronous body reading and parsing.
const response = new Response('{"drink":"lida tea"}', {
headers: { "Content-Type": "application/json" }
});
const dataPromise = response.json();
console.log(dataPromise instanceof Promise);
dataPromise.then(data => console.log(data.drink));
The log is true. After await response.json(), data is the JavaScript object and data.drink is the string.
A page demo with no endpoint dependency
This demo fetches a Blob URL, so it runs as a standalone page. It demonstrates the API flow and a status of 200, but it is not presented as a server request.
<!DOCTYPE html>
<html>
<body>
<p id="cup">blank</p>
<p id="line">…</p>
<script>
async function load() {
const blob = new Blob(['{"drink":"lida tea"}'], { type: "application/json" });
const url = URL.createObjectURL(blob);
try {
const response = await fetch(url);
if (!response.ok) throw new Error("HTTP " + response.status);
const data = await response.json();
document.getElementById("cup").textContent = data.drink;
document.getElementById("line").textContent =
response.status + " / " + data.drink;
} finally {
URL.revokeObjectURL(url);
}
}
load();
</script>
</body>
</html>
The page shows 200 / lida tea. In production, use an HTTP URL and keep the same ok test before parsing.
Try it yourself
Create /data/drink.json on a local server, serve valid JSON, and replace the Blob URL. Then request a missing path and compare ok and status.
Common mistakes
Do not treat the Promise from fetch as data. Do not forget to call and await json(). Do not rely on catch to detect every 404.
Remember
fetch sends a request and yields a Promise of Response. Check ok, then parse the expected body. response.json() returns a Promise of JavaScript data.
🧠 Test Your Knowledge
Test Your Knowledge
Challenge yourself with this interactive quiz and see how well you understand the topic
📝 Instructions
- Read each question carefully
- Select the best answer for each question
- You can retake the quiz as many times as you want
- Your progress will be shown at the top