The Fetch API is JavaScript's built-in, Promise-based way to make HTTP requests from the browser. This lesson covers issuing GET and POST requests, awaiting and parsing JSON responses, checking response.ok for failed requests, and sending a JSON body with custom headers.
1JS Fetch API | JavaScript Tutorial - In-Depth Guide Part 1
The Fetch API is the modern, Promise-based replacement for XMLHttpRequest, giving JavaScript a built-in way to talk to servers over HTTP directly from the browser.
// Fetch API: The Network ProtocolFetch API
2JS Fetch API | JavaScript Tutorial - In-Depth Guide Part 2
Calling fetch(url) alone kicks off a GET request to that endpoint and returns a Promise ā but that Promise resolves as soon as the response headers arrive, not once the full response body is ready to use.
fetch('https://api.example.com/users');Making a Request
3JS Fetch API | JavaScript Tutorial - In-Depth Guide Part 3
Wrapping fetch in an async function and using await pauses execution until the response object actually arrives, making asynchronous network code read like simple, sequential steps instead of nested .then() chains.
async function getUsers() {
const response = await fetch('https://api.example.com/users');
}Awaiting the Response
4JS Fetch API | JavaScript Tutorial - In-Depth Guide Part 4
The response body arrives as a raw stream, so res.json() is a second asynchronous step that reads and parses that stream into a usable JavaScript object ā which is why it needs its own await separate from the initial fetch.
async function getUsers() {
const res = await fetch('https://api.example.com/users');
const data = await res.json();
console.log(data);
}Parsing JSON
5JS Fetch API | JavaScript Tutorial - In-Depth Guide Part 5
fetch only rejects its Promise on a network failure ā a 404 or 500 response still resolves successfully as a valid HTTP response. You must explicitly check response.ok and throw your own error to catch bad HTTP statuses.
async function getData() {
const res = await fetch('/api');
if (!res.ok) throw new Error('Bad status');
return await res.json();
}Checking Status
6JS Fetch API | JavaScript Tutorial - In-Depth Guide Part 6
Sending data requires a second argument to fetch: method set to 'POST', a Content-Type header describing the payload format, and a body created with JSON.stringify() to serialize a JS object into a transmittable string.
const options = {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ name: 'Alice' })
};
fetch('/users', options);Sending Data (POST)
7JS Fetch API | JavaScript Tutorial - In-Depth Guide Part 7
With requests, responses, status checks, and POST payloads all covered, the next lesson dives into JSON itself ā how it's structured, serialized, and parsed.
<h1>API Master Unlocked!</h1>Fetch Master
8Step-by-Step Breakdown
The Fetch API is the modern, Promise-based way for JavaScript to talk to servers over HTTP directly from the browser, replacing the older XMLHttpRequest.
Calling fetch(url) alone kicks off a GET request to that endpoint and returns a Promise ā but that Promise resolves as soon as the response headers arrive, not once the full body is ready.
Wrapping fetch in an async function and using await pauses execution until the response object arrives, making asynchronous network code read like simple, sequential steps.
The response body arrives as a raw stream, so res.json() is a second async step that reads and parses that stream into a usable JavaScript object ā which is why it needs its own await.
Checkpoint: What HTTP method does fetch() use by default?
- āPOST
- āGET
fetch only rejects its Promise on a network failure ā a 404 or 500 response still resolves successfully, so you must explicitly check response.ok and throw your own error to catch bad HTTP statuses.
Sending data requires a second argument to fetch: a method set to POST, a Content-Type header describing the payload format, and a body created with JSON.stringify() to serialize a JS object into a string.
Checkpoint: How do we check if the server returned a successful status (like 200)?
- āresponse.ok
- āresponse.success
With requests, responses, status checks, and POST payloads all covered, you're ready to dive into JSON itself ā how it's structured and parsed.
Level Up š
Advanced cheat sheets, SEO tricks, and interview prep for this topic.
Browser Support
Fully supported.
Fully supported.
Fully supported.
Fully supported.
Accessibility (A11y)
1Announce Loading and Error States from Fetch Requests to Screen Reader Users
A spinner shown while a fetch request is in flight is purely visual by default. Wrap the loading and error messages in an `aria-live="polite"` region so screen reader users are told when a request starts, succeeds, or fails, instead of only sighted users noticing the UI change.
SEO Implications
- 1
Content Loaded Client-Side via fetch() May Not Be Indexed
If a page's main content is fetched from an API after the initial HTML loads, crawlers that don't fully execute JavaScript (or that time out before the request resolves) may index an empty page. For content that matters for SEO, prefer server-side rendering or static generation over client-only fetch calls.
Best Practices
Always Check response.ok Before Parsing the Body
fetch() only rejects on network failure, not on HTTP error statuses like 404 or 500 ā it resolves successfully either way. Check `if (!response.ok) throw new Error(...)` before calling `.json()`, otherwise failed requests silently return whatever error page or empty body the server sent.
Set the Content-Type Header Explicitly When Sending JSON
If you send a JSON body without a `'Content-Type': 'application/json'` header, many servers won't know how to parse the request body correctly and may treat it as plain text or reject it outright.
Frequent Bugs
`SyntaxError: Unexpected token < in JSON at position 0` when calling `res.json()`.
This means the server responded with an HTML page (often a 404 or 500 error page) instead of JSON, and `.json()` failed trying to parse HTML tags as JSON. Check `response.ok` and the response status before assuming the body is valid JSON.
Real-World Examples
Fetching and Displaying User Data with Error Handling
A dashboard needed to load a user's profile from an API, show a loading state while waiting, and display a friendly error message if the request failed or the server returned a non-2xx status.
async function loadProfile(userId) {
try {
const res = await fetch(`/api/users/${userId}`);
if (!res.ok) throw new Error(`Request failed: ${res.status}`);
return await res.json();
} catch (err) {
console.error('Failed to load profile:', err);
throw err;
}
}