fetch()

fetch(input[, init])
Returns: Promise<Response> · Updated March 15, 2026 · Async APIs
fetch http request async api

The fetch() function is the modern, Promise-based way to make HTTP requests in JavaScript. It replaces the older XMLHttpRequest API with a cleaner, more powerful interface built on top of Promises.

Unlike XMLHttpRequest, fetch() automatically rejects the Promise on network failure, making error handling more intuitive. However, it does not reject on HTTP error statuses (4xx, 5xx)—you must check response.ok manually.

Syntax

fetch(url)
fetch(url, options)

Parameters

ParameterTypeDefaultDescription
urlstring or RequestThe resource to fetch (URL string or Request object)
initRequestInitundefinedOptional configuration object containing method, headers, body, etc.

RequestInit Options

OptionTypeDescription
methodstringHTTP method (GET, POST, PUT, DELETE, etc.). Default: GET
headersHeaders or objectRequest headers
bodystring or FormData or Blob or URLSearchParamsRequest body (cannot be used with GET or HEAD)
modestringCORS mode: “cors”, “no-cors”, or “same-origin”
credentialsstringInclude cookies: “omit”, “same-origin”, or “include”
cachestringCache mode: “default”, “no-store”, “reload”, “no-cache”, “force-cache”, “only-if-cached”
redirectstringFollow, error, or manual redirect behavior
signalAbortSignalAbortController signal to cancel the request
referrerstringSet the request’s Referer header
referrerPolicystringReferrer policy

Examples

Basic GET request

async function fetchUser() {
  const response = await fetch('https://jsonplaceholder.typicode.com/users/1');
  const data = await response.json();
  console.log(data);
  // { id: 1, name: "Leanne Graham", email: "Sincere@april.biz", ... }
}

fetchUser();

POST request with JSON body

async function createPost() {
  const response = await fetch('https://jsonplaceholder.typicode.com/posts', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      title: 'My New Post',
      body: 'This is the post content.',
      userId: 1
    })
  });
  
  const data = await response.json();
  console.log('Created:', data);
  // Created: { title: "My New Post", body: "This is the post content.", userId: 1, id: 101 }
}

createPost();

Handling errors and checking response.ok

async function safeFetch(url) {
  try {
    const response = await fetch(url);
    
    if (!response.ok) {
      throw new Error(`HTTP error! status: ${response.status}`);
    }
    
    return await response.json();
  } catch (error) {
    console.error('Fetch failed:', error.message);
    throw error;
  }
}

safeFetch('https://jsonplaceholder.typicode.com/posts/1');
// { userId: 1, id: 1, title: "...", body: "..." }

safeFetch('https://jsonplaceholder.typicode.com/nonexistent');
// Fetch failed: HTTP error! status: 404

Canceling a request with AbortController

async function fetchWithTimeout(url, timeoutMs = 5000) {
  const controller = new AbortController();
  const timeoutId = setTimeout(() => controller.abort(), timeoutMs);
  
  try {
    const response = await fetch(url, { signal: controller.signal });
    return await response.json();
  } finally {
    clearTimeout(timeoutId);
  }
}

fetchWithTimeout('https://jsonplaceholder.typicode.com/users/1', 1000)
  .then(data => console.log(data))
  .catch(err => console.error(err.name === 'AbortError' ? 'Request timed out' : err));

Sending cookies with credentials

async function fetchWithCookies(url) {
  const response = await fetch(url, {
    credentials: 'include',
    headers: {
      'Accept': 'application/json'
    }
  });
  return response.json();
}

Common Patterns

JSON helper function:

async function fetchJSON(url, options = {}) {
  const response = await fetch(url, {
    ...options,
    headers: {
      'Content-Type': 'application/json',
      ...options.headers
    }
  });
  
  if (!response.ok) {
    throw new Error(`HTTP ${response.status}: ${response.statusText}`);
  }
  
  return response.json();
}

const user = await fetchJSON('https://api.example.com/user/1');

Retry with exponential backoff:

async function fetchWithRetry(url, options = {}, retries = 3, delay = 1000) {
  for (let i = 0; i < retries; i++) {
    try {
      const response = await fetch(url, options);
      if (!response.ok && i < retries - 1) {
        await new Promise(r => setTimeout(r, delay * Math.pow(2, i)));
        continue;
      }
      return response;
    } catch (err) {
      if (i === retries - 1) throw err;
      await new Promise(r => setTimeout(r, delay * Math.pow(2, i)));
    }
  }
}

Parallel requests with Promise.all:

async function fetchMultiple(urls) {
  const requests = urls.map(url => fetch(url).then(r => r.json()));
  return Promise.all(requests);
}

const [users, posts] = await fetchMultiple([
  'https://jsonplaceholder.typicode.com/users',
  'https://jsonplaceholder.typicode.com/posts'
]);

See Also