Making HTTP Requests in Node.js

Mateen Kiani

Mateen Kiani

Published on Sun Jun 22 2025·4 min read

making-http-requests-in-node.js

Node.js makes it surprisingly easy to reach out to APIs, fetch data, or connect microservices at scale. Yet many developers focus on one library and overlook how different methods impact performance, error handling, and streaming. How do you balance simplicity with control to get reliable, non-blocking HTTP requests in your app?

By understanding the built-in modules, popular libraries, and modern APIs, you can pick the right tool for each use case. Knowing when to stream data, retry on failures, or integrate with scheduling can save you headaches later. Let’s walk through the key approaches and best practices for making HTTP requests in Node.js.

Built-in http and https

Node.js ships with two core modules: http and https. They offer low-level control, letting you customize headers, timeouts, and request bodies without extra dependencies.

const http = require('http');
const options = {
hostname: 'api.example.com',
port: 80,
path: '/data',
method: 'GET',
headers: {
'Accept': 'application/json'
}
};
const req = http.request(options, res => {
let data = '';
res.on('data', chunk => data += chunk);
res.on('end', () => console.log('Response:', JSON.parse(data)));
});
req.on('error', err => console.error('Error:', err));
req.end();

Practical tips:

  • Use https for secure connections (port 443).
  • Stream large responses to avoid buffering everything in memory.
  • Set timeouts with req.setTimeout(...) for network resilience.

Using Axios library

Axios is a promise-based HTTP client with a clean API and built-in JSON handling. It works in Node and the browser, making code sharing easier.

To install Axios, you can use npm or follow this guide for installing Yarn and then: bash npm install axios

Basic usage: ```js const axios = require('axios');

axios.get('https://api.example.com/items') .then(response => console.log(response.data)) .catch(error => console.error('Request failed:', error)); ```

Why pick Axios?

  • Automatic JSON parsing and transforming.
  • Easy interceptors for logging or auth tokens.
  • Built-in support for request cancellation.

Tip: Use Axios interceptors to attach headers like API keys or handle global error logic in one place.

Leveraging Node Fetch

The Fetch API is familiar if you’ve used it in browsers. Node.js now supports it natively (from v18) or via the node-fetch package.

// Node 18+ native
import fetch from 'node:fetch';
(async () => {
try {
const res = await fetch('https://api.example.com');
if (!res.ok) throw new Error(res.statusText);
const data = await res.json();
console.log('Data:', data);
} catch (err) {
console.error('Fetch error:', err);
}
})();

Fetch benefits:

  • Familiar API across environments.
  • Streamable res.body for handling large files.
  • Works well with async/await.

Handling JSON and Streams

When you fetch or post large data, streaming helps you avoid loading everything into memory at once.

Example: piping a download to a file ```js import { createWriteStream } from 'node:fs'; import https from 'node:https';

https.get('https://example.com/large-file.zip', res => { const file = createWriteStream('./download.zip'); res.pipe(file); file.on('finish', () => file.close()); }); ```

For JSON:

axios.get('https://api.example.com/data', { responseType: 'stream' })
.then(res => {
const fileStream = createWriteStream('data.json');
res.data.pipe(fileStream);
});

After streaming, you might process or save the JSON. See our guide on saving JSON data for patterns.

Error Handling and Retries

A failed request can be transient. Implement retries with backoff to improve resilience:

const axios = require('axios');
const maxRetries = 3;
async function fetchWithRetry(url, retries = 0) {
try {
return await axios.get(url);
} catch (err) {
if (retries < maxRetries) {
await new Promise(r => setTimeout(r, 1000 * (retries + 1)));
return fetchWithRetry(url, retries + 1);
}
throw err;
}
}

Best practices:

  • Distinguish between client (4xx) and server errors (5xx).
  • Log errors centrally or use interceptors.
  • Fail fast on unrecoverable errors.

Production Tips and Scheduling

In production, you might hit rate limits or need regular polling. Use a scheduler like node-cron to run tasks at intervals.

Other tips:

  • Respect API rate limits by adding delays.
  • Cache responses locally when data changes infrequently.
  • Monitor metrics (latency, error rate) with a monitoring tool.

Pro Tip: Use keepAlive sockets in production for high throughput: js const agent = new http.Agent({ keepAlive: true }); axios.get(url, { httpAgent: agent });

Conclusion

Making HTTP requests in Node.js ranges from simple scripts to robust production workflows. The built-in http/https modules give you low-level control, while libraries like Axios or Fetch streamline JSON handling and error management. Remember to handle streams when working with large payloads, implement retries for transient failures, and schedule recurring jobs with cron. By understanding each approach, you’ll make more informed choices and build resilient, maintainable services.

Meta Description: Send HTTP requests in Node.js using built-in http/https modules, axios, or fetch API. Learn methods, examples, and best practices.


Mateen Kiani
Mateen Kiani
kiani.mateen012@gmail.com
I am a passionate Full stack developer with around 3 years of experience in MERN stack development and 1 year experience in blockchain application development. I have completed several projects in MERN stack, Nextjs and blockchain, including some NFT marketplaces. I have vast experience in Node js, Express, React and Redux.