I stared at this exact console output longer than I want to admit: the fetch clearly worked, the response was right there, and my data was still undefined. If that's where you are, here's what's actually happening.
You call an API with fetch, log the result, and get Promise {<pending>} where your data should be. When fetch returns Promise pending, your code isn’t broken. It just didn’t wait.
The Problem: fetch Returns Promise Pending
const data = fetch("https://api.github.com/users/octocat");
console.log(data); // Promise {<pending>}
You expected a user. You got a strange object with nothing useful in it.
Why It Happens
A request over the internet is slow. It can take half a second, which is a very long time for JavaScript. So fetch doesn’t make your whole page stand still until the answer arrives. It returns immediately and hands you a Promise.
Think of a Promise as a receipt. It isn’t the thing you ordered. It says the thing is on its way. pending means it hasn’t arrived yet. Your console.log ran a few milliseconds after the request left, long before any answer came back.
The Fix: async and await
async function loadUser() {
const response = await fetch("https://api.github.com/users/octocat");
const user = await response.json();
console.log(user.name); // The Octocat
}
loadUser();
await pauses this one function until the Promise is finished, then gives you the real value. The rest of the page keeps working.
Look closely: there are two awaits. response.json() reads the body of the answer, and that takes time too, so it returns another Promise. Forget the second await and you’re back to pending.
The Same Fix with .then()
fetch("https://api.github.com/users/octocat")
.then((response) => response.json())
.then((user) => console.log(user.name));
This is the older style, and it does the same job. Each .then runs when the step before it has finished. Use whichever you find easier to read.
If fetch Still Returns Promise Pending
You returned the data out of the function.
const user = loadUser();is a Promise again, because anasyncfunction always returns one. Use the data inside the function, orawaitthe call.awaitoutside an async function. It works only inside a function markedasync, or at the top level of a module script.A 404 that looks like success.
fetchdoesn’t throw an error when the server answers “not found”. Checkresponse.okyourself.
async function loadUser(name) {
try {
const response = await fetch("https://api.github.com/users/" + name);
if (!response.ok) {
console.log("Request failed:", response.status);
return;
}
const user = await response.json();
console.log(user.name);
} catch (error) {
console.log("Network problem:", error);
}
}
The try and catch handle the case where there is no connection at all.
So when fetch returns Promise pending, look for the missing await first. MDN’s guide to using the Fetch API covers headers, POST requests and more.
To build a whole page around an API, follow my tutorial on how to make websites using an API. For the basics first, see how to make a website using JavaScript.
Which API are you calling? Tell me in the comments, and paste the line that logs pending if you’re stuck.
Originally published on my blog. I post new C, Python and AI-agent guides there regularly.

Top comments (0)