Skip to main content

How to Resolve fetch() Returning an Empty Response Body in JavaScript

A common and frustrating issue when using the fetch API is receiving a Response object that appears to have an empty body. This can happen for several reasons, but it's almost always related to either Cross-Origin Resource Sharing (CORS) policies or incorrect handling of the Response object itself.

This guide will walk you through the most common causes of this problem, starting with the no-cors request mode and server-side CORS headers, and then covering the correct way to read the response body.

The Core Problem: Why is the Response Body Empty?

When you make a cross-origin fetch request, the browser enforces the Same-Origin Policy for security. This means that, by default, a script on https://my-website.com cannot access the response data from an API at https://api.example.com.

If you receive a Response object with an empty body and a type of "opaque", it is a clear sign that a CORS security policy is preventing you from reading the response.

Cause 1 (Most Common): The mode: 'no-cors' Setting

This is the most frequent cause of an "empty" response. Developers often add mode: 'no-cors' to their fetch request to bypass an initial CORS error, but this does not solve the problem. Instead, it tells the browser to make the request but to return an opaque response.

An opaque response is a black box. You cannot inspect its body, headers, or status code. It is designed to allow requests to be made without leaking any cross-origin information.

// Problem: This request will return an opaque response with an empty body.
async function fetchData() {
const response = await fetch('https://api.example.com/data', {
mode: 'no-cors', // This is the source of the issue
});

console.log(response.type); // Output: "opaque"

// This will fail because the body is unreadable.
const data = await response.json();
}

Solution: remove the mode: 'no-cors' option. This is almost never the correct solution for a standard API request.

// ✅ Correct: Let the browser use the default 'cors' mode.
async function fetchData() {
const response = await fetch('https://api.example.com/data');
// ...
}
warning

After removing this option, you may encounter a new CORS error, which must be fixed on the server.

Cause 2: Incorrect Server-Side CORS Headers

If you have removed mode: 'no-cors' and are now seeing a CORS error in the console (e.g., Access to fetch... has been blocked by CORS policy), the issue is on the server you are trying to contact.

The server must include the correct HTTP headers in its response to explicitly allow your website's origin to access its data. The most important header is Access-Control-Allow-Origin.

The Solution on the Server:

  • To fix this, you must configure the server to send the appropriate headers. For a public API, a common configuration is to allow any origin.

Example Server Response Header: Access-Control-Allow-Origin: *

If the API is private, the server should be configured to send back the specific origin of your web application. Access-Control-Allow-Origin: https://my-website.com

warning

Fixing this requires back-end changes. You cannot solve a server-side CORS issue from your front-end code alone.

Cause 3: Forgetting to Read the Body with .json() or .text()

The Response object you get back from fetch does not contain the body directly. The body is a stream that must be read asynchronously. If you try to access the data without calling one of the body-reading methods, you won't see it.

For example:

async function fetchData() {
const response = await fetch('https://api.example.com/data');

// ⛔️ Incorrect: `response` is not the data itself.
console.log(response); // This logs the Response object, not the JSON body.
}

Solution: you must call one of the methods like .json(), .text(), or .blob() and await its result.

async function fetchData() {
try {
const response = await fetch('https://api.example.com/data');

if (!response.ok) {
throw new Error(`HTTP error! Status: ${response.status}`);
}

// ✅ Correct: Await the .json() call to read and parse the body.
const data = await response.json();

console.log(data);
return data;
} catch (error) {
console.error('Error fetching data:', error);
}
}

Conclusion

An empty response body from a fetch request is almost always a CORS-related issue or a misunderstanding of how to read the response.

  1. First, remove mode: 'no-cors' from your fetch options. This is the most common mistake.
  2. If you then see a CORS error in your console, the server must be configured to send the correct Access-Control-Allow-Origin header.
  3. Finally, always make sure you are correctly reading the response body by awaiting a call to response.json() or response.text().