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 🙏

© 2025 – Pkg Stats / Ryan Hefner

node-libcurl-ja3

v5.0.3

Published

Node.js native bindings for libcurl-impersonate. Impersonate Chrome, Edge, Firefox and Safari TLS fingerprints.

Readme

node-libcurl-ja3

NPM version license

Disclaimer

This is a fork of node-libcurl using patches from lexiforest/curl-impersonate to impersonate the four major browsers: Chrome, Edge, Safari and Firefox. node-libcurl-ja3 is able to perform TLS and HTTP handshakes that are identical to that of a real browser.

Only the following platforms are supported:

  • Linux 64-bit (glibc based)
  • macOS Apple Silicon (M1+)

Prebuilt binaries are provided for Node.js 20 and 22. Any other version has not been tested and will need an environment capable of building the native module. Refer to Important Notes on Prebuilt Binaries / Direct Installation for a list of required system packages.

Although the library is named node-libcurl-ja3, it also supports http2 and ja4 impersonation (e.g. Akamai).

Table of Contents

Quick Start

  • This library cannot be used in a browser, it depends on native code.
  • There is no worker threads support at the moment. See #169

Install

npm i node-libcurl-ja3 --save

or

yarn add node-libcurl-ja3

Impersonate Usage

The following browser fingerprints are pre-configured:

  • Chrome 134
  • Edge 134
  • Firefox 136.0
  • Safari 18.3

To learn how to configure custom impersonation options, refer to the folder lib/impersonate/browser.

For brevity, this section covers a single example for creating impersonate instances using the curly API and Curl class. To use impersonation with the examples following this section, adapt them to use either:

  • impersonate in place of curly
  • Curl.impersonate in place of new Curl

Simple Impersonate Request - Async / Await using curly

const { Browser, impersonate } = require('node-libcurl-ja3');

const curly = impersonate(Browser.Chrome);
const { data } = await curly.get('https://tls.browserleaks.com/json');

console.log(data.ja3n_hash); // 8e19337e7524d2573be54efb2b0784c9

Simple Impersonate Request - Using Curl class

const { Browser, Curl } = require('node-libcurl-ja3');

const curl = Curl.impersonate(Browser.Chrome);

curl.setOpt('URL', 'tls.browserleaks.com/json');
curl.setOpt('FOLLOWLOCATION', true);

curl.on('end', function (statusCode, data, headers) {
  console.info(statusCode);
  console.info('---');
  console.info(data.length);
  console.info('---');
  console.info(this.getInfo('TOTAL_TIME'));

  this.close();
});

curl.on('error', curl.close.bind(curl));
curl.perform();

Simple Request - Async / Await using curly

this API is experimental and is subject to changes without a major version bump

const { curly } = require('node-libcurl-ja3');

const { statusCode, data, headers } = await curly.get('http://www.google.com')

Any option can be passed using their FULLNAME or a lowerPascalCase format:

const querystring = require('querystring');
const { curly } = require('node-libcurl-ja3');

const { statusCode, data, headers } = await curly.post('http://httpbin.com/post', {
  postFields: querystring.stringify({
    field: 'value',
  }),
  // can use `postFields` or `POSTFIELDS`
})

JSON POST example:

const { curly } = require('node-libcurl-ja3')
const { data } = await curly.post('http://httpbin.com/post', {
  postFields: JSON.stringify({ field: 'value' }),
  httpHeader: [
    'Content-Type: application/json',
    'Accept: application/json'
  ],
})

console.log(data)

Simple Request - Using Curl class

const { Curl } = require('node-libcurl-ja3');

const curl = new Curl();

curl.setOpt('URL', 'www.google.com');
curl.setOpt('FOLLOWLOCATION', true);

curl.on('end', function (statusCode, data, headers) {
  console.info(statusCode);
  console.info('---');
  console.info(data.length);
  console.info('---');
  console.info(this.getInfo( 'TOTAL_TIME'));
  
  this.close();
});

curl.on('error', curl.close.bind(curl));
curl.perform();

Setting HTTP headers

Pass an array of strings specifying headers

curl.setOpt(Curl.option.HTTPHEADER,
  ['Content-Type: application/x-amz-json-1.1'])

Form Submission (Content-Type: application/x-www-form-urlencoded)

const querystring = require('querystring');
const { Curl } = require('node-libcurl-ja3');

const curl = new Curl();
const close = curl.close.bind(curl);

curl.setOpt(Curl.option.URL, '127.0.0.1/upload');
curl.setOpt(Curl.option.POST, true)
curl.setOpt(Curl.option.POSTFIELDS, querystring.stringify({
  field: 'value',
}));

curl.on('end', close);
curl.on('error', close);

MultiPart Upload / HttpPost libcurl Option (Content-Type: multipart/form-data)

const { Curl } = require('node-libcurl-ja3');

const curl = new Curl();
const close = curl.close.bind(curl);

curl.setOpt(Curl.option.URL, '127.0.0.1/upload.php');
curl.setOpt(Curl.option.HTTPPOST, [
    { name: 'input-name', file: '/file/path', type: 'text/html' },
    { name: 'input-name2', contents: 'field-contents' }
]);

curl.on('end', close);
curl.on('error', close);

Binary Data

When requesting binary data make sure to do one of these:

  • Pass your own WRITEFUNCTION (https://curl.haxx.se/libcurl/c/CURLOPT_WRITEFUNCTION.html):
curl.setOpt('WRITEFUNCTION', (buffer, size, nmemb) => {
  // something
})
  • Enable one of the following flags:
curl.enable(CurlFeature.NoDataParsing)
// or
curl.enable(CurlFeature.Raw)

The reasoning behind this is that by default, the Curl instance will try to decode the received data and headers to utf8 strings, as can be seen here: https://github.com/JCMais/node-libcurl/blob/b55b13529c9d11fdcdd7959137d8030b39427800/lib/Curl.ts#L391

For more examples check the examples folder.

API

This library provides Typescript type definitions.

Almost all CURL options are supported, if you pass one that is not, an error will be thrown.

For more usage examples check the examples folder.

Special Notes

READFUNCTION option

The buffer passed as first parameter to the callback set with the READFUNCTION option is initialized with the size libcurl is using in their upload buffer (which can be set with UPLOAD_BUFFERSIZE), this is initialized using node::Buffer::Data(buf); which is basically the same than Buffer#allocUnsafe and therefore, it has all the implications as to its correct usage: https://nodejs.org/pt-br/docs/guides/buffer-constructor-deprecation/#regarding-buffer-allocunsafe

So, be careful, make sure to return exactly the amount of data you have written to the buffer on this callback. Only that specific amount is going to be copied and handed over to libcurl.

Common Issues

See COMMON_ISSUES.md

Benchmarks

See ./benchmark

Detailed Installation

The latest version of this package has prebuilt binaries (thanks to node-pre-gyp) available for:

  • Node.js: Latest two versions on active LTS (see https://github.com/nodejs/Release)

And on the following platforms:

  • Linux 64-bit (glibc based)
  • macOS Apple Silicon (M1+)

Installing with yarn add node-libcurl-ja3 or npm install node-libcurl-ja3 should download a prebuilt binary and no compilation will be needed.

The prebuilt binary is statically built with the following library versions, features and protocols:

Versions: libcurl/8.7.0-DEV BoringSSL zlib/1.3 brotli/1.1.0 zstd/1.5.6 nghttp2/1.63.0
Protocols: dict file ftp ftps gopher gophers http https imap imaps ipfs ipns mqtt pop3 pop3s rtsp smb smbs smtp smtps telnet tftp ws wss
Features: alt-svc AsynchDNS brotli HSTS HTTP2 HTTPS-proxy IPv6 Largefile libz NTLM SSL threadsafe UnixSockets zstd

If there is no prebuilt binary available that matches your system, or if the installation fails, then you will need an environment capable of compiling Node.js addons, which means:

  • python 3.x installed
  • updated C++ compiler able to compile C++17.

If you don't want to use the prebuilt binary even if it works on your system, you can pass a flag when installing:

With npm:

npm install node-libcurl-ja3 --build-from-source

With yarn:

npm_config_build_from_source=true yarn add node-libcurl-ja3

Important Notes on Prebuilt Binaries / Direct Installation

The built binaries are statically linked with BoringSSL, brotli, nghttp2, zlib and zstd.

Missing Packages

The built binaries do not have support for GSASL, GSS-API, HTTP3, IDN, LDAP, LDAPS, PSL, RTMP, SPNEGO, SSH, SSPI or TLS-SRP.

Building on Linux

If you are on a debian based system, install the required dependencies by running:

sudo apt install -qqy autoconf automake build-essential cmake curl libtool ninja-build pkg-config

Users for other distributions will need to find the equivalent packages and install via your package manager.

Building on macOS

On macOS you must have:

  • macOS >= 11.6 (Big Sur)
  • Xcode Command Line Tools
  • Homebrew
  • Bash >= 5.0 (unconfirmed)

You can check if you have Xcode Command Line Tools be running:

xcode-select -p

It should return their path, in case it returns nothing, you must install it by running:

xcode-select --install

Finally, install the remaining packages using homebrew:

brew install automake bash cmake libtool make meson ninja

Contributing

Read CONTRIBUTING.md

Acknowledgments