mrkeyoor.com_
Sun 09 Aug 06:59 UTC
npmWeb Backendupdated 09 Aug 2026

http-call

http-call is a small CommonJS HTTP client for Node.js built over the core http and https modules. It offers static methods for GET, POST, PUT, PATCH, DELETE, arbitrary requests, and response streaming; parses JSON according to the response Content-Type; serializes object request bodies as JSON; follows redirects; retries selected network errors; and honors common proxy environment variables. The returned object exposes the parsed body, status, headers, request, response, and final URL rather than imitating the browser fetch API.

Verdict

Do not start new code with the unscoped package: it is frozen at 5.3.0 while maintenance continues under @heroku/http-call. Keep it only for compatible legacy code, then plan a move to the scoped package or a current client with explicit retry and redirect policy.

API stability2/5The 5.x surface is compact and recognizable: HTTP.get, post, put, patch, delete, stream, request, create, HTTPError, and the returned body and response properties have stayed conceptually consistent. The practical contract is less stable than that list suggests because development moved from the unscoped http-call package at 5.3.0 to @heroku/http-call, where 5.6.0 adds a default timeout, redirect control, redirect URL fixes, and security-related header stripping that old installs do not receive.
Docs1/5The repository README is a very short usage page. It demonstrates a JSON GET, a TypeScript generic, and request headers, but does not document POST body rules, HTTPError fields, retries, redirect limits, timeouts, raw streaming, Next-Range paging, proxy variables, certificate loading, debug namespaces, or the move to @heroku/http-call. The shipped declaration file lists option names and methods, while important behavior still has to be learned from implementation and tests.
Maintenance2/5The repository is active and received code and release work in 2026, including cross-origin redirect protection and empty JSON-response handling. Those changes are published as @heroku/http-call 5.6.0, however, not as the requested unscoped package. The npm latest tag for http-call remains 5.3.0, published in December 2019. Maintenance is therefore healthy for the successor package but poor for the exact dependency a user gets from `npm install http-call`.
Ecosystem3/5The unscoped package recorded 3,025,135 downloads in the measured week and includes TypeScript declarations, automatic proxy environment support, JSON handling, streams, and an error type useful to its existing Heroku CLI consumers. Its public ecosystem is otherwise narrow: the repository has 14 stars, the README shows only a few operations, the API is Node-only and CommonJS, and there is no documented plugin or adapter layer comparable with axios, got, or undici.

Use it if

  • You maintain older Heroku CLI code that already imports the unscoped package and depends on its HTTP, HTTPError, or Next-Range behavior
  • You want a CommonJS Node client that automatically parses JSON and turns non-2xx responses into an error carrying statusCode and body
  • You need HTTP_PROXY, HTTPS_PROXY, NO_PROXY, SSL_CERT_FILE, and SSL_CERT_DIR support without constructing a proxy agent yourself
  • You consume an API that uses Heroku-style Next-Range headers and want array pages concatenated automatically
Skip it if

Setup reality

Installing the requested package is only `npm install http-call`. Version 5.3.0 has no peer dependency, native addon, credential file, or build step for consumers; it ships compiled CommonJS and its own TypeScript declarations, and its package metadata allows Node 8 or newer. The larger surprise is package identity. The active GitHub repository now has `@heroku/http-call` at 5.6.0, while `http-call` on npm still resolves to 5.3.0 from 2019. That old build has six runtime dependencies and misses newer fixes, including a default timeout, optional redirect following, safer relative redirect resolution, empty JSON-body handling, and removal of sensitive headers on cross-origin redirects. In 5.3.0 there is no default timeout, no AbortSignal option, no user-facing retry option, and no redirect-disable option. Selected DNS and socket errors are retried as many as five times with backoff, even for write methods, so callers must consider duplicate side effects. Object bodies become JSON only when no Content-Type is supplied or it is exactly application/json; form data must be encoded before passing it. Successful JSON is parsed only when the server sends application/json or a +json media type. Every non-2xx response becomes HTTPError, but its body is read into memory first. Proxy discovery is automatic from HTTP_PROXY, HTTPS_PROXY, and NO_PROXY. Corporate certificate files are read synchronously from SSL_CERT_FILE and every file in SSL_CERT_DIR when the proxy agent is created. Debug output uses the `http` and `http:headers` namespaces; authorization is redacted unless HTTP_CALL_REDACT=0, but other secret headers in 5.3.0 are not covered by that redaction rule.

Patterns

Read a JSON responseget-json

const { HTTP } = require('http-call');

const { body, statusCode, headers } = await HTTP.get(
  'https://api.example.com/users/42'
);
console.log(statusCode, headers['content-type'], body);

The body becomes an object only when the server declares application/json or a media type ending in +json; otherwise it remains a string.

Type the response body in TypeScripttype-json-body

import { HTTP } from 'http-call';

type User = { id: string; email: string };
const { body } = await HTTP.get<User>(
  'https://api.example.com/users/42'
);
console.log(body.email);

The generic is a compile-time assertion, not runtime validation. A malformed or differently shaped JSON response still reaches your code.

Build a query string explicitlysend-query-parameters

const query = new URLSearchParams({
  state: 'open',
  limit: '25',
});

const { body } = await HTTP.get(
  `https://api.example.com/issues?${query}`
);

Version 5.3.0 has no params option or serializer; query parameters must already be present in the URL.

Send authorization and custom headerssend-auth-header

const { body } = await HTTP.get('https://api.example.com/me', {
  headers: {
    authorization: `Bearer ${process.env.API_TOKEN}`,
    accept: 'application/json',
  },
});

Version 5.3.0 follows redirects and reuses these headers, including across origins. Do not call redirecting URLs with secrets unless you control the complete redirect chain.

POST an object as JSONpost-json

const { body } = await HTTP.post('https://api.example.com/users', {
  body: {
    name: 'Ada',
    email: 'ada@example.com',
  },
});
console.log(body);

A truthy object body is stringified, Content-Type defaults to application/json, and Content-Length is set. Empty strings, 0, and false are treated as no body.

POST URL-encoded form datapost-form

const form = new URLSearchParams({
  grant_type: 'client_credentials',
  scope: 'read:orders',
}).toString();

const { body } = await HTTP.post('https://api.example.com/token', {
  headers: { 'content-type': 'application/x-www-form-urlencoded' },
  body: form,
});

Encode the form yourself. When Content-Type is not exactly application/json, the package sends the supplied string without JSON serialization.

Use PUT, PATCH, and DELETEuse-write-methods

await HTTP.put('https://api.example.com/users/42', {
  body: { name: 'Ada Lovelace' },
});

await HTTP.patch('https://api.example.com/users/42', {
  body: { active: false },
});

await HTTP.delete('https://api.example.com/users/42');

Eligible network failures are retried for all methods in 5.3.0. A write can be repeated if the server acted before the connection failed.

Create a client with shared defaultscreate-configured-client

const API = HTTP.create({
  host: 'api.example.com',
  protocol: 'https:',
  timeout: 10000,
  headers: { accept: 'application/json' },
});

const { body } = await API.get('/v1/orders');

HTTP.create returns a subclass with defaults. Pass paths beginning with /; a full URL can override the configured host and protocol.

Set a request timeoutset-timeout

const { body } = await HTTP.get('https://api.example.com/slow', {
  timeout: 10000,
});

The unscoped 5.3.0 build has no default timeout and no AbortSignal option. Set a timeout on every call or in an HTTP.create client.

Inspect non-2xx failureshandle-http-errors

const { HTTP, HTTPError } = require('http-call');

try {
  await HTTP.get('https://api.example.com/private');
} catch (error) {
  if (error instanceof HTTPError) {
    console.error(error.statusCode, error.body);
  } else {
    throw error;
  }
}

HTTPError is used for responses outside 200 through 299. DNS, socket, timeout, parse, and redirect failures are different errors.

Stream a successful response to diskstream-download

const { createWriteStream } = require('node:fs');
const { pipeline } = require('node:stream/promises');

const { response } = await HTTP.stream(
  'https://downloads.example.com/archive.zip'
);
await pipeline(response, createWriteStream('archive.zip'));

Raw streaming applies only to successful responses. Error responses are buffered and parsed before HTTPError is thrown.

Choose automatic or single-page Next-Range handlingcontrol-next-range-paging

// Concatenates array pages while the server returns Next-Range.
const all = await HTTP.get('https://api.example.com/events');

// Stops after the first response.
const first = await HTTP.get('https://api.example.com/events', {
  partial: true,
});

console.log(all.body, first.body, first.headers['next-range']);

Automatic paging works only for GET responses whose parsed body is an array. It buffers and concatenates every page, so partial: true is safer for large collections.

Alternatives

PackageRegistryPick it when
@heroku/http-callnpmYou need this API but want the actively released scoped package with current redirect and timeout fixes
undicinpmYou want the Node fetch implementation plus pooling, dispatchers, and lower-level HTTP controls
gotnpmYou want a current Node-only client with documented retry, hooks, pagination, streaming, and cancellation controls
axiosnpmYou need one familiar client across Node and browsers, especially for interceptors and request configuration