Fetch JSON in JavaScript
The fetch() API is the modern way to make HTTP requests in JavaScript. It returns a Promise, works in all modern browsers and Node.js 18+, and makes consuming JSON APIs straightforward with the .json() response method.
Basic GET request
The minimal pattern to fetch JSON from an API endpoint:
fetch('https://api.example.com/users')
.then(response => response.json())
.then(data => {
console.log(data)
})response.json() reads the response body and parses it as JSON. It also returns a Promise, so you need a second .then().
Using async/await (recommended)
The async/await pattern is cleaner and easier to read:
async function getUsers() {
const response = await fetch('https://api.example.com/users')
const data = await response.json()
return data
}
const users = await getUsers()
console.log(users)Error handling
fetch() only rejects for network failures. A 404 or 500 response does not throw — you must check response.ok:
async function fetchJson(url) {
const response = await fetch(url)
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${response.statusText}`)
}
return response.json()
}
// Usage
try {
const data = await fetchJson('https://api.example.com/users/1')
console.log(data)
} catch (error) {
console.error('Failed:', error.message)
}POST JSON data
To send JSON in a POST request, set the Content-Type header and stringify the body:
async function createUser(user) {
const response = await fetch('https://api.example.com/users', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(user),
})
if (!response.ok) {
throw new Error(`HTTP ${response.status}`)
}
return response.json()
}
const newUser = await createUser({ name: 'Alice', email: 'alice@example.com' })Request headers
Pass custom headers in the options object. Common headers for JSON APIs:
const response = await fetch('https://api.example.com/data', {
headers: {
'Accept': 'application/json',
'Authorization': 'Bearer your-token-here',
'Content-Type': 'application/json',
}
})Query parameters
Use URLSearchParams to build query strings safely:
const params = new URLSearchParams({
q: 'javascript',
page: '1',
limit: '20',
})
const response = await fetch(`https://api.example.com/search?${params}`)
const data = await response.json()
// URL becomes: https://api.example.com/search?q=javascript&page=1&limit=20Timeouts
fetch() has no built-in timeout. Use AbortController:
async function fetchWithTimeout(url, timeoutMs = 5000) {
const controller = new AbortController()
const timer = setTimeout(() => controller.abort(), timeoutMs)
try {
const response = await fetch(url, { signal: controller.signal })
clearTimeout(timer)
return response.json()
} catch (error) {
if (error.name === 'AbortError') throw new Error('Request timed out')
throw error
}
}Node.js
fetch() is available natively in Node.js 18+. In earlier versions, use the node-fetch package:
// Node.js 18+ — no import needed
const response = await fetch('https://api.example.com/data')
const data = await response.json()
// Node.js < 18 — install: npm install node-fetch
import fetch from 'node-fetch'
const response = await fetch('https://api.example.com/data')
const data = await response.json()Common mistakes
- Not awaiting
response.json(): It returns a Promise. You mustawaitit or chain.then(). - Assuming non-2xx means rejection:
fetch()resolves for any completed response, including 404 and 500. Checkresponse.ok. - Forgetting
Content-Typeon POST: WithoutContent-Type: application/json, many servers reject the body. - Reading the body twice: The response body can only be read once. Calling
.json()after.text()throws an error.
Validate fetched JSON
If you are unsure whether an API response matches the expected structure, paste it into the JSON Formatter to validate and explore it. For schema validation, use the JSON Schema Validator.