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

httpcloak

v1.5.6

Published

Browser fingerprint emulation HTTP client with HTTP/1.1, HTTP/2, and HTTP/3 support

Readme

HTTPCloak Node.js

Browser fingerprint emulation HTTP client with HTTP/1.1, HTTP/2, and HTTP/3 support.

Installation

npm install httpcloak

Quick Start

Promise-based Usage (Recommended)

const { Session } = require("httpcloak");

async function main() {
  const session = new Session({ preset: "chrome-143" });

  try {
    // GET request
    const response = await session.get("https://www.cloudflare.com/cdn-cgi/trace");
    console.log(response.statusCode);
    console.log(response.text);

    // POST request with JSON body
    const postResponse = await session.post("https://api.example.com/data", {
      key: "value",
    });

    // Custom headers
    const customResponse = await session.get("https://example.com", {
      "X-Custom": "value",
    });

    // Concurrent requests
    const responses = await Promise.all([
      session.get("https://example.com/1"),
      session.get("https://example.com/2"),
      session.get("https://example.com/3"),
    ]);
  } finally {
    session.close();
  }
}

main();

ES Modules

import { Session } from "httpcloak";

const session = new Session({ preset: "chrome-143" });

const response = await session.get("https://example.com");
console.log(response.text);

session.close();

Synchronous Usage

const { Session } = require("httpcloak");

const session = new Session({ preset: "chrome-143" });

// Sync GET
const response = session.getSync("https://example.com");
console.log(response.statusCode);
console.log(response.text);

// Sync POST
const postResponse = session.postSync("https://api.example.com/data", {
  key: "value",
});

session.close();

Callback-based Usage

const { Session } = require("httpcloak");

const session = new Session({ preset: "chrome-143" });

// GET with callback
session.getCb("https://example.com", (err, response) => {
  if (err) {
    console.error("Error:", err.message);
    return;
  }
  console.log(response.statusCode);
  console.log(response.text);
});

// POST with callback
session.postCb(
  "https://api.example.com/data",
  { key: "value" },
  (err, response) => {
    if (err) {
      console.error("Error:", err.message);
      return;
    }
    console.log(response.statusCode);
  }
);

Streaming Downloads

For large downloads, use streaming to avoid loading entire response into memory:

const { Session } = require("httpcloak");
const fs = require("fs");

async function downloadFile() {
  const session = new Session({ preset: "chrome-143" });

  try {
    // Start streaming request
    const stream = session.getStream("https://example.com/large-file.zip");

    console.log(`Status: ${stream.statusCode}`);
    console.log(`Content-Length: ${stream.contentLength}`);
    console.log(`Protocol: ${stream.protocol}`);

    // Read in chunks
    const file = fs.createWriteStream("downloaded-file.zip");
    let totalBytes = 0;
    let chunk;

    while ((chunk = stream.readChunk(65536)) !== null) {
      file.write(chunk);
      totalBytes += chunk.length;
      console.log(`Downloaded ${totalBytes} bytes...`);
    }

    file.end();
    stream.close();
    console.log(`Download complete: ${totalBytes} bytes`);
  } finally {
    session.close();
  }
}

downloadFile();

Streaming with All Methods

const { Session } = require("httpcloak");

const session = new Session({ preset: "chrome-143" });

// Stream GET
const getStream = session.getStream("https://example.com/data");

// Stream POST
const postStream = session.postStream("https://example.com/upload", "data");

// Stream with custom options
const customStream = session.requestStream({
  method: "PUT",
  url: "https://example.com/resource",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({ key: "value" }),
});

// Read response
let chunk;
while ((chunk = customStream.readChunk(65536)) !== null) {
  console.log(`Received ${chunk.length} bytes`);
}
customStream.close();

session.close();

Proxy Support

HTTPCloak supports HTTP, SOCKS5, and HTTP/3 (MASQUE) proxies with full fingerprint preservation.

HTTP Proxy

const { Session } = require("httpcloak");

// Basic HTTP proxy
const session = new Session({
  preset: "chrome-143",
  proxy: "http://host:port",
});

// With authentication
const sessionAuth = new Session({
  preset: "chrome-143",
  proxy: "http://user:pass@host:port",
});

// HTTPS proxy
const sessionHttps = new Session({
  preset: "chrome-143",
  proxy: "https://user:pass@host:port",
});

SOCKS5 Proxy

const { Session } = require("httpcloak");

// SOCKS5 proxy (with DNS resolution on proxy)
const session = new Session({
  preset: "chrome-143",
  proxy: "socks5h://host:port",
});

// With authentication
const sessionAuth = new Session({
  preset: "chrome-143",
  proxy: "socks5h://user:pass@host:port",
});

const response = await session.get("https://www.cloudflare.com/cdn-cgi/trace");
console.log(response.protocol); // h3 (HTTP/3 through SOCKS5!)

HTTP/3 MASQUE Proxy

MASQUE (RFC 9484) enables HTTP/3 connections through compatible proxies:

const { Session } = require("httpcloak");

// MASQUE proxy (auto-detected for known providers like Bright Data)
const session = new Session({
  preset: "chrome-143",
  proxy: "https://user:[email protected]:10001",
});

const response = await session.get("https://www.cloudflare.com/cdn-cgi/trace");
console.log(response.protocol); // h3

Split Proxy Configuration

Use different proxies for TCP (HTTP/1.1, HTTP/2) and UDP (HTTP/3) traffic:

const { Session } = require("httpcloak");

const session = new Session({
  preset: "chrome-143",
  tcpProxy: "http://tcp-proxy:port",      // For HTTP/1.1, HTTP/2
  udpProxy: "https://masque-proxy:port",  // For HTTP/3
});

Advanced Features

Encrypted Client Hello (ECH)

ECH encrypts the SNI (Server Name Indication) to prevent traffic analysis. Works with all Cloudflare domains:

const { Session } = require("httpcloak");

// Enable ECH for Cloudflare domains
const session = new Session({
  preset: "chrome-143",
  echConfigDomain: "cloudflare-ech.com",
});

const response = await session.get("https://www.cloudflare.com/cdn-cgi/trace");
console.log(response.text);
// Output includes: sni=encrypted, http=http/3

Domain Fronting (Connect-To)

Connect to one server while requesting a different domain:

const { Session } = require("httpcloak");

// Connect to claude.ai's IP but request www.cloudflare.com
const session = new Session({
  preset: "chrome-143",
  connectTo: { "www.cloudflare.com": "claude.ai" },
});

const response = await session.get("https://www.cloudflare.com/cdn-cgi/trace");

Combined: SOCKS5 + ECH

Get HTTP/3 with encrypted SNI through a SOCKS5 proxy:

const { Session } = require("httpcloak");

const session = new Session({
  preset: "chrome-143",
  proxy: "socks5h://user:pass@host:port",
  echConfigDomain: "cloudflare-ech.com",
});

const response = await session.get("https://www.cloudflare.com/cdn-cgi/trace");
// Response shows: http=http/3, sni=encrypted

Cookie Management

const { Session } = require("httpcloak");

const session = new Session();

// Set a cookie
session.setCookie("session_id", "abc123");

// Get all cookies
const cookies = session.getCookies();
console.log(cookies);

// Access cookies as property
console.log(session.cookies);

// Clear a cookie
session.clearCookie("session_id");

// Clear all cookies
session.clearCookies();

session.close();

Session Configuration

const { Session } = require("httpcloak");

const session = new Session({
  preset: "chrome-143",           // Browser fingerprint preset
  proxy: null,                    // Proxy URL
  tcpProxy: null,                 // Separate TCP proxy
  udpProxy: null,                 // Separate UDP proxy (MASQUE)
  timeout: 30,                    // Request timeout in seconds
  httpVersion: "auto",            // "auto", "h1", "h2", "h3"
  verify: true,                   // SSL certificate verification
  allowRedirects: true,           // Follow redirects
  maxRedirects: 10,               // Maximum redirect count
  retry: 3,                       // Retry count on failure
  preferIpv4: false,              // Prefer IPv4 over IPv6
  connectTo: null,                // Domain fronting map
  echConfigDomain: null,          // ECH config domain
});

Available Presets

const { availablePresets } = require("httpcloak");

console.log(availablePresets());
// ['chrome-143', 'chrome-143-windows', 'chrome-143-linux', 'chrome-143-macos',
//  'chrome-131', 'firefox-133', 'safari-18', ...]

Response Object

Standard Response

const response = await session.get("https://example.com");

response.statusCode;   // number: HTTP status code
response.headers;      // object: Response headers (values are arrays)
response.body;         // Buffer: Raw response body
response.text;         // string: Response body as text
response.finalUrl;     // string: Final URL after redirects
response.protocol;     // string: Protocol used (http/1.1, h2, h3)
response.ok;           // boolean: True if status < 400
response.cookies;      // array: Cookies from response
response.history;      // array: Redirect history

// Get specific header
const contentType = response.getHeader("Content-Type");
const allCookies = response.getHeaders("Set-Cookie");

// Parse JSON
const data = response.json();

Streaming Response

const stream = session.getStream("https://example.com");

stream.statusCode;      // number: HTTP status code
stream.headers;         // object: Response headers (values are arrays)
stream.contentLength;   // number: Content length (-1 if unknown)
stream.finalUrl;        // string: Final URL after redirects
stream.protocol;        // string: Protocol used

// Read all bytes
const data = stream.readAll();

// Read in chunks (memory efficient)
let chunk;
while ((chunk = stream.readChunk(65536)) !== null) {
  process(chunk);
}

stream.close();

HTTP Methods

const { Session } = require("httpcloak");

const session = new Session({ preset: "chrome-143" });

// GET
const response = await session.get("https://example.com");

// POST
const postResponse = await session.post("https://example.com", { key: "value" });

// PUT
const putResponse = await session.put("https://example.com", { key: "value" });

// PATCH
const patchResponse = await session.patch("https://example.com", { key: "value" });

// DELETE
const deleteResponse = await session.delete("https://example.com");

// HEAD
const headResponse = await session.head("https://example.com");

// OPTIONS
const optionsResponse = await session.options("https://example.com");

// Custom request
const customResponse = await session.request({
  method: "PUT",
  url: "https://api.example.com/resource",
  headers: { "X-Custom": "value" },
  body: { data: "value" },
  timeout: 60,
});

session.close();

Error Handling

const { Session, HTTPCloakError } = require("httpcloak");

const session = new Session();

try {
  const response = await session.get("https://example.com");
} catch (err) {
  if (err instanceof HTTPCloakError) {
    console.error("HTTPCloak error:", err.message);
  } else {
    console.error("Unknown error:", err);
  }
}

session.close();

TypeScript Support

HTTPCloak includes TypeScript definitions out of the box:

import { Session, Response, StreamResponse, HTTPCloakError } from "httpcloak";

const session = new Session({ preset: "chrome-143" });

async function fetchData(): Promise<Response> {
  return session.get("https://example.com");
}

async function downloadLargeFile(): Promise<void> {
  const stream: StreamResponse = session.getStream("https://example.com/file");
  let chunk: Buffer | null;
  while ((chunk = stream.readChunk(65536)) !== null) {
    // Process chunk
  }
  stream.close();
}

Platform Support

  • Linux (x64, arm64)
  • macOS (x64, arm64)
  • Windows (x64, arm64)
  • Node.js 16+

License

MIT