The Fetch API
Learn how to make HTTP requests with fetch(), handle the Response object correctly (including the gotcha that fetch only rejects on network failure), send data with POST requests, and cancel requests with AbortController.
Reading Time
18 min
Lesson
Lesson 32 of 48
What fetch() Does
fetch() is the built-in way to make HTTP requests from JavaScript. You call it with a URL, and it returns a Promise — the same kind of Promise you already know how to work with from the Promises and async/await lessons. That Promise resolves to a Response object representing the HTTP response: its status code, headers, and body. Getting the body's actual content, like JSON or text, is a separate, additional step, which trips a lot of people up the first time they use fetch().
A Basic fetch() Call
Console Output
Click “Run” to see the console output here.
The Biggest Gotcha: fetch() Only Rejects on Network Failure
fetch()'s returned promise only rejects if the request never completed — a network failure, a DNS problem, a CORS block, and similar. It does NOT reject just because the server responded with an error status like 404 or 500. A 404 Not Found or a 500 Internal Server Error is still a completed HTTP exchange as far as fetch() is concerned, so the promise fulfills normally with a Response object whose .ok is false and whose .status reflects the error. If you don't check this yourself, your .then() or await will happily treat a failed request as a success.
Checking response.ok Yourself
Console Output
Click “Run” to see the console output here.
Parsing the Response Body
The Response object gives you several methods to read its body, and each one returns yet another Promise, because reading the body is itself an asynchronous streaming operation. response.json() parses the body as JSON and resolves with the resulting value. response.text() resolves with the raw body as a plain string, useful for HTML, plain text, or anything that isn't JSON. You can only read a response's body once — if you need to inspect it more than once, clone it first with response.clone().
response.json() vs. response.text()
Console Output
Click “Run” to see the console output here.
Sending a POST Request
By default, fetch() sends a GET request. To send other HTTP methods, or to include a request body, pass a second argument: an options object. The method property sets the HTTP verb, headers sets any request headers (like telling the server you're sending JSON), and body carries the actual payload. Since body must be a string (or a few other specific types), you typically serialize a JavaScript object into JSON yourself with JSON.stringify() before sending it.
POST with a JSON Body
Console Output
Click “Run” to see the console output here.
Using fetch() with async/await and try/catch
Since fetch() returns a Promise, everything from the async/await lesson applies directly: await the call, and wrap it in a try/catch to handle both genuine network failures (caught automatically, since those are real rejections) and HTTP error statuses (which you still need to check and throw yourself, per the gotcha above). This combination — await plus a manual response.ok check plus try/catch — is the standard, production-ready shape for a fetch() call.
The Standard fetch() Pattern
Console Output
Click “Run” to see the console output here.
Cancelling a Request with AbortController
Sometimes you need to cancel an in-flight fetch() — a user navigates away, types a new search query before the last one finished, or a request is simply taking too long. AbortController gives you a way to do this. You create a controller, pass its .signal to fetch()'s options object, and call controller.abort() whenever you want to cancel. The pending fetch() promise then rejects with an AbortError, which you can detect and handle separately from a genuine network failure.
Aborting a fetch() Request
Console Output
Click “Run” to see the console output here.
Response Object Cheat Sheet
| Property / Method | Purpose |
|---|---|
| response.status | The numeric HTTP status code (200, 404, 500, etc.) |
| response.ok | true if status is in the 200-299 range, false otherwise |
| response.json() | Returns a Promise that resolves with the body parsed as JSON |
| response.text() | Returns a Promise that resolves with the body as a raw string |
| response.headers | A Headers object for reading response headers |
Always Check response.ok Before Parsing
Make it a habit to check response.ok (or response.status) immediately after every fetch() call, before trying to parse the body. Treating a non-ok response as success, and only discovering the problem when .json() fails to parse an HTML error page, is one of the most common fetch() mistakes.
Course Complete
That's the end of the JavaScript fundamentals section of this course — 47 lessons covering everything from the basics of variables and functions through closures, prototypes, the event loop, memory management, and now the Fetch API. Everything you've learned here — Promises, async/await, and now fetch() — is the foundation you'll use constantly when building real applications that talk to real APIs. Congratulations on making it through the whole curriculum.