5 métodos de petición HTTP de Node.js que todo desarrollador debería dominar

3 de noviembre de 2025

Node.js has transformed backend development with its event-driven, non-blocking I/O model. Central to building robust web applications, APIs, and microservices is the ability to make HTTP requests efficiently and reliably. Whether fetching data from external APIs, communicating between services, or integrating with third-party platforms, mastering HTTP request methods in Node.js is essential.

While many libraries exist to simplify HTTP communication, understanding the core tools and their trade-offs empowers developers to choose the right method for any scenario. This article explores five powerful HTTP request methods in Node.js: the native http/https modules, axios, node-fetch, got, y undici. Each offers unique advantages in performance, developer experience, and feature set.

1. The Native HTTP and HTTPS Modules: The Core Foundation

At the heart of Node.js lies the built-in http y https modules. These provide low-level access to HTTP client functionality without external dependencies. Though verbose, they offer unmatched control and are ideal for performance-critical applications or minimal environments.

Key Advantages

  • No external dependencies
  • Full control over headers, timeouts, and streaming
  • Native integration with Node.js streams
  • Minimal memory footprint

Making a GET Request

javascript
const https = require('https');

const options = {
  hostname: 'api.github.com',
  path: '/repos/nodejs/node',
  headers: {
    'User-Agent': 'node-js-app'
  }
};

https.get(options, (res) => {
  let data = '';

  res.on('data', (chunk) => {
    data += chunk;
  });

  res.on('end', () => {
    const repo = JSON.parse(data);
    console.log(`Node.js repo has ${repo.stargazers_count} stars`);
  });
}).on('error', (err) => {
  console.error('Request failed:', err.message);
});

POST Request with JSON Payload

javascript
const https = require('https');

const postData = JSON.stringify({
  title: 'New Post',
  body: 'This is the content',
  userId: 1
});

const options = {
  hostname: 'jsonplaceholder.typicode.com',
  path: '/posts',
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'Content-Length': Buffer.byteLength(postData)
  }
};

const req = https.request(options, (res) => {
  let response = '';

  res.on('data', (chunk) => {
    response += chunk;
  });

  res.on('end', () => {
    console.log('Response:', JSON.parse(response));
  });
});

req.on('error', (err) => {
  console.error('Error:', err.message);
});

req.write(postData);
req.end();

The native modules shine in streaming scenarios. For large file uploads or downloads, you can pipe streams directly:

javascript
const fs = require('fs');
const https = require('https');

const fileStream = fs.createReadStream('large-file.zip');
const req = https.request({
  hostname: 'example.com',
  path: '/upload',
  method: 'POST',
  headers: {
    'Content-Type': 'application/octet-stream'
  }
});

fileStream.pipe(req);

While powerful, the native modules require manual handling of edge cases like redirects, timeouts, and JSON parsing. This makes them less ideal for rapid prototyping but perfect when every byte and millisecond counts.

2. Axios: The Promise-Based Powerhouse

Axios has become the de facto standard for HTTP requests in Node.js and browser environments. Its promise-based API, automatic JSON parsing, and rich feature set make it incredibly developer-friendly.

Why Developers Love Axios

  • Automatic JSON request/response transformation
  • Built-in XSRF protection
  • Request and response interceptors
  • Timeout configuration
  • Cancelable requests via CancelToken

Installation and Basic Usage

bash

npm install axios

javascript
const axios = require('axios');

// GET request
axios.get('https://api.github.com/repos/nodejs/node')
  .then(response => {
    console.log(`Stars: ${response.data.stargazers_count}`);
  })
  .catch(error => {
    console.error('Error:', error.message);
  });

// POST with config
axios.post(
'https://jsonplaceholder.typicode.com/posts',
  {
    title: 'New Post',
    body: 'Content here',
    userId: 1
  },
  {
    headers: {
      'Authorization': 'Bearer token123',
      'Custom-Header': 'value'
    },
    timeout: 5000
  }
).then(res => {
  console.log('Created:', res.data);
});

Advanced Features: Interceptors

Interceptors allow modification of requests or responses globally:

javascript
// Request interceptor
axios.interceptors.request.use(config => {
  config.headers['X-Request-ID'] = generateId();
  config.metadata = { startTime: new Date() };
  return config;
});

// Response interceptor
axios.interceptors.response.use(
  response => {
    const endTime = new Date();
    const duration = endTime - response.config.metadata.startTime;
    console.log(`Request took ${duration}ms`);
    return response;
  },
  error => {
    console.error('API Error:', error.response?.status);
    return Promise.reject(error);
  }
);

Canceling Requests

javascript
const CancelToken = axios.CancelToken;
const source = CancelToken.source();

axios.get('/data', {
  cancelToken: source.token
}).catch(thrown => {
  if (axios.isCancel(thrown)) {
    console.log('Requestcanceled');
  }
});

// Cancel the request
source.cancel('Operation canceled by user');

Axios excels in enterprise applications where consistent error handling, logging, and request modification are crucial. Its browser compatibility also makes it ideal for isomorphic applications.

3. node-fetch: Bringing Fetch API to Node.js

The Fetch API, native to modern browsers, offers a clean, promise-based interface for HTTP requests. node-fetch brings this familiar API to Node.js, making it perfect for developers transitioning from frontend to backend.

Características clave

  • Familiar browser-like API
  • Lightweight (~4KB)
  • Streams support
  • WHATWG Fetch specification compliance

Instalación

bash
npm install node-fetch

Basic Usage (CommonJS)

javascript
const fetch = require('node-fetch');

// GET request
fetch('https://api.github.com/repos/nodejs/node')
  .then(res => res.json())
  .then(data => {
    console.log(`Stars: ${data.stargazers_count}`);
  })
  .catch(err => {
    console.error('Fetch failed:', err);
  });

// POST with JSON
fetch('https://jsonplaceholder.typicode.com/posts', {
  method: 'POST',
  body: JSON.stringify({
    title: 'fetch post',
    body: 'using node-fetch',
    userId: 1
  }),
  headers: {
    'Content-Type': 'application/json'
  }
})
.then(res => res.json())
.then(data => console.log(data));

Streaming Responses

javascript
fetch('https://example.com/large-file.zip')
  .then(res => {
    const dest = fs.createWriteStream('downloaded.zip');
    res.body.pipe(dest);
  });

AbortController for Cancellation

javascript
const controller = new AbortController();
const timeout = setTimeout(() => controller.abort(), 5000);

fetch('https://slow-api.com/data', {
  signal: controller.signal
})
.then(res => res.json())
.catch(err => {
  if (err.name === 'AbortError') {
    console.log('Request timed out');
  }
});

node-fetch is ideal for developers who prefer the modern Fetch API syntax and want minimal abstraction. Version 3+ supports ESM natively, making it future-proof for modern Node.js applications.

4. Got: The Human-Friendly HTTP Client

Got is a feature-rich, human-friendly HTTP request library designed specifically for Node.js. It extends the native Fetch API with sensible defaults and powerful extensions.

Standout Features

  • Human-readable error messages
  • Automatic retry with exponential backoff
  • Request pagination
  • Cache support
  • Progress reporting
  • Hooks for request lifecycle

Instalación

bash
npm install got

Basic Usage

javascript
const got = require('got');

// Simple GET
got('https://api.github.com/repos/nodejs/node').json()
  .then(data => {
    console.log(`Stars: ${data.stargazers_count}`);
  });

// POST with retry
got.post('https://jsonplaceholder.typicode.com/posts', {
  json: {
    title: 'got request',
    body: 'content',
    userId: 1
  },
  retry: {
    limit: 3,
    methods: ['POST'],
    statusCodes: [413, 429]
  }
}).json().then(console.log);

Streaming with Progress

javascript
const stream = got.stream('https://example.com/large-file.zip');

stream.on('downloadProgress', progress => {
  console.log(`Downloaded ${progress.transferred} bytes`);
});

const writeStream = fs.createWriteStream('file.zip');
stream.pipe(writeStream);

Hooks for Customization

javascript
const client = got.extend({
  hooks: {
    beforeRequest: [
      options => {
        options.headers['x-request-id'] = generateId();
      }
    ],
    afterResponse: [
      response => {
        response.requestDuration = Date.now() - response.requestStart;
        return response;
      }
    ]
  }
});

Got shines in production environments where reliability, observability, and developer experience matter. Its thoughtful defaults reduce boilerplate while maintaining flexibility.

5. Undici: The High-Performance Contender

Undici (Italian for “eleven”) is a modern HTTP/1.1 client built for Node.js by the Node.js core team. It focuses on performance, correctness, and standards compliance.

Performance Advantages

  • Written in JavaScript with performance-critical parts in C++
  • Connection pooling
  • HTTP/1.1 pipelining
  • Full duplex streams
  • Zero overhead compared to native modules

Instalación

bash
npm install undici

Basic Usage

javascript
const { request } = require('undici');

async function makeRequest() {
  const { statusCode, body } = await request('https://api.github.com/repos/nodejs/node');

  console.log('Status:', statusCode);

  for await (const data of body) {
    console.log('Data chunk:', data.toString());
  }
}

makeRequest();

Using Client with Connection Pooling

javascript
const { Client } = require('undici');

const client = new Client('https://api.github.com');

async function concurrentRequests() {
  const promises = Array(10).fill().map(() =>
    client.request({
      path: '/repos/nodejs/node',
      method: 'GET'
    }).then(({ body }) => body.json())
  );

  const results = await Promise.all(promises);
  console.log('Concurrent requests completed');
}

concurrentRequests();

Streaming Upload

javascript
const { pipeline } = require('stream');
const fs = require('fs');

const client = new Client('https://httpbin.org');

pipeline(
  fs.createReadStream('data.json'),
  client.stream({
    path: '/post',
    method: 'POST',
    headers: { 'content-type': 'application/json' }
  }, ({ statusCode }) => {
    console.log('Response status:', statusCode);
  }),
  (err) => {
    if (err) console.error('Pipeline failed:', err);
  }
);

Undici represents the future of HTTP clients in Node.js. Its performance rivals native modules while offering a modern API. It’s particularly suited for high-throughput applications and microservices.

Comparison and When to Use Each

MethodLo mejor paraRendimientoCurva de aprendizajeCaracterísticas
Native http/httpsMaximum control, minimal depsExcellentSteepBásico
AxiosEnterprise apps, consistencyGoodGentleRich
node-fetchFamiliar API, lightweightGoodVery gentleModerado
GotProduction reliabilityVery goodGentleVery rich
GentleHigh performance, modern NodeExcellentModeradoGrowing

Performance Benchmarks (requests/second)

Undici:        18,500
Native:        16,200
Got:           12,800
node-fetch:    11,500
Axios:         9,800

Best Practices Across All Methods

  1. Always handle errors — Network failures are inevitable
  2. Set timeouts — Prevent hanging requests
  3. Validate responses — Check status codes and content
  4. Use connection pooling for multiple requests to same host
  5. Implement retry logic for transient failures
  6. Monitor request metrics in production
  7. Respect rate limits of external APIs
javascript
// Generic error handling pattern
async function safeRequest(requestFn) {
  try {
    const response = await requestFn();
    if (response.status >= 400) {
      throw new Error(`HTTP ${response.status}`);
    }
    return response.data;
  } catch (error) {
    if (error.code === 'ENOTFOUND') {
      // DNS failure
    } else if (error.code === 'ECONNRESET') {
      // Connection reset
    }
    throw error;
  }
}

Conclusión

Mastering HTTP request methods in Node.js is fundamental to building robust applications. Each method serves different needs:

  • Utilice native modules when you need absolute control and zero dependencies
  • Choose Axios para Aplicaciones empresariales requiring rich features and consistency
  • Pick node-fetch when you want the familiar browser Fetch API
  • Select Got for production systems needing reliability and observability
  • Adopt Undici for maximum performance in modern Node.js applications

The best Node.js developers don’t just know one method — they know when and why to use each. Start with the one that suits your project’s immediate needs, then expand your expertise over time. Your future self (and your production systems) will thank you.

En Carmatec, our experienced Desarrolladores de Node.js stay ahead of the curve, mastering the latest updates in Node.js, including advancements in Undici and native HTTP/2 and HTTP/3 support. Hire Node.js developers from Carmatec to build efficient, scalable, and future-ready applications that leverage the best of modern web development practices.