Skip to content

Fetch API

This lesson explains Fetch API with clear examples, use cases, and best practices so you can use HTML5 APIs confidently in real web applications.

HTML5 Fetch API Overview

The Fetch API is the modern JavaScript interface for making HTTP requests from the browser. It replaces the older XMLHttpRequest (XHR) API with a cleaner, Promise-based interface that works naturally with async/await.

Developers use the Fetch API to retrieve data from REST APIs, submit forms, upload files, download resources, authenticate users, communicate with servers, and build modern Single Page Applications (SPAs).

Feature Description
API Name Fetch API
Main Function fetch()
Programming Style Promise-based
Supports GET, POST, PUT, PATCH, DELETE and more
Response Formats JSON, Text, Blob, ArrayBuffer, FormData
Common Uses REST APIs, authentication, uploads, downloads, data fetching

Basic Fetch Syntax

// Basic Fetch request

fetch("/api/users")
  .then((response) => response.json())
  .then((users) => {
    console.log(users);
  })
  .catch((error) => {
    console.error(error);
  });

The fetch() function returns a Promise that resolves to a Response object. The response body can then be converted into JSON, text, Blob, or other formats.

Fetch Request Lifecycle

Step Description
1. Send Request Browser sends an HTTP request using fetch().
2. Receive Response Server returns an HTTP response.
3. Check Status Verify response.ok or response.status.
4. Read Body Convert response using json(), text(), or blob().
5. Handle Errors Catch network or application errors.

GET Request Example

// GET request using async/await

async function loadUsers() {
  try {
    const response =
      await fetch("/api/users");

    if (!response.ok) {
      throw new Error("Unable to load users.");
    }

    const users =
      await response.json();

    console.log(users);
  } catch (error) {
    console.error(error.message);
  }
}

loadUsers();

GET requests retrieve data from a server and are the most common Fetch API operation.

POST Request Example

// POST request

async function createUser() {
  const response =
    await fetch("/api/users", {
      method: "POST",
      headers: {
        "Content-Type": "application/json"
      },
      body: JSON.stringify(
        {
          name: "John",
          email: "john@example.com"
        }
      )
    });

  const result =
    await response.json();

  console.log(result);
}

createUser();

POST requests send data to the server, usually for creating new resources.

PUT Request Example

// Update existing resource

fetch("/api/users/5", {
  method: "PUT",
  headers: {
    "Content-Type": "application/json"
  },
  body: JSON.stringify(
    {
      name: "David"
    }
  )
})
.then((response) => response.json())
.then((data) => {
  console.log(data);
});

DELETE Request Example

// Delete resource

fetch("/api/users/5", {
  method: "DELETE"
})
.then((response) => {
  console.log(response.status);
});

Common Fetch Options

Option Description Example
method HTTP method. GET, POST, PUT, DELETE
headers Request headers. Content-Type, Authorization
body Request payload. JSON.stringify(data)
mode CORS mode. cors, no-cors, same-origin
credentials Cookie handling. include, omit
cache Cache behavior. default, reload, no-store
signal Abort request. AbortController

Response Methods

Method Returns Common Use
json() JavaScript object REST APIs
text() String Plain text files
blob() Blob object Images, PDFs
arrayBuffer() Binary data Media processing
formData() FormData object Forms and uploads

Upload File Example

// Upload file

const formData =
  new FormData();

formData.append(
  "photo",
  fileInput.files[0]
);

fetch("/upload", {
  method: "POST",
  body: formData
})
.then((response) => response.json())
.then((data) => {
  console.log(data);
});

When sending FormData, do not manually set the Content-Type header because the browser automatically adds the correct multipart boundary.

Download File Example

// Download PDF

async function downloadFile() {
  const response =
    await fetch("/reports/monthly.pdf");

  const blob =
    await response.blob();

  const url =
    URL.createObjectURL(blob);

  const link =
    document.createElement("a");

  link.href = url;
  link.download = "report.pdf";
  link.click();

  URL.revokeObjectURL(url);
}

Cancel Request Example

// Abort Fetch request

const controller =
  new AbortController();

fetch("/api/users", {
  signal: controller.signal
});

setTimeout(() => {
  controller.abort();
}, 3000);

AbortController lets you cancel slow or unnecessary requests, improving performance and responsiveness.

Error Handling

try {
  const response =
    await fetch("/api/users");

  if (!response.ok) {
    throw new Error(
      "HTTP Error: " +
      response.status
    );
  }

  const users =
    await response.json();

  console.log(users);
} catch (error) {
  console.error(error.message);
}

Always check response.ok because Fetch only rejects Promises for network failures, not HTTP errors such as 404 or 500.

Common HTTP Status Codes

Status Meaning
200 Success
201 Created
204 No Content
400 Bad Request
401 Unauthorized
403 Forbidden
404 Not Found
500 Internal Server Error

Common Fetch API Use Cases

  • REST API communication
  • Loading dashboard data
  • User authentication
  • Submitting forms
  • Uploading files
  • Downloading documents
  • Lazy loading content
  • Progressive Web Apps

Fetch API Best Practices

  • Always check response.ok.
  • Wrap asynchronous code in try...catch.
  • Use async/await for readable code.
  • Abort unnecessary requests.
  • Handle loading and error states in the UI.
  • Use HTTPS for production APIs.
  • Validate server responses before rendering.
  • Reuse helper functions for API requests.

Common Fetch API Mistakes

  • Assuming Fetch throws errors for HTTP 404 or 500 responses.
  • Forgetting to await response.json().
  • Ignoring network failures.
  • Not cancelling long-running requests.
  • Sending JSON without the correct Content-Type.
  • Setting multipart headers manually when using FormData.
  • Ignoring CORS restrictions.
  • Not handling authentication failures.

Fetch API vs XMLHttpRequest

Feature Fetch API XMLHttpRequest
Programming Style Promise-based Callback/Event-based
async/await Native support Not supported
Readable Code Excellent Verbose
Abort Support AbortController abort()
Recommended Today ✔ Yes Legacy only

Key Takeaways

  • The Fetch API is the modern way to perform HTTP requests.
  • It is Promise-based and works naturally with async/await.
  • Support for GET, POST, PUT, PATCH, DELETE and other HTTP methods.
  • Always check response.ok before reading response data.
  • Supports uploads, downloads, authentication, and streaming responses.
  • Use Fetch instead of XMLHttpRequest for new applications.

Pro Tip

Create a reusable API helper that automatically handles headers, JSON parsing, authentication tokens, error handling, retries, and timeouts. This keeps your application code clean and consistent.