fetch() is how JavaScript talks to the internet. With it you can load the latest weather, search a list of films, post a comment or save a score. Combine it with async/await and JSON and you can build apps that work with real, live data.
The services you fetch data from are called APIs (Application Programming Interfaces). An API is an address on a server that returns data instead of a web page. This lesson brings together several earlier topics, so if anything feels unfamiliar, the linked lessons are worth a quick review.
A GET request in three steps
const response = await fetch("https://jsonplaceholder.typicode.com/users/1");
const user = await response.json();
console.log(user.name);fetch(url)sends the request and returns a promise for a Response object.response.json()reads the body of the response and parses the JSON. It also returns a promise, soawaitit too.- Use the data, for example by displaying it on the page.
GET is the default type of request, used for reading data. You don't need to specify it.
Always check response.ok
fetch only rejects when the network itself fails, for example when the visitor is offline or the domain doesn't exist. A "404 Not Found" or "500 Server Error" still resolves successfully. Check the result yourself:
if (!response.ok) {
throw new Error(`HTTP ${response.status}`);
}response.status holds the status code: 200 means OK, 404 means Not Found and 500 means Server Error. Skipping this check is one of the most common fetch bugs, because the code then tries to read data that isn't there.
Sending data with a POST request
const response = await fetch(url, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ title: "Hello" }),
});methodisGET(the default),POST(create),PUTorPATCH(update) orDELETE.headerstell the server what kind of data you're sending.bodyis the data itself, converted to a JSON string.
Adding query parameters
Build URLs safely with URLSearchParams, which escapes spaces and special characters for you:
const params = new URLSearchParams({ q: "banana bread", page: 2 });
fetch(`https://api.example.com/search?${params}`);JavaScript Fetch API Syntax
fetch patterns
async function getJSON(url) {
const res = await fetch(url);
if (!res.ok) throw new Error(`HTTP ${res.status}`);
return res.json();
}
await fetch(url, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(data),
});JavaScript Fetch API Summary
fetch(url)sends a request and returns a promise for a Response.- Use
await response.json()to read JSON data. - Always check
response.ok, because HTTP errors don't reject the promise. - Send data with
method: "POST", a JSON header and a stringified body. - Show loading and error states so visitors know what's happening.
JavaScript Fetch API Examples
Each example runs in the page. Edit the code and press Run to see what changes.
Load a user
This calls a public practice API, JSONPlaceholder. Change the 1 to another number from 1 to 10.
async function loadUser(id) {
const response = await fetch(`https://jsonplaceholder.typicode.com/users/${id}`);
console.log("Status:", response.status);
const user = await response.json();
console.log(user.name, "|", user.email);
console.log("Lives in", user.address.city);
}
loadUser(1);Line-by-line explanation
- Line 2Request the user.
awaitwaits for the response headers. - Line 3200 means OK.
- Line 5Parse the JSON body.
- Lines 6 to 7Use the data like any object.
A list with loading and error states
<button id="load">Load posts</button>
<p id="status"></p>
<ol id="posts"></ol>const button = document.querySelector("#load");
const statusEl = document.querySelector("#status");
const list = document.querySelector("#posts");
button.addEventListener("click", async () => {
button.disabled = true;
statusEl.textContent = "Loading…";
list.replaceChildren();
try {
const res = await fetch("https://jsonplaceholder.typicode.com/posts?_limit=5");
if (!res.ok) throw new Error(`HTTP ${res.status}`);
const posts = await res.json();
for (const post of posts) {
const li = document.createElement("li");
li.textContent = post.title;
list.append(li);
}
statusEl.textContent = `Loaded ${posts.length} posts ✅`;
} catch (error) {
statusEl.textContent = "Couldn't load posts: " + error.message;
} finally {
button.disabled = false;
}
});Line-by-line explanation
- Lines 6 to 8Show a loading state and clear old results.
- Lines 11 to 12Request and check the status.
- Lines 15 to 20Turn data into list items with
textContent(safe from injected HTML). - Lines 21 to 22Friendly error message.
- Lines 23 to 25Always re-enable the button.
Sending data with POST
JSONPlaceholder pretends to save it and sends back the new item with an id.
async function createTodo(title) {
const res = await fetch("https://jsonplaceholder.typicode.com/todos", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ title, completed: false }),
});
if (!res.ok) throw new Error(`HTTP ${res.status}`);
const saved = await res.json();
console.log("Saved with id", saved.id, "→", saved.title);
}
createTodo("Learn fetch").catch(err => console.log("Error:", err.message));Line-by-line explanation
- Lines 3 to 5Method, headers and a JSON body.
- Line 8Check for server errors.
- Lines 9 to 10The server replies with what it saved.
Common JavaScript Fetch API Mistakes
Forgetting to await response.json()
const res = await fetch(url);
const data = res.json(); // a Promise!
console.log(data.name); // undefinedconst data = await res.json();Assuming fetch rejects on 404
try {
const res = await fetch("/missing");
const data = await res.json(); // crashes on an HTML error page
} catch (e) { … }const res = await fetch("/missing");
if (!res.ok) throw new Error(`HTTP ${res.status}`);Putting secret API keys in front-end code
fetch(`https://api.paid.com/data?key=sk_live_123456`);// call your own server, which keeps the key secret and calls the paid API
fetch("/api/data");Anyone can read your JavaScript in the browser. Keep secrets on a server.
JavaScript Fetch API in Real Projects
Real apps are built on fetch
Weather widgets, live sports scores, social feeds, "load more" buttons, search suggestions, payment forms and dashboards all fetch JSON from APIs. You now know the complete pattern: request → check → parse → render → handle errors.
JavaScript Fetch API Exercises
Answer each one and check it instantly. If you get stuck, open the hint before the answer.
Read the JSON body.
const res = await (url);
const data = await res.();
.json() parses its body.What does fetch do when the server replies with 404?
Which option sends JSON data to a server?
getTitle(1) should return the title of todo 1 ("delectus aut autem") and log it. Fix the function.
async function getTitle(id) {
const res = fetch(`https://jsonplaceholder.typicode.com/todos/${id}`);
const todo = res.json();
return todo.title;
}
getTitle(1).then(t => console.log(t));- getTitle(1) returns the title
JavaScript Fetch API Quiz
3 questions to check what you learned.
What does
response.status200 mean?- Not found
- Server error
- Redirect
- OK, meaning success
Which HTTP method is used to create new data?
- GET
- POST
- DELETE
- HEAD
Why use
URLSearchParamsto build query strings?- It correctly escapes spaces and special characters
- It's faster
- fetch requires it
- It adds an API key
JavaScript Fetch API Challenge
Count completed todos
Write async function countDone(userId) that:
- Fetches
https://jsonplaceholder.typicode.com/todos?userId=+userId - Checks
response.okand parses the JSON - Returns how many todos have
completed === true
Then log User 1 completed 11 todos.
- countDone(1) resolves to 11
- Checks response.ok
- Logs the summary