# How to Fetch and Parse JSON Data from a Local File Using the Fetch API

> Learn to fetch and parse JSON from a local file using the Fetch API.  Easily deserialize the JSON data and use it in your JavaScript applications.

- Repository: [Jisan Mia/dom-projects](https://github.com/jisan-mia/dom-projects)
- Tags: tutorial
- Published: 2026-03-04

---

**Use the browser's native `fetch()` method with a relative file path, chain `.then(response => response.json())` to deserialize the body, and consume the resulting JavaScript object in the next promise resolution.**

The `jisan-mia/dom-projects` repository demonstrates a robust, production-ready pattern to fetch and parse JSON data from a local file using the fetch API. In the site's entry-point script, the application loads a static [`data.json`](https://github.com/jisan-mia/dom-projects/blob/main/data.json) file to hydrate the project list UI without requiring a backend server or external network requests.

## The Core Implementation in [`index.js`](https://github.com/jisan-mia/dom-projects/blob/main/index.js)

The canonical implementation lives in **[`index.js`](https://github.com/jisan-mia/dom-projects/blob/main/index.js)** (lines 23–31). The `fetchProjects` function requests the local JSON asset, parses the response, and delegates rendering to `renderProjectList`.

```javascript
// index.js
function fetchProjects() {
  fetch("./data.json")               // ① request the local file
    .then((res) => res.json())       // ② parse JSON into a JS object
    .then((projects) => {
      renderProjectList(projects);   // ③ render the UI
    })
    .catch((err) => console.log(err));
}

```

**Key details from the source:**
- **Relative URL**: `"./data.json"` resolves to the same origin, avoiding CORS restrictions.
- **Promise chain**: `fetch` returns a `Response` object; calling `.json()` returns a second promise that resolves to the parsed data.
- **Error boundary**: The `.catch()` block prevents runtime crashes if the file is missing or malformed.

## Step-by-Step Breakdown

### 1. Initiating the Request

The `fetch` function accepts a resource identifier. For local files served by the same web server, use a relative path.

```javascript
fetch("./data.json")

```

According to the `dom-projects` source code, this pattern is used to load the static dataset that populates the homepage grid.

### 2. Parsing the Response Body

The `Response` object provides several body-reading methods. For JSON data, use **`response.json()`**, which reads the stream to completion and parses the text as JSON.

```javascript
.then(response => response.json())

```

This method returns a promise that resolves to the actual JavaScript object or array defined in [`data.json`](https://github.com/jisan-mia/dom-projects/blob/main/data.json).

### 3. Consuming the Data

Once parsed, the data can be passed to rendering functions or state management logic.

```javascript
.then(projects => {
  // projects is the array from data.json
  renderProjectList(projects);
})

```

In the repository, `renderProjectList` iterates over the array to generate DOM nodes for each project card.

## Complete Working Example

Below is a minimal, runnable HTML page that demonstrates the pattern isolated from the larger codebase.

```html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Local JSON Fetch Demo</title>
</head>
<body>
  <h1>Projects</h1>
  <ul id="project-list"></ul>

  <script>
    // Fetch and parse JSON data from a local file using fetch API
    fetch("./data.json")
      .then(response => {
        if (!response.ok) {
          throw new Error(`HTTP error: ${response.status}`);
        }
        return response.json();
      })
      .then(data => {
        const list = document.getElementById("project-list");
        data.forEach(project => {
          const li = document.createElement("li");
          li.textContent = `${project.name}: ${project.description}`;
          list.appendChild(li);
        });
      })
      .catch(error => console.error("Fetch failed:", error));
  </script>
</body>
</html>

```

Place a [`data.json`](https://github.com/jisan-mia/dom-projects/blob/main/data.json) file in the same directory containing a valid JSON array to see the rendered output.

## Reusable Helper Function

For larger applications like `dom-projects`, abstract the fetch-and-parse logic into a utility function to avoid repetition.

```javascript
/**
 * Loads a local JSON file and returns the parsed data.
 * @param {string} path - Relative path to the JSON file.
 * @returns {Promise<any>} The parsed JSON content.
 */
function loadLocalJson(path) {
  return fetch(path)
    .then(response => {
      if (!response.ok) {
        throw new Error(`Failed to load ${path}: ${response.status} ${response.statusText}`);
      }
      return response.json();
    });
}

// Usage in the project context
loadLocalJson("./data.json")
  .then(projects => renderProjectList(projects))
  .catch(err => console.error("Project data unavailable:", err));

```

This pattern is consistent with the implementation found in [`index.js`](https://github.com/jisan-mia/dom-projects/blob/main/index.js), where the fetch logic is encapsulated within `fetchProjects` but could be further generalized for multiple data sources.

## Summary

- **Initiate the request** with `fetch("./data.json")` using a relative path to avoid CORS issues.
- **Parse the response** by calling `.json()` on the `Response` object to deserialize the JSON into a JavaScript object.
- **Handle errors** with a `.catch()` block to manage missing files or network failures gracefully.
- **Reference implementation**: The `jisan-mia/dom-projects` repository demonstrates this pattern in [`index.js`](https://github.com/jisan-mia/dom-projects/blob/main/index.js) (lines 23–31) to populate the project list from [`data.json`](https://github.com/jisan-mia/dom-projects/blob/main/data.json).

## Frequently Asked Questions

### Can the Fetch API load local JSON files without a web server?

No. The Fetch API requires the resource to be served over HTTP/HTTPS. Opening an HTML file directly from the filesystem (`file://` protocol) will cause CORS errors or silent failures in most modern browsers. You must serve the files via a local development server (e.g., `npx serve`, Live Server, or Python's `http.server`).

### What is the difference between `response.text()` and `response.json()`?

`response.text()` reads the body stream and returns a promise that resolves to a raw string, which is useful for CSV or plain text files. `response.json()` is a convenience method that first reads the stream as text, then automatically calls `JSON.parse()` to convert the string into a JavaScript object or array. Use `response.json()` exclusively when consuming JSON data.

### How do I handle CORS errors when fetching local JSON?

CORS errors occur when the JavaScript origin does not match the resource origin. For local files in the same project, ensure you use a **relative path** (e.g., `"./data.json"` or `"data.json"`) rather than an absolute URL. Serve both the HTML and JSON from the same web server and port. If you control the server, ensure it sends the `Access-Control-Allow-Origin` header for cross-origin requests.

### Why does my fetch request return `undefined` instead of JSON data?

This typically happens when you forget to return the promise from the `.json()` method or when you attempt to access the data outside the promise chain. Ensure you chain `.then(response => response.json())` and place your logic that consumes the data inside the subsequent `.then()` block. The Fetch API is asynchronous; the data is not available immediately after the `fetch()` call.