Fetch API

Reviewed & published by Brayan K

A deep dive into making HTTP requests, API architecture, JSON handling, security, CORS, streaming, authentication, pagination, rate limits, real-world examples, and more.

Part of the free JavaScript course at LearnCodingFast โ€” hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.

What You'll Learn in This Lesson

๐Ÿ’ก Running Code Locally: While this online editor runs real JavaScript, some advanced examples may have limitations. For the best experience:

๐Ÿ“ก Real-World Analogy: The Fetch API is like ordering from a drive-thru:

๐ŸŒ Fetch API โ€” The Backbone of Modern Web Applications

The Fetch API is the heart of modern JavaScript development. Every interactive, data-driven website uses fetch() behind the scenes:

HTTP MethodPurposeReal Example
GETRetrieve dataLoading user profile
POSTSend new dataCreating a new post
PUT/PATCHUpdate dataEditing your bio
DELETERemove dataDeleting a comment

Fetch is the engine connecting the browser (your JavaScript) to servers, databases, APIs, clouds, and backend systems around the world.

If you understand fetch deeply, you can build:

๐Ÿš€ What Exactly Is the Fetch API?

The Fetch API is a modern browser interface for making HTTP requests: GET, POST, PUT, DELETE, PATCH โ€” everything.

Before fetch(), developers used XMLHttpRequest (XHR). Fetch replaces ALL of it with a cleaner, Promise-based approach.

Old (XHR)

const req = new XMLHttpRequest();
req.open("GET", "/api");
req.onload = function() {
    console.log(req.responseText);
};
req.send();

Modern (Fetch)

const res = await fetch("/api");
const data = await res.json();

Cleaner. Faster. Easier. More powerful.

๐Ÿ“ฌ Basic GET Request โ€” The Foundation

const response = await fetch("https://api.example.com/data");
const data = await response.json();
console.log(data);

But behind those 2 lines is a HUGE world:

We will cover ALL of this in this mega lesson.

๐Ÿง  Understanding the Fetch Response Object

response.ok          // true/false if status is 200โ€“299
response.status      // e.g., 200, 404, 500
response.statusText  // human readable text
response.headers     // all server headers
response.url         // final resolved URL
response.redirected  // boolean
response.type        // basic, cors, error, opaque
response.body        // ReadableStream
response.json()      // parse JSON
response.text()      // raw text
response.blob()      // files, images
response.arrayBuffer() // binary
response.formData()

Fetch is far more than just .json().

๐Ÿงช Full Syntax of fetch()

fetch(url, {
    method: "GET",
    headers: { ... },
    body: "...",
    mode: "cors",
    cache: "no-cache",
    credentials: "include",
    redirect: "follow",
    referrerPolicy: "no-referrer"
});

We will break down each one deeply in this lesson.

๐Ÿ“ก Real Example โ€” Fetching JSONPlaceholder API

This free API is used in thousands of tutorials.

const res = await fetch("https://jsonplaceholder.typicode.com/posts/1");
const post = await res.json();
console.log(post);
{
  "userId": 1,
  "id": 1,
  "title": "...",
  "body": "..."
}

๐Ÿ”ฅ Using Async/Await With Fetch (The Best Way)

Async/await + fetch = modern JavaScript.

๐Ÿ›‘ Error Handling: Fetch Does NOT Throw on 400/500 Errors

This surprises most developers.

Fetch only throws on:

But it DOES NOT throw on:

๐Ÿงจ Handling Failed JSON Parsing

Server may return invalid JSON:

try {
    const data = await res.json();
} catch (err) {
    console.error("Bad JSON:", err);
}

This happens more often than beginners expect.

๐Ÿ“ฅ POST Requests โ€” Sending Data

Fetch makes POST simple:

const res = await fetch("/api/users", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({ name: "Brayan", age: 16 })
});

๐Ÿ“ Common Fetch Methods

GETRetrieve data
POSTCreate new data
PUT/PATCHUpdate existing data
DELETERemove data

๐Ÿ“ฆ Sending FormData (No Need to JSON.stringify)

const form = new FormData();
form.append("file", fileInput.files[0]);

fetch("/upload", {
    method: "POST",
    body: form
});

This is how Instagram/TikTok upload images.

๐ŸŒ CORS โ€” The Gatekeeper of APIs

CORS = Cross-Origin Resource Sharing One of the MOST misunderstood web concepts.

Browser blocks request โ†’ API says: "You're not allowed."

Access-Control-Allow-Origin: *

CORS Modes in fetch:

mode: "cors"        // default for most APIs
mode: "no-cors"     // restricted, only opaque responses
mode: "same-origin" // only internal requests

๐Ÿ” Authorization Headers (Tokens, API Keys, JWT)

fetch("/private", {
    headers: {
        "Authorization": "Bearer SECRET_TOKEN"
    }
});

๐Ÿ”„ PUT, PATCH, DELETE Requests

PUT (Overwrite)

fetch("/api/user/1", {
    method: "PUT",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({ name: "Boopie" })
});

PATCH (Partial Update)

fetch("/api/user/1", {
    method: "PATCH",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({ age: 17 })
});

DELETE

fetch("/api/user/1", {
    method: "DELETE"
});

โšก AbortController โ€” Cancel Fetch Requests

Imagine the user types fast into a search bar. You must cancel old requests:

const controller = new AbortController();

fetch("/search?q=hello", {
    signal: controller.signal
});

// Cancel
controller.abort();

๐Ÿ“Š Fetching Large Lists with Pagination

/posts?limit=10&page=2

Used in every real platform:

๐Ÿ“ก Parallel Fetching With Promise.all()

const [user, posts, comments] = await Promise.all([
    fetch("/user/1").then(r => r.json()),
    fetch("/posts").then(r => r.json()),
    fetch("/comments").then(r => r.json())
]);

This is how dashboards load instantly.

๐Ÿ”ฅ Real Example: Loading a Dashboard

async function loadDashboard() {
    const [
        stats,
        notifications,
        recent
    ] = await Promise.all([
        fetch("/dashboard/stats").then(r => r.json()),
        fetch("/dashboard/notifications").then(r => r.json()),
        fetch("/dashboard/recent").then(r => r.json())
    ]);

    return { stats, notifications, recent };
}

๐ŸŒ GET Request with Query Parameters

const url = new URL("https://api.example.com/search");
url.searchParams.set("q", "javascript");
url.searchParams.set("limit", 20);

const res = await fetch(url);

Easier and cleaner than string concatenation.

๐ŸŒ Understanding HTTP Status Codes

Fetch won't throw errors automatically, so YOU must check status codes manually.

๐ŸŸข Success Codes

๐Ÿ” Authentication Errors

๐Ÿ”ด Client Errors

๐Ÿ”ฅ Server Errors

Mastering status codes = mastering error handling.

๐ŸŽฏ Fetch with Retry Logic

Real APIs sometimes fail. So you need retry strategies.

async function retryFetch(url, attempts = 3) {
    for (let i = 0; i < attempts; i++) {
        try {
            const res = await fetch(url);
            if (!res.ok) throw new Error();
            return res.json();
        } catch (err) {
            if (i === attempts - 1) throw err;
            await new Promise(r => setTimeout(r, 500));
        }
    }
}

๐Ÿง  Real-World Example: Authenticate User & Get Profile

This is how dashboards like Facebook, YouTube Studio, Amazon Seller Central, and TikTok Business load your data securely.

๐Ÿ›ก๏ธ Security Best Practices

fetch(`https://api.example.com?key=SECRET`)

๐ŸŽฏ Practice Challenge

๐Ÿ Recap

The Fetch API is the foundation of modern web communication. Once you master it, you can build any data-driven application with confidence.

๐Ÿ“‹ Quick Reference โ€” Fetch API

ActionCode Snippet
Basic GETconst res = await fetch(url);
Get JSONconst data = await res.json();
Check Successif (!res.ok) throw new Error();
POST JSONfetch(url, { method: 'POST', body: ... })
Headersheaders: { 'Content-Type': 'application/json' }

Lesson Complete โ€” Fetch API!

You can now connect your JavaScript code to the outside world โ€” fetching data, sending forms, and building real dynamic applications.

Practice quiz

Which HTTP method does the lesson use to retrieve data?

  • POST
  • DELETE
  • GET
  • PUT

Answer: GET. GET retrieves data, like loading a user profile; POST sends new data.

How do you parse a JSON response from fetch?

  • response.json()
  • response.parse()
  • JSON.fetch(response)
  • response.toJSON()

Answer: response.json(). await response.json() reads the body and parses it as JSON.

Does fetch reject (throw) on a 404 or 500 HTTP status?

  • Yes, it throws on any error status
  • Only on 500, not 404
  • Only when using async/await
  • No โ€” you must check response.ok or response.status yourself

Answer: No โ€” you must check response.ok or response.status yourself. Fetch only rejects on network failures; for 4xx/5xx you must check response.ok manually.

What does response.ok tell you?

  • The body is valid JSON
  • The status is in the 200-299 range
  • The request used HTTPS
  • The server supports CORS

Answer: The status is in the 200-299 range. response.ok is true when the status code is 200-299.

When sending JSON in a POST, which header should you set?

  • Content-Type: application/json
  • Accept: text/html
  • Authorization: Bearer
  • X-Requested-With

Answer: Content-Type: application/json. Set Content-Type to application/json and send JSON.stringify(data) as the body.

What does CORS stand for?

  • Client Origin Request Security
  • Cached Object Response System
  • Cross-Origin Resource Sharing
  • Cross-Object Reference Standard

Answer: Cross-Origin Resource Sharing. CORS = Cross-Origin Resource Sharing; the server grants access via Access-Control-Allow-Origin.

What is AbortController used for with fetch?

  • Parsing JSON faster
  • Cancelling in-flight requests via a signal
  • Retrying failed requests
  • Adding auth headers

Answer: Cancelling in-flight requests via a signal. You pass controller.signal to fetch and call controller.abort() to cancel, e.g. for live search.

How do you run several fetches in parallel and wait for all of them?

  • A for loop with await each
  • fetch.all(...)
  • Promise.race([...])
  • Promise.all([...])

Answer: Promise.all([...]). Promise.all waits for all the requests, which overlap so total time is roughly the slowest one.

Which status code commonly signals API rate-limiting?

  • 204 No Content
  • 429 Too Many Requests
  • 301 Moved Permanently
  • 418 I'm a teapot

Answer: 429 Too Many Requests. 429 Too Many Requests indicates you have hit a rate limit.

Which is a security best practice the lesson stresses?

  • Put secret API keys in the frontend URL
  • Disable CORS entirely
  • Never expose API keys in frontend code
  • Always use no-cors mode

Answer: Never expose API keys in frontend code. Never expose secret keys client-side; route private API calls through your own backend.

Continue this course