Skip to main content

How to Fetch and Display JSON Data in HTML using JavaScript

A cornerstone of modern web development is fetching data from an API and rendering it on a webpage. This process typically involves making an HTTP request to get JSON data, parsing that data, and then dynamically creating HTML elements to display it.

This guide will teach you the standard, modern methods for this task. You will learn how to use the fetch API to retrieve data and then how to safely render it into the DOM. We will cover the recommended approach of creating DOM elements programmatically and the simpler, but less secure, innerHTML method.

The Core Task: Fetch and Render

The overall process can be broken down into two main steps:

  1. Fetch: Use the fetch() API to make a network request to an endpoint that returns JSON data.
  2. Render: Take the parsed JSON data (which will be a JavaScript object or array) and create HTML elements to display it in the document.

HTML for Examples:

<div id="data-container"></div>

Step 1: Fetching the JSON Data

The fetch() API is the modern, standard way to make HTTP requests. It is promise-based, making it perfect for async/await syntax.

The solution is to use an async function that fetches an array of user data from a sample API.

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

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

// The .json() method parses the response body as JSON.
const data = await response.json();
return data;

} catch (error) {
console.error('Error fetching data:', error);
return []; // Return an empty array on error
}
}

This is the safest and most robust method for rendering dynamic data. You create each HTML element programmatically and set its content using the .textContent property.

The logic:

  1. Get a reference to the container element where you want to display the data.
  2. Loop through your array of data.
  3. Inside the loop, for each item, create the necessary DOM elements (e.g., <li>, <p>).
  4. Set their content using .textContent to prevent security risks.
  5. Append the new elements to the container.

Solution:

const container = document.getElementById('data-container');

fetchData().then(users => {
if (users.length === 0) {
container.textContent = 'No users found.';
return;
}

const userList = document.createElement('ul');

users.forEach(user => {
const listItem = document.createElement('li');
listItem.textContent = `${user.name} (@${user.username})`;
userList.appendChild(listItem);
});

container.appendChild(userList);
});

An Alternative Rendering Method: Using innerHTML

For simple cases, you can build up a large HTML string and then set the .innerHTML property of the container. This is often faster to write but comes with a critical security warning.

warning

Security Warning: Never use innerHTML to render content that comes from a user or an untrusted source. Doing so can expose your site to Cross-Site Scripting (XSS) attacks, where a malicious user could inject a <script> tag into your page.

Solution:

const container = document.getElementById('data-container');

fetchData().then(users => {
if (users.length === 0) {
container.innerHTML = '<p>No users found.</p>';
return;
}

// Use map() and join() to build the HTML string
const userListHtml = `
<ul>
${users.map(user => `<li>${user.name} (@${user.username})</li>`).join('')}
</ul>
`;

container.innerHTML = userListHtml;
});

While this is more concise, it is less safe and less performant than creating DOM elements directly, as it requires the browser to re-parse the entire HTML string.

Practical Example: Displaying Data in a Table

This example combines the best practices to fetch user data and render it into an HTML table.

HTML:

<table id="users-table">
<thead>
<tr>
<th>Name</th>
<th>Email</th>
<th>City</th>
</tr>
</thead>
<tbody id="table-body"></tbody>
</table>

JavaScript:

const tableBody = document.getElementById('table-body');

fetchData().then(users => {
users.forEach(user => {
// Create a new table row
const row = document.createElement('tr');

// Create and append the cells for the row
const nameCell = document.createElement('td');
nameCell.textContent = user.name;
row.appendChild(nameCell);

const emailCell = document.createElement('td');
emailCell.textContent = user.email;
row.appendChild(emailCell);

const cityCell = document.createElement('td');
cityCell.textContent = user.address.city;
row.appendChild(cityCell);

// Append the row to the table body
tableBody.appendChild(row);
});
});

// (Include the fetchData function from Section above)

Conclusion

Fetching and displaying JSON data is a fundamental workflow in web development.

  • Always use the fetch() API (with async/await for readability) to retrieve your data.
  • The recommended best practice for rendering is to create DOM elements programmatically (e.g., document.createElement) and set their content with .textContent for security.
  • Using .innerHTML is a faster way to write the code but is less performant and carries significant security risks if the data is not from a trusted source.