New Research: Supply Chain Attack on Axios Pulls Malicious Dependency from npm.Details →
Socket
Book a DemoSign in
Socket

httpcloak

Package Overview
Dependencies
Maintainers
1
Versions
39
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

httpcloak

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

latest
Source
npmnpm
Version
1.6.1
Version published
Weekly downloads
895
181.45%
Maintainers
1
Weekly downloads
 
Created
Source

HTTPCloak Node.js

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

Installation

npm install httpcloak

Quick Start

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

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

  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-latest" });

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-latest" });

// 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-latest" });

// 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-latest" });

  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-latest" });

// 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-latest",
  proxy: "http://host:port",
});

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

// HTTPS proxy
const sessionHttps = new Session({
  preset: "chrome-latest",
  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-latest",
  proxy: "socks5h://host:port",
});

// With authentication
const sessionAuth = new Session({
  preset: "chrome-latest",
  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-latest",
  proxy: "https://user:pass@brd.superproxy.io: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-latest",
  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-latest",
  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 example.com's IP but request www.cloudflare.com
const session = new Session({
  preset: "chrome-latest",
  connectTo: { "www.cloudflare.com": "example.com" },
});

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-latest",
  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
const { Session } = require("httpcloak");

const session = new Session();

// Set a simple cookie (global, sent to all domains)
session.setCookie("session_id", "abc123");

// Set a domain-scoped cookie with full metadata
session.setCookie("auth", "token", {
  domain: ".example.com",
  path: "/",
  secure: true,
  httpOnly: true,
  sameSite: "Lax",
});

// Get all cookies (returns Cookie[] with full metadata)
const cookies = session.getCookies();
for (const cookie of cookies) {
  console.log(`${cookie.name}=${cookie.value} (domain: ${cookie.domain})`);
}

// Get a specific cookie by name (returns Cookie or null)
const cookie = session.getCookie("session_id");
if (cookie) console.log(cookie.value);

// Delete a cookie (omit domain to delete from all domains)
session.deleteCookie("session_id");
session.deleteCookie("auth", ".example.com"); // delete from specific domain

// Clear all cookies
session.clearCookies();

session.close();

Session Configuration

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

const session = new Session({
  preset: "chrome-latest",           // 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-146', 'chrome-145', 'chrome-144', 'chrome-143', 'chrome-141', 'chrome-133',
//  'firefox-133', 'safari-18', 'chrome-146-ios', ...]

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-latest" });

// 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("PUT", "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-latest" });

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();
}

Local Proxy

Use LocalProxy to apply TLS fingerprinting to any HTTP client (axios, node-fetch, etc.).

For HTTPS requests with full fingerprinting AND true streaming (request/response bodies not materialized into memory), use the X-HTTPCloak-Scheme header:

const { LocalProxy } = require("httpcloak");
const axios = require("axios");

// Start local proxy with Chrome fingerprint
const proxy = new LocalProxy({ preset: "chrome-latest" });
console.log(`Proxy running on ${proxy.proxyUrl}`);

// Use X-HTTPCloak-Scheme header for HTTPS with fingerprinting + streaming
const response = await axios.get("http://example.com/api", {
  // Note: http:// URL
  proxy: {
    host: "127.0.0.1",
    port: proxy.port,
  },
  headers: {
    "X-HTTPCloak-Scheme": "https", // Upgrades to HTTPS with fingerprinting
  },
});

// This provides:
// - Full TLS fingerprinting (Chrome/Firefox JA3/JA4)
// - HTTP/3 support
// - True streaming (request body NOT materialized into memory)
// - Header modification capabilities

proxy.close();

Why use X-HTTPCloak-Scheme?

Standard HTTP proxy clients use CONNECT tunneling for HTTPS, which means the proxy can't inspect or modify the request. The X-HTTPCloak-Scheme: https header tells LocalProxy to:

  • Accept the request as plain HTTP
  • Upgrade it to HTTPS internally
  • Apply full TLS fingerprinting
  • Stream request/response bodies without memory materialization

Basic Usage

const { LocalProxy } = require("httpcloak");
const axios = require("axios");

// Start local proxy with Chrome fingerprint
const proxy = new LocalProxy({ preset: "chrome-latest" });

// Standard HTTPS (uses CONNECT tunnel - fingerprinting via upstream proxy only)
const response = await axios.get("https://example.com", {
  proxy: {
    host: "127.0.0.1",
    port: proxy.port,
  },
});

// Per-request upstream proxy rotation
const rotatedResponse = await axios.get("https://example.com", {
  proxy: {
    host: "127.0.0.1",
    port: proxy.port,
  },
  headers: {
    "X-Upstream-Proxy": "http://user:pass@rotating-proxy.com:8080",
  },
});

proxy.close();

TLS-Only Mode

When your client already provides authentic browser headers, use TLS-only mode:

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

// Only apply TLS fingerprint, pass headers through
const proxy = new LocalProxy({ preset: "chrome-latest", tlsOnly: true });

// Your client's headers are preserved
const response = await fetch("https://example.com", {
  agent: new HttpsProxyAgent(proxy.proxyUrl),
  headers: { "User-Agent": "My Custom UA" },
});

proxy.close();

Session Registry

Route different requests through different browser fingerprints:

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

const proxy = new LocalProxy({ preset: "chrome-latest" });

// Create sessions with different fingerprints
const chromeSession = new Session({ preset: "chrome-latest" });
const firefoxSession = new Session({ preset: "firefox-133" });

// Register sessions with the proxy
proxy.registerSession("chrome-user", chromeSession);
proxy.registerSession("firefox-user", firefoxSession);

// Route requests using X-HTTPCloak-Session header
const response = await axios.get("https://example.com", {
  proxy: { host: "127.0.0.1", port: proxy.port },
  headers: { "X-HTTPCloak-Session": "firefox-user" }, // Uses firefox fingerprint
});

// Unregister when done
proxy.unregisterSession("chrome-user");
proxy.unregisterSession("firefox-user");

chromeSession.close();
firefoxSession.close();
proxy.close();

LocalProxy Options

const proxy = new LocalProxy({
  port: 0,              // Port (0 = auto-select)
  preset: "chrome-latest", // Browser fingerprint
  timeout: 30,          // Request timeout in seconds
  maxConnections: 1000, // Max concurrent connections
  tcpProxy: null,       // Default upstream TCP proxy
  udpProxy: null,       // Default upstream UDP proxy
  tlsOnly: false,       // TLS-only mode
});

proxy.port;           // Actual port number
proxy.proxyUrl;       // Full proxy URL (http://127.0.0.1:port)
proxy.isRunning;      // True if proxy is active
proxy.getStats();     // Returns object with request/connection stats
proxy.close();        // Stop the proxy

Platform Support

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

License

MIT

Keywords

http

FAQs

Package last updated on 15 Mar 2026

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts