Loading...

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.

fetch returns a Promise

javascript
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.

Await Response and JSON

javascript
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.

Inspect an HTTP-style error response

javascript
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.

json returns a Promise

javascript
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.

Standalone fetch page

html
<!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

Ready to Start

Test Your Knowledge

Challenge yourself with this interactive quiz and see how well you understand the topic

❓
5
Questions
🎯
70%
To Pass
♾️
∞
Time
🔄
∞
Attempts

📝 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