Your first request, and the data that comes back
Everything so far comes together in about eight lines: ask a real server for real prices and print them.
The code
// fetch.js — run with: node fetch.js
const url = "https://eodhd.com/api/eod/AAPL.US?api_token=demo&fmt=json&from=2026-08-20";
const res = await fetch(url);
console.log(res.status); // 200, you hope
const bars = await res.json(); // text -> array of objects
console.log(bars.length);
console.log(bars[0]);
Every piece is something you have met: a URL with a query, a status code, JSON becoming objects, an array indexed from zero.
await, and why it exists
A request goes over the internet and takes time. await means wait here for the answer before continuing. Without it you get a Promise — a placeholder for an answer that has not arrived — and printing one shows Promise { <pending> } rather than your data.
That is a confusing first sight, and now it will not be: Promise { <pending> } means a missing await.
The check that matters
if (!res.ok) {
console.log("request failed:", res.status);
} else {
const bars = await res.json();
console.log(bars.length);
}
The else is doing real work: it is what stops res.json() running on a response you already know is an error.
fetch does not throw on a 404 or a 429 — those are successful conversations in which the server said no. Only a network failure throws. So code without an res.ok check happily tries to read prices out of an error message.
Course 1 finds this exact omission in generated code, and course 3 finds a 404 whose body is not even JSON, so res.json() throws somewhere you were not expecting.
About api_token=demo
That is a shared demonstration key, good for a few tickers and not yours. Course 1 has you get your own free key and — this is the point of the previous lesson — put it somewhere the browser never sees.
Try it now
Run it. Then break it three ways on purpose: misspell the ticker and read the status, remove the await and see the Promise, and turn off your wifi to see what a real throw looks like. Three deliberate failures teach more than one success.
So you know the first one when you see it: with the demo key and APPL typed for AAPL in the URL, the script printed these two lines on 28 September 2026 (Node adds a stack trace under the second), from the first version of the script, the one without the res.ok check:
403
SyntaxError: Unexpected token 'F', "Forbidden" is not valid JSON
A 403 rather than a 404, because the demo key refuses any symbol it does not cover before looking it up, and a throw on the next line, because the body is the plain word Forbidden. That second line is what the res.ok check exists to prevent.