npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

node-curlifier

v0.0.1

Published

A non-prototype-mutating library for converting Node.js http.ClientRequest objects into curl command

Readme

node-curlifier

A non-prototype-mutating library for converting Node.js http.ClientRequest objects into curl command.

Quick start

npm install node-curlifier

or

yarn add node-curlifier

or

pnpm add node-curlifier

then

import http from 'http';
import { requestToCurl } from 'node-curlifier';

const req = http.request('https://api.example.com/users', res => {
  // Handle response...
});

requestToCurl(req).then(curl => {
  console.log(curl);
  // Output: curl 'https://api.example.com/users' --compressed
});

req.end();

Stability

Used in production, but still not super battle-tested.

Motivation

Module request-to-curl is a pretty handy way to get copy-pastable curl commands to debug network issues.

But it comes with 2 problems:

  1. It shims http.ClientRequest.prototype, which is yucky
  2. It buffers all requests, which can lead to memory pressure and leaks in cases like HTTP streaming or big file uploads.

This library gives you more control by only shimming individual requests that you want to log. No prototypes are modified. This allows you to decide where the performance tradeoffs make sense.

API

requestToCurl(req, callback?, timeout?)

Attaches lightweight shims to the provided request object so it can buffer anything written through write() or end(), and resolves as soon as the caller invokes req.end(). Returns a promise that resolves with the curl string, rejects with a timeout error. Callback interface is also supported, which might be more convenient for something like simple logging.

Parameters

  • req: A Node.js http.ClientRequest object.
  • callback? (error, curl?): Optional Node-style callback invoked when the request finishes or when the timeout fires.
  • timeout?: Controls how long to wait for req.end():
    • number: Custom timeout in milliseconds.
    • true or undefined: Use requestToCurl.DEFAULT_TIMEOUT_MS (30s by default).
    • false: Disable the timeout and wait indefinitely.

When the timeout triggers, the returned promise rejects with { code: 'ETIMEDOUT' } and the callback receives the same error as its first argument.

// Using a callback
requestToCurl(req, (err, curl) => {
  if (err) {
    console.error('Failed to capture curl', err);
    return;
  }
  console.log(curl);
});

// Custom timeout (5 seconds)
const curl = await requestToCurl(req, undefined, 5000);

// Disable timeout
const slowCurl = await requestToCurl(req, undefined, false);

Best-effort behavior: if you call requestToCurl after the request has already finished, the library will use any buffered output (for example Node's outputData queue) so you still get a useful command without throwing.

Usage with axios + http adapter

Axios is a bit inconvenient to work with, because it attaches its own headers and does other processing after calling interceptors, but before sending the request. That's why curl loggers that rely on interceptors (eg. axios-curlirize, axios2curl) won't produce the correct results.

You can use this library with axios by producing a transport shim like this:

import followRedirects, { FollowOptions } from 'follow-redirects';

const makeTransport = (config: AxiosRequestConfig) => {
  const url = new URL(config.url, config.baseURL);
  const transport = /https:?/.test(url.protocol) ? followRedirects.https : followRedirects.http;

  // NOTE: Axios only uses transport.request, so we don't need anything else
  return {
    request: (requestOptions: FollowOptions<RequestOptions>, handleResponse) => {
      if (config.maxRedirects) {
        requestOptions.maxRedirects = config.maxRedirects;
      }

      const req = transport.request(requestOptions, handleResponse);

      requestToCurl(req['_currentRequest'], (err, curl) => {
        if (curl) {
          console.log(`[REQ] ${curl}`);
        }
      });

      return req;
    },
  };
};

const config = {
  url: 'https://example.com/api',
};

const resp = await axiosInstance({
  ...config,
  transport: makeTransport(config),
});

//...

This pattern is still experimental, which is why it's not officially in the library.

Changelog

0.0.1

  • Initial release

License

MIT - See MIT.md for full license text.