Send an HTTP POST request from Node.js
Send JSON with fetch, the built-in HTTP modules, or Axios, while handling status codes, response bodies, and timeouts explicitly.
Use fetch() for a straightforward POST request on a supported Node.js release. The built-in http and https modules offer lower-level control; Axios is useful when a project already relies on its client configuration and interceptors.
Send JSON with fetch
Save this as an ES module, such as post.mjs, and replace the example endpoint with your API:
const response = await fetch('https://example.com/api', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ key1: 'value1', key2: 'value2' }),
signal: AbortSignal.timeout(5000),
});
if (!response.ok) {
const detail = await response.text();
throw new Error(`HTTP ${response.status}: ${detail.slice(0, 200)}`);
}
const data = response.status === 204 ? null : await response.json();
console.log(data);
Global fetch became available without its enabling flag in Node 18 and became stable in Node 21. Use a currently supported release rather than choosing an old release solely because it has fetch. Top-level await requires an ES module; in CommonJS, put it inside an async function.
Fetch rejects network failures but does not reject merely because a server returns 404 or 500. This example expects JSON on successful responses other than 204; adapt parsing to the endpoint's contract. Avoid exposing sensitive error bodies in production logs.
Use the built-in HTTPS client
This CommonJS example handles a textual response:
const https = require('node:https');
const payload = JSON.stringify({ key1: 'value1', key2: 'value2' });
const request = https.request('https://example.com/api', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Content-Length': Buffer.byteLength(payload),
},
}, (response) => {
response.setEncoding('utf8');
response.on('data', (chunk) => process.stdout.write(chunk));
response.on('error', (error) => console.error(error.message));
response.on('end', () => {
console.log(`\nHTTP ${response.statusCode}`);
});
});
request.on('error', (error) => console.error(error.message));
request.setTimeout(5000, () => request.destroy(new Error('Socket timed out')));
request.end(payload);
Use node:http and an http: URL for plain HTTP. Set both the protocol and destination correctly; changing the module alone is not enough. A known byte length is useful, but Content-Length is not universally mandatory: HTTP/1.1 can frame a request with chunked transfer encoding. end() completes the request body; data can begin transmission before it is called.
The socket timeout above is an inactivity timeout, not a guaranteed total deadline. It only aborts because the callback destroys the request.
Use Axios
After npm install axios, an ES module can use:
import axios from 'axios';
const response = await axios.post('https://example.com/api', {
key1: 'value1', key2: 'value2',
}, { timeout: 5000 });
console.log(response.data);
Axios serializes a plain object as JSON and normally rejects unsuccessful HTTP statuses. Its timeout must be configured; the default is no timeout. Automatic retries are not a built-in guarantee. Add a deliberate retry policy, especially because repeating a POST can duplicate work.
Choose the level of control
| Need | Useful starting point |
|---|---|
| Simple request on modern Node | fetch |
| Existing application client conventions | Its existing HTTP client |
| Interceptors and shared Axios configuration | Axios |
| Direct control over Node request/response streams | http or https |
FAQ
How do I send URL-encoded fields? Pass new URLSearchParams({ key: 'value' }) as the fetch body. Fetch supplies the corresponding content type unless you override it. Axios also supports URL-encoded bodies.
How do I upload a file? Use FormData with values supported by your client, such as a Blob for built-in fetch. Let the client generate the multipart boundary instead of setting a bare multipart content-type header manually. Consult the client's streaming-upload support for large files.
Does a timeout prove the server did nothing? No. The server may have processed the request before the client stopped waiting. Use idempotency mechanisms where the API provides them.
References
Contact us
Join the community
to join the community
Try Guance
Start online and pay only for what you use.
Get startedChoose a Guance plan