Using fetch in JavaScript to Get Data from an API

Learn how to use the Fetch API in JavaScript to get and send data from APIs with async/await, error handling, and practical code examples.

Published on 16 May 2026
Reading Time 4
Number of Words 824

Using fetch in JavaScript to Get Data from an API

fetch is a modern Web API for making HTTP requests from the browser. It returns promises and provides a flexible way to request remote resources such as data from web APIs.

Basic Fetch Pattern

Here’s how to fetch data from a JSON API and work with the response:

fetch('https://api.example.com/data')
  .then(response => {
    if (!response.ok) {
      throw new Error(`HTTP error! status: ${response.status}`);
    }
    return response.json();  // parse JSON body
  })
  .then(data => {
    console.log('Received data:', data);
    // do something with the data
  })
  .catch(error => {
    console.error('Fetch error:', error);
  });

  • response.ok checks that the HTTP status code is in the 200–299 range.
  • response.json() parses the response body as JSON.
  • Always include error handling to catch network issues or invalid responses.

Using async/await

For more readable code, especially when dealing with multiple asynchronous operations, use async/await:

async function fetchUser(userId) {
  try {
    const response = await fetch(`https://api.example.com/users/${userId}`);
    if (!response.ok) {
      throw new Error(`Error fetching user: ${response.status}`);
    }
    const userData = await response.json();
    console.log('User data:', userData);
    return userData;
  } catch (err) {
    console.error('Fetch failed:', err);
    // Optionally return a fallback or rethrow
    return null;
  }
}

fetchUser(123).then(user => {
  if (user) {
    console.log('Name:', user.name);
  }
});

Fetch with Request Options

You can customize your request — add headers, send data, change method, etc.:

async function postData(url = '', data = {}) {
  const response = await fetch(url, {
    method: 'POST',                          // HTTP method
    headers: {
      'Content-Type': 'application/json'     // tell server we send JSON
    },
    body: JSON.stringify(data)               // convert JS object to JSON
  });

  if (!response.ok) {
    throw new Error(`Server error: ${response.status}`);
  }
  return response.json();                    // parse JSON response
}

postData('https://api.example.com/items', { title: 'New Item', completed: false })
  .then(result => {
    console.log('Result:', result);
  })
  .catch(error => {
    console.error('Error posting data:', error);
  });

Handling Different Response Types

Sometimes an API returns images, text, or binary data instead of JSON. You can handle those using different methods:

// For plain text
const textResponse = await fetch('https://api.example.com/readme.txt');
const text = await textResponse.text();
console.log(text);

// For blobs (e.g. images, files)
const imageResponse = await fetch('https://api.example.com/picture.jpg');
const blob = await imageResponse.blob();
// e.g. convert to image URL
const imgURL = URL.createObjectURL(blob);
document.querySelector('img').src = imgURL;

// For form data
const form = new FormData();
form.append('username', 'alice');
form.append('file', someFileObject);

const uploadResponse = await fetch('https://api.example.com/upload', {
  method: 'POST',
  body: form
});

Best Practices & Tips

  • Timeout and AbortController: fetch does not have built-in timeout. Use AbortController to cancel fetch after some time.
  • Check response codes: Always verify response.ok or response.status to handle errors properly (e.g. 404, 500).
  • Avoid memory leaks: Clean up DOM references if using fetch in components (e.g. React) to avoid setting state after unmounting.
  • Secure against CORS issues: The server must allow cross-origin requests via appropriate headers (Access-Control-Allow-Origin).
  • Use caching when possible: Browser’s HTTP caching or service workers can help reduce network load.
  • Don’t expose secrets: Never hard-code API keys in frontend code; consider using server-side proxy or environment variables.

Full Example: Fetching & Displaying Data in UI

Here’s a small example integrating fetch with DOM updates:

<!DOCTYPE html>
<html>
<head>
  <title>User List</title>
</head>
<body>
  <h1>Users</h1>
  <ul id="userList"></ul>
  <button id="refresh">Refresh</button>

  <script>
    const userListEl = document.getElementById('userList');
    const refreshBtn = document.getElementById('refresh');

    async function loadUsers() {
      userListEl.innerHTML = 'Loading...';
      try {
        const res = await fetch('https://api.example.com/users');
        if (!res.ok) throw new Error(`Status: ${res.status}`);
        const users = await res.json();
        userListEl.innerHTML = '';  // clear “Loading...”
        users.forEach(user => {
          const li = document.createElement('li');
          li.textContent = `${user.name} (${user.email})`;
          userListEl.appendChild(li);
        });
      } catch (err) {
        userListEl.innerHTML = `Error: ${err.message}`;
      }
    }

    refreshBtn.addEventListener('click', loadUsers);

    // Initial load
    loadUsers();
  </script>
</body>
</html>