├── .gitignore ├── src ├── index.ts ├── interface │ ├── index.ts │ ├── client.ts │ ├── native.ts │ └── payload.ts ├── utils │ ├── index.ts │ ├── tlsError.ts │ ├── logger.ts │ ├── request.ts │ ├── native.ts │ └── download.ts ├── lib │ ├── index.ts │ ├── tlsClient.ts │ ├── Response.ts │ ├── Client.ts │ ├── requests.ts │ ├── Cookie.ts │ └── Session.ts └── workers │ └── index.ts ├── typings ├── index.d.ts ├── interface │ ├── index.d.ts │ ├── client.d.ts │ ├── native.d.ts │ └── payload.d.ts ├── lib │ ├── tlsClient.d.ts │ ├── index.d.ts │ ├── Client.d.ts │ ├── requests.d.ts │ ├── Response.d.ts │ ├── Cookie.d.ts │ └── Session.d.ts ├── utils │ ├── tlsError.d.ts │ ├── index.d.ts │ ├── native.d.ts │ ├── download.d.ts │ ├── logger.d.ts │ └── request.d.ts └── workers │ └── index.d.ts ├── dist ├── interface │ ├── client.js │ ├── native.js │ ├── payload.js │ ├── index.js │ └── session.js ├── lib │ ├── tlsClient.js │ ├── index.js │ ├── Response.js │ ├── requests.js │ ├── Client.js │ ├── Cookie.js │ └── Session.js ├── utils │ ├── tlsError.js │ ├── index.js │ ├── logger.js │ ├── request.js │ ├── native.js │ └── download.js ├── workers │ └── index.js └── index.js ├── docs ├── .nojekyll ├── assets │ ├── navigation.js │ ├── highlight.css │ └── search.js ├── types │ ├── CertCompressionAlgo.html │ ├── PseudoHeaderOrder.html │ ├── SupportedVersions.html │ ├── Methods.html │ ├── KeyShareCurves.html │ └── SupportedSignatureAlgorithms.html ├── functions │ ├── initTLS.html │ ├── destroyTLS.html │ └── fetch.html ├── hierarchy.html ├── interfaces │ ├── PriorityFrames.html │ └── PriorityParam.html └── modules.html ├── tsconfig.json ├── examples ├── extra.js ├── simple.js ├── samples │ ├── executable.md │ └── cookie-example.md ├── images.js ├── timeout.js └── advanced.js ├── package.json └── CHANGELOG.md /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | *.lock -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./interface"; 2 | export * from "./lib"; 3 | -------------------------------------------------------------------------------- /typings/index.d.ts: -------------------------------------------------------------------------------- 1 | export * from "./interface"; 2 | export * from "./lib"; 3 | -------------------------------------------------------------------------------- /src/interface/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./session"; 2 | export * from "./client"; 3 | -------------------------------------------------------------------------------- /typings/interface/index.d.ts: -------------------------------------------------------------------------------- 1 | export * from "./session"; 2 | export * from "./client"; 3 | -------------------------------------------------------------------------------- /dist/interface/client.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | -------------------------------------------------------------------------------- /dist/interface/native.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | -------------------------------------------------------------------------------- /dist/interface/payload.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | -------------------------------------------------------------------------------- /typings/lib/tlsClient.d.ts: -------------------------------------------------------------------------------- 1 | export declare function initTLS(): Promise; 2 | export declare function destroyTLS(): Promise; 3 | -------------------------------------------------------------------------------- /typings/utils/tlsError.d.ts: -------------------------------------------------------------------------------- 1 | export declare class TlsClientError extends Error { 2 | constructor(message: string | Error); 3 | } 4 | -------------------------------------------------------------------------------- /src/utils/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./download"; 2 | export * from "./logger"; 3 | export * from "./request"; 4 | export * from "./tlsError"; 5 | -------------------------------------------------------------------------------- /src/lib/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./Session"; 2 | export * from "./Response"; 3 | export * from "./requests"; 4 | export * from "./tlsClient"; 5 | -------------------------------------------------------------------------------- /typings/lib/index.d.ts: -------------------------------------------------------------------------------- 1 | export * from "./Session"; 2 | export * from "./Response"; 3 | export * from "./requests"; 4 | export * from "./tlsClient"; 5 | -------------------------------------------------------------------------------- /typings/utils/index.d.ts: -------------------------------------------------------------------------------- 1 | export * from "./download"; 2 | export * from "./logger"; 3 | export * from "./request"; 4 | export * from "./tlsError"; 5 | -------------------------------------------------------------------------------- /docs/.nojekyll: -------------------------------------------------------------------------------- 1 | TypeDoc added this file to prevent GitHub Pages from using Jekyll. You can turn off this behavior by setting the `githubPages` option to false. -------------------------------------------------------------------------------- /src/interface/client.ts: -------------------------------------------------------------------------------- 1 | import { KoffiFunction } from "koffi"; 2 | 3 | export interface IClient { 4 | request: KoffiFunction; 5 | freeMemory: KoffiFunction; 6 | destroyAll: KoffiFunction; 7 | destroySession: KoffiFunction; 8 | } 9 | -------------------------------------------------------------------------------- /typings/interface/client.d.ts: -------------------------------------------------------------------------------- 1 | import { KoffiFunction } from "koffi"; 2 | export interface IClient { 3 | request: KoffiFunction; 4 | freeMemory: KoffiFunction; 5 | destroyAll: KoffiFunction; 6 | destroySession: KoffiFunction; 7 | } 8 | -------------------------------------------------------------------------------- /src/lib/tlsClient.ts: -------------------------------------------------------------------------------- 1 | import { Client } from "./Client"; 2 | 3 | export async function initTLS(): Promise { 4 | return Client.init(); 5 | } 6 | 7 | export async function destroyTLS(): Promise { 8 | return Client.destroy(); 9 | } 10 | -------------------------------------------------------------------------------- /typings/workers/index.d.ts: -------------------------------------------------------------------------------- 1 | export declare function request(payload: string): any; 2 | export declare function destroySession(payload: string): any; 3 | export declare function destroyAll(): any; 4 | export declare function freeMemory(payload: string): any; 5 | export default request; 6 | -------------------------------------------------------------------------------- /dist/lib/tlsClient.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | exports.initTLS = initTLS; 4 | exports.destroyTLS = destroyTLS; 5 | const Client_1 = require("./Client"); 6 | async function initTLS() { 7 | return Client_1.Client.init(); 8 | } 9 | async function destroyTLS() { 10 | return Client_1.Client.destroy(); 11 | } 12 | -------------------------------------------------------------------------------- /typings/utils/native.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Loads and handles functionality related to shared library management. 3 | */ 4 | import { TlsNativeLibrary } from "../interface/native"; 5 | export declare class LibraryHandler { 6 | private static path; 7 | static validateFile(): Promise; 8 | static retrieveLibrary(): TlsNativeLibrary; 9 | private static retrieveFileInfo; 10 | } 11 | -------------------------------------------------------------------------------- /src/utils/tlsError.ts: -------------------------------------------------------------------------------- 1 | export class TlsClientError extends Error { 2 | constructor(message: string | Error) { 3 | super(message instanceof Error ? message.message : message); 4 | if (message instanceof Error && message.stack) { 5 | this.stack = message.stack; 6 | } 7 | this.name = "TlsClientError"; 8 | Object.setPrototypeOf(this, new.target.prototype); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2022", 4 | "experimentalDecorators": true, 5 | "emitDecoratorMetadata": true, 6 | "declaration": true, 7 | "outDir": "./dist", 8 | "declarationDir": "./typings", 9 | "esModuleInterop": true, 10 | "forceConsistentCasingInFileNames": true, 11 | "strict": true, 12 | "skipLibCheck": true, 13 | "module": "commonjs" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /typings/lib/Client.d.ts: -------------------------------------------------------------------------------- 1 | import { Piscina } from "piscina"; 2 | export declare class Client { 3 | private static instance; 4 | private static ready; 5 | private static readyPromise; 6 | private _pool; 7 | private constructor(); 8 | static init(): Promise; 9 | static destroy(): Promise; 10 | static getInstance(): Client; 11 | get pool(): Piscina; 12 | static isReady(): boolean; 13 | } 14 | -------------------------------------------------------------------------------- /typings/utils/download.d.ts: -------------------------------------------------------------------------------- 1 | import { FileInfo } from "../interface/native"; 2 | export declare class LibraryDownloader { 3 | private static file; 4 | private static path; 5 | private static readonly issueURL; 6 | static retrieveLibrary(file: FileInfo, libPath: string): Promise; 7 | private static formatBytes; 8 | private static progress; 9 | private static download; 10 | private static extract; 11 | private static getLatest; 12 | } 13 | -------------------------------------------------------------------------------- /src/interface/native.ts: -------------------------------------------------------------------------------- 1 | import { KoffiFunction } from "koffi"; 2 | 3 | export interface TlsNativeLibrary { 4 | request: KoffiFunction; 5 | freeMemory: KoffiFunction; 6 | destroyAll: KoffiFunction; 7 | destroySession: KoffiFunction; 8 | } 9 | 10 | type ArchMap = { 11 | [arch: string]: FileInfo; 12 | }; 13 | 14 | export type FileInfo = { 15 | name: string; 16 | downloadName: string; 17 | }; 18 | 19 | export type PlatformMap = { 20 | [platform: string]: ArchMap; 21 | }; 22 | -------------------------------------------------------------------------------- /typings/interface/native.d.ts: -------------------------------------------------------------------------------- 1 | import { KoffiFunction } from "koffi"; 2 | export interface TlsNativeLibrary { 3 | request: KoffiFunction; 4 | freeMemory: KoffiFunction; 5 | destroyAll: KoffiFunction; 6 | destroySession: KoffiFunction; 7 | } 8 | type ArchMap = { 9 | [arch: string]: FileInfo; 10 | }; 11 | export type FileInfo = { 12 | name: string; 13 | downloadName: string; 14 | }; 15 | export type PlatformMap = { 16 | [platform: string]: ArchMap; 17 | }; 18 | export {}; 19 | -------------------------------------------------------------------------------- /dist/utils/tlsError.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | exports.TlsClientError = void 0; 4 | class TlsClientError extends Error { 5 | constructor(message) { 6 | super(message instanceof Error ? message.message : message); 7 | if (message instanceof Error && message.stack) { 8 | this.stack = message.stack; 9 | } 10 | this.name = "TlsClientError"; 11 | Object.setPrototypeOf(this, new.target.prototype); 12 | } 13 | } 14 | exports.TlsClientError = TlsClientError; 15 | -------------------------------------------------------------------------------- /typings/utils/logger.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Logger utility. 3 | * 4 | * @property {Function} debug - Logs a debug message. 5 | * @property {Function} error - Logs an error message. 6 | * @property {Function} success - Logs a success message. 7 | * @property {Function} hyperlink - Generates a clickable hyperlink. 8 | */ 9 | export declare const logger: { 10 | debug: (...args: any[]) => boolean; 11 | error: (...args: any[]) => boolean; 12 | success: (...args: any[]) => boolean; 13 | hyperlink: (text: string, url: string) => string; 14 | stamp: string; 15 | }; 16 | -------------------------------------------------------------------------------- /typings/lib/requests.d.ts: -------------------------------------------------------------------------------- 1 | import { fetchOptions } from "../interface"; 2 | import { Response } from "."; 3 | /** 4 | * Makes an HTTP request using the specified URL and options. 5 | * 6 | * @param {string} url - The URL to make the request to. 7 | * @param {fetchOptions} [options] - Optional parameters for the request. 8 | * @returns {Promise} The response from the HTTP request. 9 | * @throws Will throw an error if the HTTP request fails or the method is not allowed. 10 | */ 11 | export declare function fetch(url: string, options?: fetchOptions): Promise; 12 | -------------------------------------------------------------------------------- /src/workers/index.ts: -------------------------------------------------------------------------------- 1 | import { LibraryHandler } from "../utils/native"; 2 | 3 | const instance = LibraryHandler.retrieveLibrary(); 4 | 5 | export function request(payload: string) { 6 | if (!payload) return; 7 | return instance.request(payload); 8 | } 9 | 10 | export function destroySession(payload: string) { 11 | if (!payload) return; 12 | return instance.destroySession(payload); 13 | } 14 | 15 | export function destroyAll() { 16 | return instance.destroyAll(); 17 | } 18 | 19 | export function freeMemory(payload: string) { 20 | if (!payload) return; 21 | return instance.freeMemory(payload); 22 | } 23 | 24 | export default request; 25 | -------------------------------------------------------------------------------- /docs/assets/navigation.js: -------------------------------------------------------------------------------- 1 | window.navigationData = "data:application/octet-stream;base64,H4sIAAAAAAAAA43Vy07DMBAF0H/xuiJQ8ewOingIEBVBbBALK5k2FokdZiaICvHvqG0gD6dTb3vvHCex5b5+K4YvVhM1zQ1Yvk3BspkbQDVSpeZMTRTYqqCon+9lXORqpN6NTdXk9Gf0Lz0Blc4SNEKSayKg6C/pzh6M29MxEBln/eE6kGYvNMETfFRA/FiycZYaxlgGnOsEKPJrXXR8dNxCLyEHDmGHihJ8DRygei2JvBnHwGzsYthqYhEBnQY8mF+T0NvN+RmU6kwar1cIeKzBpkTPNCdZADzQE1lHIdvr10QUjUPDyyvUBWwBO5UQbKZRF6K1bohUFfSu/ZZEBnjhWH13SFi3ImHPOflXXEtq5SKD2lLpUHzFfkkC58BJJmHtggRNAXnqihI3n+Q8X7jG42UJFA1UeuL+2cnB0bil3sEyzjTCtMLP9tndgN10l/UAnLnUQ+qfd03PCKrUre4vwEdM2/91G8cr7BLjqlxtEqSxWVjNFcLqi6DhrPAeUuoGr/MCSN197uF/hV1iCsTols/3cUPNK5usD0nUpF3n+LB/7oam14EwaKzhLQvXkTf89gsruzPWsQgAAA==" -------------------------------------------------------------------------------- /typings/utils/request.d.ts: -------------------------------------------------------------------------------- 1 | import { OutgoingHttpHeaders } from "http"; 2 | /** 3 | * Determines if a request should be treated as a byte request based on its headers. 4 | * 5 | * This function checks the "Content-Type", "Content-Transfer-Encoding" and "Content-Encoding" headers 6 | * to determine if the request is for binary data (such as images, audio, video, 7 | * application binaries, etc.). If the headers indicate binary data, it returns true. 8 | * 9 | * @param {OutgoingHttpHeaders} headers - The headers of the request. 10 | * @returns {boolean} - Returns true if the request is for binary data, otherwise false. 11 | */ 12 | export declare function isByteRequest(headers: OutgoingHttpHeaders): boolean; 13 | -------------------------------------------------------------------------------- /dist/workers/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | exports.request = request; 4 | exports.destroySession = destroySession; 5 | exports.destroyAll = destroyAll; 6 | exports.freeMemory = freeMemory; 7 | const native_1 = require("../utils/native"); 8 | const instance = native_1.LibraryHandler.retrieveLibrary(); 9 | function request(payload) { 10 | if (!payload) 11 | return; 12 | return instance.request(payload); 13 | } 14 | function destroySession(payload) { 15 | if (!payload) 16 | return; 17 | return instance.destroySession(payload); 18 | } 19 | function destroyAll() { 20 | return instance.destroyAll(); 21 | } 22 | function freeMemory(payload) { 23 | if (!payload) 24 | return; 25 | return instance.freeMemory(payload); 26 | } 27 | exports.default = request; 28 | -------------------------------------------------------------------------------- /typings/lib/Response.d.ts: -------------------------------------------------------------------------------- 1 | import { TlsResponse } from "../interface"; 2 | import { IncomingHttpHeaders } from "http"; 3 | export declare class Response { 4 | ok: boolean; 5 | headers: IncomingHttpHeaders; 6 | status: number; 7 | url: string; 8 | body: string; 9 | cookies: Record; 10 | constructor(response: TlsResponse); 11 | /** 12 | * Returns the body of the response as a string. 13 | * 14 | * @returns A promise that resolves with the body of the response as a string. 15 | */ 16 | text(): Promise; 17 | /** 18 | * Returns the body of the response as a JSON object. 19 | * 20 | * @typeparam T - The type of the JSON object. 21 | * @returns A promise that resolves with the body of the response as a JSON object. 22 | */ 23 | json(): Promise; 24 | } 25 | -------------------------------------------------------------------------------- /dist/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { 3 | if (k2 === undefined) k2 = k; 4 | var desc = Object.getOwnPropertyDescriptor(m, k); 5 | if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { 6 | desc = { enumerable: true, get: function() { return m[k]; } }; 7 | } 8 | Object.defineProperty(o, k2, desc); 9 | }) : (function(o, m, k, k2) { 10 | if (k2 === undefined) k2 = k; 11 | o[k2] = m[k]; 12 | })); 13 | var __exportStar = (this && this.__exportStar) || function(m, exports) { 14 | for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); 15 | }; 16 | Object.defineProperty(exports, "__esModule", { value: true }); 17 | __exportStar(require("./interface"), exports); 18 | __exportStar(require("./lib"), exports); 19 | -------------------------------------------------------------------------------- /dist/interface/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { 3 | if (k2 === undefined) k2 = k; 4 | var desc = Object.getOwnPropertyDescriptor(m, k); 5 | if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { 6 | desc = { enumerable: true, get: function() { return m[k]; } }; 7 | } 8 | Object.defineProperty(o, k2, desc); 9 | }) : (function(o, m, k, k2) { 10 | if (k2 === undefined) k2 = k; 11 | o[k2] = m[k]; 12 | })); 13 | var __exportStar = (this && this.__exportStar) || function(m, exports) { 14 | for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); 15 | }; 16 | Object.defineProperty(exports, "__esModule", { value: true }); 17 | __exportStar(require("./session"), exports); 18 | __exportStar(require("./client"), exports); 19 | -------------------------------------------------------------------------------- /examples/extra.js: -------------------------------------------------------------------------------- 1 | const { Session, ClientIdentifier, initTLS, destroyTLS } = require("node-tls-client"); 2 | 3 | (async () => { 4 | await initTLS(); 5 | 6 | const session = new Session({ 7 | clientIdentifier: ClientIdentifier.chrome_120, //client identifier 8 | timeout: 30 * 1000, //timeout in *milliseconds*, applies for each requests, checkout examples/timeout.js for using different timeouts. 9 | insecureSkipVerify: false, 10 | }); 11 | 12 | const response = await session.get("https://example.com", { 13 | proxy: `http://user:pass@ip:port`, //proxy format: http://user:pass@ip:port or http://ip:port 14 | cookies: { parameter: "value" }, //cookies 15 | followRedirects: true, //follow redirected urls 16 | headers: { authorization: "test" }, //request headers 17 | }); 18 | 19 | console.log(response.status); 20 | 21 | await session.close(); 22 | await destroyTLS(); 23 | })(); 24 | -------------------------------------------------------------------------------- /examples/simple.js: -------------------------------------------------------------------------------- 1 | const { 2 | Session, 3 | ClientIdentifier, 4 | initTLS, 5 | destroyTLS, 6 | } = require("node-tls-client"); 7 | 8 | /** 9 | * @description Demonstrates using the node-tls-client library to make HTTP requests with a specified timeout. 10 | * Note: The timeout is set per session and cannot be changed during the session. 11 | * 12 | * @see {@link https://sahil1337.github.io/node-tls-client/interfaces/SessionOptions.html SessionOptions} for more details. 13 | */ 14 | (async () => { 15 | await initTLS(); 16 | 17 | const session = new Session({ 18 | clientIdentifier: ClientIdentifier.chrome_103, 19 | timeout: 3000, 20 | }); 21 | 22 | try { 23 | const response = await session.get("https://website.com/"); 24 | 25 | console.log(response.status, await response.text()); 26 | } catch (error) { 27 | console.error("An error occurred:", error); 28 | } finally { 29 | await session.close(); 30 | await destroyTLS(); 31 | } 32 | })(); 33 | -------------------------------------------------------------------------------- /dist/utils/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { 3 | if (k2 === undefined) k2 = k; 4 | var desc = Object.getOwnPropertyDescriptor(m, k); 5 | if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { 6 | desc = { enumerable: true, get: function() { return m[k]; } }; 7 | } 8 | Object.defineProperty(o, k2, desc); 9 | }) : (function(o, m, k, k2) { 10 | if (k2 === undefined) k2 = k; 11 | o[k2] = m[k]; 12 | })); 13 | var __exportStar = (this && this.__exportStar) || function(m, exports) { 14 | for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); 15 | }; 16 | Object.defineProperty(exports, "__esModule", { value: true }); 17 | __exportStar(require("./download"), exports); 18 | __exportStar(require("./logger"), exports); 19 | __exportStar(require("./request"), exports); 20 | __exportStar(require("./tlsError"), exports); 21 | -------------------------------------------------------------------------------- /dist/lib/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { 3 | if (k2 === undefined) k2 = k; 4 | var desc = Object.getOwnPropertyDescriptor(m, k); 5 | if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { 6 | desc = { enumerable: true, get: function() { return m[k]; } }; 7 | } 8 | Object.defineProperty(o, k2, desc); 9 | }) : (function(o, m, k, k2) { 10 | if (k2 === undefined) k2 = k; 11 | o[k2] = m[k]; 12 | })); 13 | var __exportStar = (this && this.__exportStar) || function(m, exports) { 14 | for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); 15 | }; 16 | Object.defineProperty(exports, "__esModule", { value: true }); 17 | __exportStar(require("./Session"), exports); 18 | __exportStar(require("./Response"), exports); 19 | __exportStar(require("./requests"), exports); 20 | __exportStar(require("./tlsClient"), exports); 21 | -------------------------------------------------------------------------------- /examples/samples/executable.md: -------------------------------------------------------------------------------- 1 | # 🛠️ Building Executables with `node-tls-client` using `nexe` 2 | 3 | > [!WARNING] 4 | > Prebuilt binaries for Node.js **v20 and later are not available** in `nexe` or `pkg`. You must build from source using the `--build` flag. 5 | 6 | --- 7 | 8 | ### 🔧 Build Script (Linux, Node.js v20.0.0): 9 | ```bash 10 | nexe app.js -t linux-x64-20.0.0 --build 11 | ``` 12 | 13 | --- 14 | 15 | ### 🔍 Breakdown of Command 16 | 17 | | Flag | Description | 18 | |-----------------------|-------------------------------------------------------------| 19 | | `app.js` | Your Node.js entry script | 20 | | `-t linux-x64-20.0.0` | Target platform: Linux, 64-bit, Node.js v20.0.0 | 21 | | `--build` | Builds Node.js from source (required for v20+, no prebuilts)| 22 | 23 | --- 24 | 25 | > [!NOTE] 26 | > Replace the target triple if you're building for other platforms (e.g., `windows-x64-20.0.0`, `macos-x64-20.0.0`). -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "node-tls-client", 3 | "version": "2.1.0", 4 | "description": "Advanced library based on node-fetch and tls-client.", 5 | "main": "dist/index.js", 6 | "typings": "typings/index.d.ts", 7 | "repository": "https://github.com/Sahil1337/node-tls-client", 8 | "author": "Sahil1337", 9 | "license": "GPL-3.0", 10 | "private": false, 11 | "scripts": { 12 | "build": "tsc", 13 | "docs": "typedoc --out docs src/index.ts" 14 | }, 15 | "keywords": [ 16 | "tls-client", 17 | "node-tls-client", 18 | "javascript", 19 | "typescript", 20 | "tls client", 21 | "tls", 22 | "cloudflare" 23 | ], 24 | "devDependencies": { 25 | "@types/node": "^20.12.12", 26 | "@types/tough-cookie": "^4.0.5", 27 | "@types/cookie-parser": "^1.4.9", 28 | "typedoc": "^0.25.13", 29 | "typescript": "^5.4.5" 30 | }, 31 | "dependencies": { 32 | "cookie-parser": "^1.4.7", 33 | "koffi": "^2.8.9", 34 | "piscina": "^5.1.1", 35 | "tough-cookie": "^4.1.4" 36 | }, 37 | "files": [ 38 | "dist", 39 | "typings" 40 | ] 41 | } 42 | -------------------------------------------------------------------------------- /dist/utils/logger.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | exports.logger = void 0; 4 | const colors = { 5 | reset: "\x1b[0m", 6 | blue: "\x1b[34m", 7 | red: "\x1b[31m", 8 | green: "\x1b[32m", 9 | cyan: "\x1b[36m", 10 | }; 11 | /** 12 | * Logger utility. 13 | * 14 | * @property {Function} debug - Logs a debug message. 15 | * @property {Function} error - Logs an error message. 16 | * @property {Function} success - Logs a success message. 17 | * @property {Function} hyperlink - Generates a clickable hyperlink. 18 | */ 19 | exports.logger = { 20 | debug: function (...args) { 21 | return process.stdout.write(`${colors.cyan}@node-tls-client ~ ${colors.blue}DEBUG:${colors.reset} ${args.join(" ")}\n`); 22 | }, 23 | error: function (...args) { 24 | return process.stdout.write(`${colors.cyan}@node-tls-client ~ ${colors.red}ERROR:${colors.reset} ${args.join(" ")}\n`); 25 | }, 26 | success: function (...args) { 27 | return process.stdout.write(`${colors.cyan}@node-tls-client ~ ${colors.green}SUCCESS:${colors.reset} ${args.join(" ")}\n`); 28 | }, 29 | hyperlink: function (text, url) { 30 | return `\x1b]8;;${url}\x1b\\${text}\x1b]8;;\x1b\\`; 31 | }, 32 | stamp: `${colors.cyan}@node-tls-client ~${colors.reset}`, 33 | }; 34 | -------------------------------------------------------------------------------- /examples/images.js: -------------------------------------------------------------------------------- 1 | const { 2 | Session, 3 | ClientIdentifier, 4 | initTLS, 5 | destroyTLS, 6 | } = require("node-tls-client"); 7 | const fs = require("fs"); 8 | 9 | /** 10 | * @description Demonstrates a example for downloading images. 11 | * 12 | * @important 13 | * Ensure you specify `byteResponse: true` in the options to receive image data in base64 format. 14 | * This is necessary only for receiving image data, not for sending byte data in requests, which is handled internally. 15 | * 16 | * @see {@link https://sahil1337.github.io/node-tls-client/interfaces/SessionOptions.html SessionOptions} for more details. 17 | */ 18 | (async () => { 19 | await initTLS(); 20 | 21 | const session = new Session({ 22 | clientIdentifier: ClientIdentifier.chrome_103, 23 | }); 24 | 25 | const avatarURI = "https://avatars.githubusercontent.com/u/69236315?v=4"; 26 | 27 | try { 28 | const avatarRes = await session.get(avatarURI, { byteResponse: true }); 29 | 30 | const avatarResText = await avatarRes.text(); 31 | const avatarBase64 = avatarResText.replace(/^data:image\/\w+;base64,/, ""); 32 | 33 | fs.writeFileSync("avatar.png", avatarBase64, "base64"); 34 | } catch (error) { 35 | console.error("An error occurred:", error); 36 | } finally { 37 | await session.close(); 38 | await destroyTLS(); 39 | } 40 | })(); 41 | -------------------------------------------------------------------------------- /src/utils/logger.ts: -------------------------------------------------------------------------------- 1 | const colors = { 2 | reset: "\x1b[0m", 3 | blue: "\x1b[34m", 4 | red: "\x1b[31m", 5 | green: "\x1b[32m", 6 | cyan: "\x1b[36m", 7 | }; 8 | 9 | /** 10 | * Logger utility. 11 | * 12 | * @property {Function} debug - Logs a debug message. 13 | * @property {Function} error - Logs an error message. 14 | * @property {Function} success - Logs a success message. 15 | * @property {Function} hyperlink - Generates a clickable hyperlink. 16 | */ 17 | export const logger = { 18 | debug: function (...args: any[]) { 19 | return process.stdout.write( 20 | `${colors.cyan}@node-tls-client ~ ${colors.blue}DEBUG:${ 21 | colors.reset 22 | } ${args.join(" ")}\n` 23 | ); 24 | }, 25 | error: function (...args: any[]) { 26 | return process.stdout.write( 27 | `${colors.cyan}@node-tls-client ~ ${colors.red}ERROR:${ 28 | colors.reset 29 | } ${args.join(" ")}\n` 30 | ); 31 | }, 32 | success: function (...args: any[]) { 33 | return process.stdout.write( 34 | `${colors.cyan}@node-tls-client ~ ${colors.green}SUCCESS:${ 35 | colors.reset 36 | } ${args.join(" ")}\n` 37 | ); 38 | }, 39 | hyperlink: function (text: string, url: string) { 40 | return `\x1b]8;;${url}\x1b\\${text}\x1b]8;;\x1b\\`; 41 | }, 42 | stamp: `${colors.cyan}@node-tls-client ~${colors.reset}`, 43 | }; 44 | -------------------------------------------------------------------------------- /examples/timeout.js: -------------------------------------------------------------------------------- 1 | const { fetch, ClientIdentifier, initTLS, destroyTLS } = require("node-tls-client"); 2 | 3 | /** 4 | * @description Demonstrates using the node-tls-client library to make HTTP requests with different timeouts. 5 | * 6 | * The `fetch` method in the node-tls-client library creates a new session with the provided options 7 | * and closes the session after the request ends. As a result, session cookies and cache won't be 8 | * automatically cached across multiple requests. 9 | * 10 | * This example shows how to make two HTTP requests with different timeout settings. 11 | * Checkout docs for fetchOptions information. 12 | */ 13 | (async () => { 14 | await initTLS(); 15 | 16 | /** 17 | * @description Timeout cannot be changed during the session. 18 | */ 19 | const response1 = await fetch("https://example.com", { 20 | options: { timeout: 3000, clientIdentifier: ClientIdentifier.chrome_110 }, 21 | }); 22 | console.log("Response 1:", await response1.text()); 23 | 24 | // Making the second request with a 6000ms timeout and a specific client identifier 25 | const response2 = await fetch("https://example.com", { 26 | options: { timeout: 6000, clientIdentifier: ClientIdentifier.chrome_110 }, //options: SessionOptions 27 | }); 28 | console.log("Response 2:", await response2.text()); 29 | 30 | await destroyTLS(); 31 | })(); 32 | -------------------------------------------------------------------------------- /dist/lib/Response.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | exports.Response = void 0; 4 | class Response { 5 | // Indicates whether the response was successful (status in the range 200-299) or not. 6 | ok; 7 | // Represents the response headers. 8 | headers; 9 | // Represents the HTTP status code of the response. 10 | status; 11 | // Represents the URL of the response. 12 | url; 13 | // The response body 14 | body; 15 | // The cookies from the response 16 | cookies; 17 | constructor(response) { 18 | this.ok = response.status >= 200 && response.status < 300; 19 | this.headers = response.headers; 20 | this.status = response.status; 21 | this.url = response.target; 22 | this.body = response.body; 23 | this.cookies = response.cookies; 24 | } 25 | /** 26 | * Returns the body of the response as a string. 27 | * 28 | * @returns A promise that resolves with the body of the response as a string. 29 | */ 30 | async text() { 31 | return this.body; 32 | } 33 | /** 34 | * Returns the body of the response as a JSON object. 35 | * 36 | * @typeparam T - The type of the JSON object. 37 | * @returns A promise that resolves with the body of the response as a JSON object. 38 | */ 39 | async json() { 40 | return JSON.parse(this.body); 41 | } 42 | } 43 | exports.Response = Response; 44 | -------------------------------------------------------------------------------- /examples/samples/cookie-example.md: -------------------------------------------------------------------------------- 1 | # Example: session.cookies 2 | 3 | ## Retrieving all session cookies 4 | ```javascript 5 | await initTLS(); 6 | const session = new Session(); 7 | await session.get("http://localhost:3000/"); 8 | console.log(await session.cookies()); 9 | await destroyTLS(); 10 | ``` 11 | 12 | ## Cookies Response Example 13 | ```json 14 | [ 15 | { 16 | "key": "cookie1", 17 | "value": "value1", 18 | "domain": "localhost", 19 | "path": "/", 20 | "hostOnly": true, 21 | "pathIsDefault": true, 22 | "creation": "2025-06-20T19:30:28.478Z", 23 | "lastAccessed": "2025-06-20T19:30:28.478Z" 24 | }, 25 | { 26 | "key": "cookie2", 27 | "value": "value2", 28 | "domain": "localhost", 29 | "path": "/", 30 | "hostOnly": true, 31 | "pathIsDefault": true, 32 | "creation": "2025-06-20T19:30:28.480Z", 33 | "lastAccessed": "2025-06-20T19:30:28.480Z" 34 | }, 35 | { 36 | "key": "cookie3", 37 | "value": "value3", 38 | "domain": "localhost", 39 | "path": "/", 40 | "hostOnly": true, 41 | "pathIsDefault": true, 42 | "creation": "2025-06-20T19:30:28.480Z", 43 | "lastAccessed": "2025-06-20T19:30:28.480Z" 44 | }, 45 | { 46 | "key": "cookie4", 47 | "value": "value4", 48 | "domain": "localhost", 49 | "path": "/", 50 | "hostOnly": true, 51 | "pathIsDefault": true, 52 | "creation": "2025-06-20T19:30:28.480Z", 53 | "lastAccessed": "2025-06-20T19:30:28.480Z" 54 | } 55 | ] 56 | ``` 57 | -------------------------------------------------------------------------------- /src/lib/Response.ts: -------------------------------------------------------------------------------- 1 | import { TlsResponse } from "../interface"; 2 | import { IncomingHttpHeaders } from "http"; 3 | import { logger } from "../utils"; 4 | 5 | export class Response { 6 | // Indicates whether the response was successful (status in the range 200-299) or not. 7 | public ok: boolean; 8 | 9 | // Represents the response headers. 10 | public headers: IncomingHttpHeaders; 11 | 12 | // Represents the HTTP status code of the response. 13 | public status: number; 14 | 15 | // Represents the URL of the response. 16 | public url: string; 17 | 18 | // The response body 19 | public body: string; 20 | 21 | // The cookies from the response 22 | public cookies: Record; 23 | 24 | constructor(response: TlsResponse) { 25 | this.ok = response.status >= 200 && response.status < 300; 26 | this.headers = response.headers; 27 | this.status = response.status; 28 | this.url = response.target; 29 | this.body = response.body; 30 | this.cookies = response.cookies; 31 | } 32 | 33 | /** 34 | * Returns the body of the response as a string. 35 | * 36 | * @returns A promise that resolves with the body of the response as a string. 37 | */ 38 | public async text(): Promise { 39 | return this.body; 40 | } 41 | 42 | /** 43 | * Returns the body of the response as a JSON object. 44 | * 45 | * @typeparam T - The type of the JSON object. 46 | * @returns A promise that resolves with the body of the response as a JSON object. 47 | */ 48 | public async json(): Promise { 49 | return JSON.parse(this.body) as T; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /typings/lib/Cookie.d.ts: -------------------------------------------------------------------------------- 1 | import { CookieJar } from "tough-cookie"; 2 | export declare class Cookies extends CookieJar { 3 | constructor(); 4 | /** 5 | * Fetches all cookies and organizes them by URL. 6 | * 7 | * This method serializes cookies and groups them by their domain and path, 8 | * constructing a URL as the key and an object of cookies as key-value pairs. 9 | * 10 | * @returns A promise that resolves to an object where keys are URLs and values are objects containing cookies as key-value pairs. 11 | */ 12 | fetchAllCookies(): Promise; 13 | /** 14 | * Syncs cookies with the provided URL. 15 | * 16 | * @param cookies - An object containing cookies as key-value pairs. 17 | * @param url - The URL for which cookies are to be set. 18 | * @returns A promise that resolves to an object containing the synced cookies. 19 | */ 20 | syncCookies(cookies: Record, url: string): Promise>; 21 | /** 22 | * Merges the provided cookies with the existing cookies for a given URL according to request payload. 23 | * 24 | * @param cookies - An object containing cookies as key-value pairs. 25 | * @param url - The URL for which cookies are to be set. 26 | * @returns A promise that resolves to an array of objects, each containing the name and value of a cookie. 27 | * 28 | * @example 29 | * mergeCookies({ 'cookie1': 'value1', 'cookie2': 'value2' }, 'http://example.com') 30 | */ 31 | mergeCookies(cookies: Record, url: string): Promise<{ 32 | name: string; 33 | value: string; 34 | }[]>; 35 | } 36 | -------------------------------------------------------------------------------- /dist/lib/requests.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | exports.fetch = fetch; 4 | const _1 = require("."); 5 | const utils_1 = require("../utils"); 6 | /** 7 | * Makes an HTTP request using the specified URL and options. 8 | * 9 | * @param {string} url - The URL to make the request to. 10 | * @param {fetchOptions} [options] - Optional parameters for the request. 11 | * @returns {Promise} The response from the HTTP request. 12 | * @throws Will throw an error if the HTTP request fails or the method is not allowed. 13 | */ 14 | async function fetch(url, options) { 15 | const session = new _1.Session(options?.options); 16 | const method = options?.method?.toUpperCase() || "GET"; 17 | try { 18 | let response; 19 | switch (method) { 20 | case "GET": 21 | response = await session.get(url, options); 22 | break; 23 | case "POST": 24 | response = await session.post(url, options); 25 | break; 26 | case "PUT": 27 | response = await session.put(url, options); 28 | break; 29 | case "DELETE": 30 | response = await session.delete(url, options); 31 | break; 32 | case "HEAD": 33 | response = await session.head(url, options); 34 | break; 35 | case "OPTIONS": 36 | response = await session.options(url, options); 37 | break; 38 | case "PATCH": 39 | response = await session.patch(url, options); 40 | break; 41 | default: 42 | throw new Error(`HTTP method ${method} is not allowed.`); 43 | } 44 | return response; 45 | } 46 | catch (error) { 47 | throw new utils_1.TlsClientError(error); 48 | } 49 | finally { 50 | await session.close(); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/utils/request.ts: -------------------------------------------------------------------------------- 1 | import { OutgoingHttpHeaders } from "http"; 2 | 3 | const exactContentTypes = new Set([ 4 | "application/octet-stream", 5 | "application/pdf", 6 | "application/zip", 7 | "application/gzip", 8 | "application/x-rar-compressed", 9 | "application/x-msdownload", 10 | "application/x-sh", 11 | "application/x-binary", 12 | "base64", 13 | ]); 14 | 15 | const prefixContentTypes = new Set([ 16 | "image/", 17 | "audio/", 18 | "video/", 19 | "application/vnd.", 20 | ]); 21 | 22 | /** 23 | * Determines if a request should be treated as a byte request based on its headers. 24 | * 25 | * This function checks the "Content-Type", "Content-Transfer-Encoding" and "Content-Encoding" headers 26 | * to determine if the request is for binary data (such as images, audio, video, 27 | * application binaries, etc.). If the headers indicate binary data, it returns true. 28 | * 29 | * @param {OutgoingHttpHeaders} headers - The headers of the request. 30 | * @returns {boolean} - Returns true if the request is for binary data, otherwise false. 31 | */ 32 | export function isByteRequest(headers: OutgoingHttpHeaders): boolean { 33 | if (headers["content-encoding"] || headers["Content-Encoding"]) return true; 34 | 35 | const contentType = headers["content-type"] || headers["Content-Type"]; 36 | const contentTransferEncoding = 37 | headers["content-transfer-encoding"] || 38 | headers["Content-Transfer-Encoding"]; 39 | 40 | if (contentTransferEncoding) { 41 | const encodingString = String(contentTransferEncoding); 42 | if (exactContentTypes.has(encodingString)) { 43 | return true; 44 | } 45 | } 46 | 47 | if (contentType) { 48 | const contentTypeString = String(contentType); 49 | 50 | if (exactContentTypes.has(contentTypeString)) { 51 | return true; 52 | } 53 | 54 | for (const prefix of prefixContentTypes) { 55 | if (contentTypeString.startsWith(prefix)) { 56 | return true; 57 | } 58 | } 59 | } 60 | 61 | return false; 62 | } 63 | -------------------------------------------------------------------------------- /src/lib/Client.ts: -------------------------------------------------------------------------------- 1 | import { Piscina } from "piscina"; 2 | import { LibraryHandler } from "../utils/native"; 3 | import { TlsClientError } from "../utils"; 4 | import os from "os"; 5 | 6 | export class Client { 7 | private static instance: Client | null = null; 8 | private static ready = false; 9 | private static readyPromise: Promise | null = null; 10 | 11 | private _pool: Piscina; 12 | 13 | private constructor() { 14 | this._pool = new Piscina({ 15 | filename: require.resolve("../workers/index.js"), 16 | maxQueue: Infinity, 17 | maxThreads: 18 | (typeof os.availableParallelism === "function" 19 | ? os.availableParallelism() 20 | : os.cpus().length) * 2, 21 | atomics: "disabled", 22 | }); 23 | } 24 | 25 | public static async init(): Promise { 26 | if (Client.ready) return; 27 | 28 | if (!Client.readyPromise) { 29 | // Initialize ready promise 30 | Client.readyPromise = (async () => { 31 | await LibraryHandler.validateFile(); 32 | Client.instance = new Client(); 33 | Client.ready = true; 34 | Client.readyPromise = null; 35 | })(); 36 | } 37 | 38 | return Client.readyPromise; 39 | } 40 | 41 | public static async destroy(): Promise { 42 | if (!Client.instance) { 43 | throw new TlsClientError("Client not initialized. Call initTLS() first."); 44 | } 45 | // Clear sessions cache 46 | await Client.instance.pool.run({}, { name: "destroyAll" }); 47 | // Destroy worker pool 48 | await Client.instance.pool.close(); 49 | // Reset instance 50 | Client.instance = null; 51 | Client.ready = false; 52 | } 53 | 54 | public static getInstance(): Client { 55 | if (!Client.instance) { 56 | throw new TlsClientError("Client not initialized. Call initTLS() first."); 57 | } 58 | return Client.instance; 59 | } 60 | 61 | public get pool(): Piscina { 62 | return this._pool; 63 | } 64 | 65 | public static isReady(): boolean { 66 | return Client.ready; 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/interface/payload.ts: -------------------------------------------------------------------------------- 1 | import { OutgoingHttpHeaders } from "http2"; 2 | import { 3 | CertCompressionAlgo, 4 | H2Settings, 5 | KeyShareCurves, 6 | Methods, 7 | PriorityFrames, 8 | PriorityParam, 9 | PseudoHeaderOrder, 10 | SupportedSignatureAlgorithms, 11 | SupportedVersions, 12 | TransportOptions, 13 | } from "./session"; 14 | 15 | export interface Payload { 16 | catchPanics: boolean; 17 | customTlsClient?: CustomTlsClient; 18 | tlsClientIdentifier?: string; 19 | transportOptions?: TransportOptions; 20 | followRedirects: boolean; 21 | forceHttp1: boolean; 22 | headerOrder: OutgoingHttpHeaders[]; 23 | headers: OutgoingHttpHeaders; 24 | connectHeaders: Record; 25 | insecureSkipVerify: boolean; 26 | isByteRequest: boolean; 27 | isByteResponse: boolean; 28 | isRotatingProxy: boolean; 29 | proxyUrl: string; 30 | requestBody: string; 31 | requestCookies: { name: string; value: string }[]; 32 | requestHostOverride: string | null; 33 | requestMethod: Methods; 34 | requestUrl: string | URL; 35 | disableIPV6: boolean; 36 | disableIPV4: boolean; 37 | localAddress: string | null; 38 | sessionId: string; 39 | serverNameOverwrite?: string; 40 | streamOutputBlockSize?: number | null; 41 | streamOutputEOFSymbol?: string | null; 42 | streamOutputPath?: string | null; 43 | timeoutMilliseconds: number; 44 | withDebug: boolean; 45 | withDefaultCookieJar: boolean; 46 | withoutCookieJar: boolean; 47 | withRandomTLSExtensionOrder: boolean; 48 | } 49 | 50 | interface CustomTlsClient { 51 | ja3String: string; 52 | h2Settings: H2Settings; 53 | h2SettingsOrder: (keyof H2Settings)[]; 54 | pseudoHeaderOrder: PseudoHeaderOrder[]; 55 | connectionFlow: number; 56 | priorityFrames: PriorityFrames[]; 57 | headerPriority: PriorityParam; 58 | certCompressionAlgo: CertCompressionAlgo; 59 | supportedVersions: SupportedVersions[]; 60 | supportedSignatureAlgorithms: SupportedSignatureAlgorithms[]; 61 | keyShareCurves: KeyShareCurves[]; 62 | alpnProtocols: string[]; 63 | alpsProtocols: string[]; 64 | } 65 | -------------------------------------------------------------------------------- /dist/utils/request.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | exports.isByteRequest = isByteRequest; 4 | const exactContentTypes = new Set([ 5 | "application/octet-stream", 6 | "application/pdf", 7 | "application/zip", 8 | "application/gzip", 9 | "application/x-rar-compressed", 10 | "application/x-msdownload", 11 | "application/x-sh", 12 | "application/x-binary", 13 | "base64", 14 | ]); 15 | const prefixContentTypes = new Set([ 16 | "image/", 17 | "audio/", 18 | "video/", 19 | "application/vnd.", 20 | ]); 21 | /** 22 | * Determines if a request should be treated as a byte request based on its headers. 23 | * 24 | * This function checks the "Content-Type", "Content-Transfer-Encoding" and "Content-Encoding" headers 25 | * to determine if the request is for binary data (such as images, audio, video, 26 | * application binaries, etc.). If the headers indicate binary data, it returns true. 27 | * 28 | * @param {OutgoingHttpHeaders} headers - The headers of the request. 29 | * @returns {boolean} - Returns true if the request is for binary data, otherwise false. 30 | */ 31 | function isByteRequest(headers) { 32 | if (headers["content-encoding"] || headers["Content-Encoding"]) 33 | return true; 34 | const contentType = headers["content-type"] || headers["Content-Type"]; 35 | const contentTransferEncoding = headers["content-transfer-encoding"] || 36 | headers["Content-Transfer-Encoding"]; 37 | if (contentTransferEncoding) { 38 | const encodingString = String(contentTransferEncoding); 39 | if (exactContentTypes.has(encodingString)) { 40 | return true; 41 | } 42 | } 43 | if (contentType) { 44 | const contentTypeString = String(contentType); 45 | if (exactContentTypes.has(contentTypeString)) { 46 | return true; 47 | } 48 | for (const prefix of prefixContentTypes) { 49 | if (contentTypeString.startsWith(prefix)) { 50 | return true; 51 | } 52 | } 53 | } 54 | return false; 55 | } 56 | -------------------------------------------------------------------------------- /typings/interface/payload.d.ts: -------------------------------------------------------------------------------- 1 | import { OutgoingHttpHeaders } from "http2"; 2 | import { CertCompressionAlgo, H2Settings, KeyShareCurves, Methods, PriorityFrames, PriorityParam, PseudoHeaderOrder, SupportedSignatureAlgorithms, SupportedVersions, TransportOptions } from "./session"; 3 | export interface Payload { 4 | catchPanics: boolean; 5 | customTlsClient?: CustomTlsClient; 6 | tlsClientIdentifier?: string; 7 | transportOptions?: TransportOptions; 8 | followRedirects: boolean; 9 | forceHttp1: boolean; 10 | headerOrder: OutgoingHttpHeaders[]; 11 | headers: OutgoingHttpHeaders; 12 | connectHeaders: Record; 13 | insecureSkipVerify: boolean; 14 | isByteRequest: boolean; 15 | isByteResponse: boolean; 16 | isRotatingProxy: boolean; 17 | proxyUrl: string; 18 | requestBody: string; 19 | requestCookies: { 20 | name: string; 21 | value: string; 22 | }[]; 23 | requestHostOverride: string | null; 24 | requestMethod: Methods; 25 | requestUrl: string | URL; 26 | disableIPV6: boolean; 27 | disableIPV4: boolean; 28 | localAddress: string | null; 29 | sessionId: string; 30 | serverNameOverwrite?: string; 31 | streamOutputBlockSize?: number | null; 32 | streamOutputEOFSymbol?: string | null; 33 | streamOutputPath?: string | null; 34 | timeoutMilliseconds: number; 35 | withDebug: boolean; 36 | withDefaultCookieJar: boolean; 37 | withoutCookieJar: boolean; 38 | withRandomTLSExtensionOrder: boolean; 39 | } 40 | interface CustomTlsClient { 41 | ja3String: string; 42 | h2Settings: H2Settings; 43 | h2SettingsOrder: (keyof H2Settings)[]; 44 | pseudoHeaderOrder: PseudoHeaderOrder[]; 45 | connectionFlow: number; 46 | priorityFrames: PriorityFrames[]; 47 | headerPriority: PriorityParam; 48 | certCompressionAlgo: CertCompressionAlgo; 49 | supportedVersions: SupportedVersions[]; 50 | supportedSignatureAlgorithms: SupportedSignatureAlgorithms[]; 51 | keyShareCurves: KeyShareCurves[]; 52 | alpnProtocols: string[]; 53 | alpsProtocols: string[]; 54 | } 55 | export {}; 56 | -------------------------------------------------------------------------------- /src/lib/requests.ts: -------------------------------------------------------------------------------- 1 | import { 2 | DeleteRequestOptions, 3 | fetchOptions, 4 | GetRequestOptions, 5 | HeadRequestOptions, 6 | OptionsRequestOptions, 7 | PatchRequestOptions, 8 | PostRequestOptions, 9 | PutRequestOptions, 10 | SessionOptions, 11 | } from "../interface"; 12 | import { Response, Session } from "."; 13 | import { TlsClientError } from "../utils"; 14 | 15 | /** 16 | * Makes an HTTP request using the specified URL and options. 17 | * 18 | * @param {string} url - The URL to make the request to. 19 | * @param {fetchOptions} [options] - Optional parameters for the request. 20 | * @returns {Promise} The response from the HTTP request. 21 | * @throws Will throw an error if the HTTP request fails or the method is not allowed. 22 | */ 23 | export async function fetch( 24 | url: string, 25 | options?: fetchOptions 26 | ): Promise { 27 | const session = new Session(options?.options as SessionOptions); 28 | const method = options?.method?.toUpperCase() || "GET"; 29 | 30 | try { 31 | let response; 32 | 33 | switch (method) { 34 | case "GET": 35 | response = await session.get(url, options as GetRequestOptions); 36 | break; 37 | case "POST": 38 | response = await session.post(url, options as PostRequestOptions); 39 | break; 40 | case "PUT": 41 | response = await session.put(url, options as PutRequestOptions); 42 | break; 43 | case "DELETE": 44 | response = await session.delete(url, options as DeleteRequestOptions); 45 | break; 46 | case "HEAD": 47 | response = await session.head(url, options as HeadRequestOptions); 48 | break; 49 | case "OPTIONS": 50 | response = await session.options(url, options as OptionsRequestOptions); 51 | break; 52 | case "PATCH": 53 | response = await session.patch(url, options as PatchRequestOptions); 54 | break; 55 | default: 56 | throw new Error(`HTTP method ${method} is not allowed.`); 57 | } 58 | 59 | return response; 60 | } catch (error) { 61 | throw new TlsClientError(error as Error); 62 | } finally { 63 | await session.close(); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/lib/Cookie.ts: -------------------------------------------------------------------------------- 1 | import { CookieJar } from "tough-cookie"; 2 | 3 | export class Cookies extends CookieJar { 4 | constructor() { 5 | super(); 6 | } 7 | 8 | /** 9 | * Fetches all cookies and organizes them by URL. 10 | * 11 | * This method serializes cookies and groups them by their domain and path, 12 | * constructing a URL as the key and an object of cookies as key-value pairs. 13 | * 14 | * @returns A promise that resolves to an object where keys are URLs and values are objects containing cookies as key-value pairs. 15 | */ 16 | public async fetchAllCookies() { 17 | return (await this.serialize()).cookies; 18 | } 19 | 20 | /** 21 | * Syncs cookies with the provided URL. 22 | * 23 | * @param cookies - An object containing cookies as key-value pairs. 24 | * @param url - The URL for which cookies are to be set. 25 | * @returns A promise that resolves to an object containing the synced cookies. 26 | */ 27 | public async syncCookies( 28 | cookies: Record, 29 | url: string 30 | ): Promise> { 31 | if (!cookies) return {}; 32 | 33 | const result: Record = {}; 34 | 35 | await Promise.all( 36 | Object.entries(cookies).map(async ([key, value]) => { 37 | const cookie = await this.setCookie(`${key}=${value}`, url); 38 | result[cookie.key] = cookie.value; 39 | }) 40 | ); 41 | 42 | return result; 43 | } 44 | 45 | /** 46 | * Merges the provided cookies with the existing cookies for a given URL according to request payload. 47 | * 48 | * @param cookies - An object containing cookies as key-value pairs. 49 | * @param url - The URL for which cookies are to be set. 50 | * @returns A promise that resolves to an array of objects, each containing the name and value of a cookie. 51 | * 52 | * @example 53 | * mergeCookies({ 'cookie1': 'value1', 'cookie2': 'value2' }, 'http://example.com') 54 | */ 55 | public async mergeCookies(cookies: Record, url: string) { 56 | return Promise.all( 57 | Object.entries(cookies).map(async ([key, value]) => { 58 | const cookie = await this.setCookie(`${key}=${value}`, url); 59 | return { 60 | name: cookie.key, 61 | value: cookie.value, 62 | }; 63 | }) 64 | ); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /dist/lib/Client.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __importDefault = (this && this.__importDefault) || function (mod) { 3 | return (mod && mod.__esModule) ? mod : { "default": mod }; 4 | }; 5 | Object.defineProperty(exports, "__esModule", { value: true }); 6 | exports.Client = void 0; 7 | const piscina_1 = require("piscina"); 8 | const native_1 = require("../utils/native"); 9 | const utils_1 = require("../utils"); 10 | const os_1 = __importDefault(require("os")); 11 | class Client { 12 | static instance = null; 13 | static ready = false; 14 | static readyPromise = null; 15 | _pool; 16 | constructor() { 17 | this._pool = new piscina_1.Piscina({ 18 | filename: require.resolve("../workers/index.js"), 19 | maxQueue: Infinity, 20 | maxThreads: (typeof os_1.default.availableParallelism === "function" 21 | ? os_1.default.availableParallelism() 22 | : os_1.default.cpus().length) * 2, 23 | atomics: "disabled", 24 | }); 25 | } 26 | static async init() { 27 | if (Client.ready) 28 | return; 29 | if (!Client.readyPromise) { 30 | // Initialize ready promise 31 | Client.readyPromise = (async () => { 32 | await native_1.LibraryHandler.validateFile(); 33 | Client.instance = new Client(); 34 | Client.ready = true; 35 | Client.readyPromise = null; 36 | })(); 37 | } 38 | return Client.readyPromise; 39 | } 40 | static async destroy() { 41 | if (!Client.instance) { 42 | throw new utils_1.TlsClientError("Client not initialized. Call initTLS() first."); 43 | } 44 | // Clear sessions cache 45 | await Client.instance.pool.run({}, { name: "destroyAll" }); 46 | // Destroy worker pool 47 | await Client.instance.pool.close(); 48 | // Reset instance 49 | Client.instance = null; 50 | Client.ready = false; 51 | } 52 | static getInstance() { 53 | if (!Client.instance) { 54 | throw new utils_1.TlsClientError("Client not initialized. Call initTLS() first."); 55 | } 56 | return Client.instance; 57 | } 58 | get pool() { 59 | return this._pool; 60 | } 61 | static isReady() { 62 | return Client.ready; 63 | } 64 | } 65 | exports.Client = Client; 66 | -------------------------------------------------------------------------------- /dist/lib/Cookie.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | exports.Cookies = void 0; 4 | const tough_cookie_1 = require("tough-cookie"); 5 | class Cookies extends tough_cookie_1.CookieJar { 6 | constructor() { 7 | super(); 8 | } 9 | /** 10 | * Fetches all cookies and organizes them by URL. 11 | * 12 | * This method serializes cookies and groups them by their domain and path, 13 | * constructing a URL as the key and an object of cookies as key-value pairs. 14 | * 15 | * @returns A promise that resolves to an object where keys are URLs and values are objects containing cookies as key-value pairs. 16 | */ 17 | async fetchAllCookies() { 18 | return (await this.serialize()).cookies; 19 | } 20 | /** 21 | * Syncs cookies with the provided URL. 22 | * 23 | * @param cookies - An object containing cookies as key-value pairs. 24 | * @param url - The URL for which cookies are to be set. 25 | * @returns A promise that resolves to an object containing the synced cookies. 26 | */ 27 | async syncCookies(cookies, url) { 28 | if (!cookies) 29 | return {}; 30 | const result = {}; 31 | await Promise.all(Object.entries(cookies).map(async ([key, value]) => { 32 | const cookie = await this.setCookie(`${key}=${value}`, url); 33 | result[cookie.key] = cookie.value; 34 | })); 35 | return result; 36 | } 37 | /** 38 | * Merges the provided cookies with the existing cookies for a given URL according to request payload. 39 | * 40 | * @param cookies - An object containing cookies as key-value pairs. 41 | * @param url - The URL for which cookies are to be set. 42 | * @returns A promise that resolves to an array of objects, each containing the name and value of a cookie. 43 | * 44 | * @example 45 | * mergeCookies({ 'cookie1': 'value1', 'cookie2': 'value2' }, 'http://example.com') 46 | */ 47 | async mergeCookies(cookies, url) { 48 | return Promise.all(Object.entries(cookies).map(async ([key, value]) => { 49 | const cookie = await this.setCookie(`${key}=${value}`, url); 50 | return { 51 | name: cookie.key, 52 | value: cookie.value, 53 | }; 54 | })); 55 | } 56 | } 57 | exports.Cookies = Cookies; 58 | -------------------------------------------------------------------------------- /src/utils/native.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Loads and handles functionality related to shared library management. 3 | */ 4 | 5 | import path from "path"; 6 | import fs from "fs/promises"; 7 | import { PlatformMap, TlsNativeLibrary } from "../interface/native"; 8 | import os from "os"; 9 | import { load as koffi } from "koffi"; 10 | import { LibraryDownloader } from "./download"; 11 | 12 | export class LibraryHandler { 13 | private static path = path.join(os.tmpdir(), this.retrieveFileInfo().name); 14 | 15 | static async validateFile(): Promise { 16 | const fileExists = await fs 17 | .access(this.path) 18 | .then(() => true) 19 | .catch(() => false); 20 | 21 | if (!fileExists) { 22 | const isDownloaded = await LibraryDownloader.retrieveLibrary( 23 | LibraryHandler.retrieveFileInfo(), 24 | LibraryHandler.path 25 | ); 26 | 27 | if (!isDownloaded) return process.exit(1); 28 | } 29 | } 30 | 31 | static retrieveLibrary(): TlsNativeLibrary { 32 | const library = koffi(LibraryHandler.path); 33 | 34 | return { 35 | request: library.func("request", "string", ["string"]), 36 | freeMemory: library.func("freeMemory", "void", ["string"]), 37 | destroyAll: library.func("destroyAll", "string", []), 38 | destroySession: library.func("destroySession", "string", ["string"]), 39 | }; 40 | } 41 | 42 | private static retrieveFileInfo() { 43 | const platform = process.platform; 44 | const arch = process.arch; 45 | 46 | const map: PlatformMap = { 47 | darwin: { 48 | arm64: { 49 | name: "tls-client-arm64.dylib", 50 | downloadName: "tls-client-darwin-arm64-{version}.dylib", 51 | }, 52 | x64: { 53 | name: "tls-client-x86.dylib", 54 | downloadName: "tls-client-darwin-amd64-{version}.dylib", 55 | }, 56 | }, 57 | win32: { 58 | x64: { 59 | name: "tls-client-64.dll", 60 | downloadName: "tls-client-windows-64-{version}.dll", 61 | }, 62 | ia32: { 63 | name: "tls-client-32.dll", 64 | downloadName: "tls-client-windows-32-{version}.dll", 65 | }, 66 | }, 67 | linux: { 68 | arm64: { 69 | name: "tls-client-arm64.so", 70 | downloadName: "tls-client-linux-arm64-{version}.so", 71 | }, 72 | x64: { 73 | name: "tls-client-x64.so", 74 | downloadName: "tls-client-linux-ubuntu-amd64-{version}.so", 75 | }, 76 | default: { 77 | name: "tls-client-amd64.so", 78 | downloadName: "tls-client-linux-ubuntu-amd64-{version}.so", 79 | }, 80 | }, 81 | }; 82 | 83 | return map[platform]?.[arch] || map.linux.default; 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /docs/assets/highlight.css: -------------------------------------------------------------------------------- 1 | :root { 2 | --light-hl-0: #795E26; 3 | --dark-hl-0: #DCDCAA; 4 | --light-hl-1: #000000; 5 | --dark-hl-1: #D4D4D4; 6 | --light-hl-2: #A31515; 7 | --dark-hl-2: #CE9178; 8 | --light-hl-3: #008000; 9 | --dark-hl-3: #6A9955; 10 | --light-hl-4: #0000FF; 11 | --dark-hl-4: #569CD6; 12 | --light-hl-5: #0070C1; 13 | --dark-hl-5: #4FC1FF; 14 | --light-hl-6: #267F99; 15 | --dark-hl-6: #4EC9B0; 16 | --light-hl-7: #001080; 17 | --dark-hl-7: #9CDCFE; 18 | --light-hl-8: #AF00DB; 19 | --dark-hl-8: #C586C0; 20 | --light-hl-9: #098658; 21 | --dark-hl-9: #B5CEA8; 22 | --light-code-background: #FFFFFF; 23 | --dark-code-background: #1E1E1E; 24 | } 25 | 26 | @media (prefers-color-scheme: light) { :root { 27 | --hl-0: var(--light-hl-0); 28 | --hl-1: var(--light-hl-1); 29 | --hl-2: var(--light-hl-2); 30 | --hl-3: var(--light-hl-3); 31 | --hl-4: var(--light-hl-4); 32 | --hl-5: var(--light-hl-5); 33 | --hl-6: var(--light-hl-6); 34 | --hl-7: var(--light-hl-7); 35 | --hl-8: var(--light-hl-8); 36 | --hl-9: var(--light-hl-9); 37 | --code-background: var(--light-code-background); 38 | } } 39 | 40 | @media (prefers-color-scheme: dark) { :root { 41 | --hl-0: var(--dark-hl-0); 42 | --hl-1: var(--dark-hl-1); 43 | --hl-2: var(--dark-hl-2); 44 | --hl-3: var(--dark-hl-3); 45 | --hl-4: var(--dark-hl-4); 46 | --hl-5: var(--dark-hl-5); 47 | --hl-6: var(--dark-hl-6); 48 | --hl-7: var(--dark-hl-7); 49 | --hl-8: var(--dark-hl-8); 50 | --hl-9: var(--dark-hl-9); 51 | --code-background: var(--dark-code-background); 52 | } } 53 | 54 | :root[data-theme='light'] { 55 | --hl-0: var(--light-hl-0); 56 | --hl-1: var(--light-hl-1); 57 | --hl-2: var(--light-hl-2); 58 | --hl-3: var(--light-hl-3); 59 | --hl-4: var(--light-hl-4); 60 | --hl-5: var(--light-hl-5); 61 | --hl-6: var(--light-hl-6); 62 | --hl-7: var(--light-hl-7); 63 | --hl-8: var(--light-hl-8); 64 | --hl-9: var(--light-hl-9); 65 | --code-background: var(--light-code-background); 66 | } 67 | 68 | :root[data-theme='dark'] { 69 | --hl-0: var(--dark-hl-0); 70 | --hl-1: var(--dark-hl-1); 71 | --hl-2: var(--dark-hl-2); 72 | --hl-3: var(--dark-hl-3); 73 | --hl-4: var(--dark-hl-4); 74 | --hl-5: var(--dark-hl-5); 75 | --hl-6: var(--dark-hl-6); 76 | --hl-7: var(--dark-hl-7); 77 | --hl-8: var(--dark-hl-8); 78 | --hl-9: var(--dark-hl-9); 79 | --code-background: var(--dark-code-background); 80 | } 81 | 82 | .hl-0 { color: var(--hl-0); } 83 | .hl-1 { color: var(--hl-1); } 84 | .hl-2 { color: var(--hl-2); } 85 | .hl-3 { color: var(--hl-3); } 86 | .hl-4 { color: var(--hl-4); } 87 | .hl-5 { color: var(--hl-5); } 88 | .hl-6 { color: var(--hl-6); } 89 | .hl-7 { color: var(--hl-7); } 90 | .hl-8 { color: var(--hl-8); } 91 | .hl-9 { color: var(--hl-9); } 92 | pre, code { background: var(--code-background); } 93 | -------------------------------------------------------------------------------- /dist/utils/native.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | /** 3 | * Loads and handles functionality related to shared library management. 4 | */ 5 | var __importDefault = (this && this.__importDefault) || function (mod) { 6 | return (mod && mod.__esModule) ? mod : { "default": mod }; 7 | }; 8 | Object.defineProperty(exports, "__esModule", { value: true }); 9 | exports.LibraryHandler = void 0; 10 | const path_1 = __importDefault(require("path")); 11 | const promises_1 = __importDefault(require("fs/promises")); 12 | const os_1 = __importDefault(require("os")); 13 | const koffi_1 = require("koffi"); 14 | const download_1 = require("./download"); 15 | class LibraryHandler { 16 | static path = path_1.default.join(os_1.default.tmpdir(), this.retrieveFileInfo().name); 17 | static async validateFile() { 18 | const fileExists = await promises_1.default 19 | .access(this.path) 20 | .then(() => true) 21 | .catch(() => false); 22 | if (!fileExists) { 23 | const isDownloaded = await download_1.LibraryDownloader.retrieveLibrary(LibraryHandler.retrieveFileInfo(), LibraryHandler.path); 24 | if (!isDownloaded) 25 | return process.exit(1); 26 | } 27 | } 28 | static retrieveLibrary() { 29 | const library = (0, koffi_1.load)(LibraryHandler.path); 30 | return { 31 | request: library.func("request", "string", ["string"]), 32 | freeMemory: library.func("freeMemory", "void", ["string"]), 33 | destroyAll: library.func("destroyAll", "string", []), 34 | destroySession: library.func("destroySession", "string", ["string"]), 35 | }; 36 | } 37 | static retrieveFileInfo() { 38 | const platform = process.platform; 39 | const arch = process.arch; 40 | const map = { 41 | darwin: { 42 | arm64: { 43 | name: "tls-client-arm64.dylib", 44 | downloadName: "tls-client-darwin-arm64-{version}.dylib", 45 | }, 46 | x64: { 47 | name: "tls-client-x86.dylib", 48 | downloadName: "tls-client-darwin-amd64-{version}.dylib", 49 | }, 50 | }, 51 | win32: { 52 | x64: { 53 | name: "tls-client-64.dll", 54 | downloadName: "tls-client-windows-64-{version}.dll", 55 | }, 56 | ia32: { 57 | name: "tls-client-32.dll", 58 | downloadName: "tls-client-windows-32-{version}.dll", 59 | }, 60 | }, 61 | linux: { 62 | arm64: { 63 | name: "tls-client-arm64.so", 64 | downloadName: "tls-client-linux-arm64-{version}.so", 65 | }, 66 | x64: { 67 | name: "tls-client-x64.so", 68 | downloadName: "tls-client-linux-ubuntu-amd64-{version}.so", 69 | }, 70 | default: { 71 | name: "tls-client-amd64.so", 72 | downloadName: "tls-client-linux-ubuntu-amd64-{version}.so", 73 | }, 74 | }, 75 | }; 76 | return map[platform]?.[arch] || map.linux.default; 77 | } 78 | } 79 | exports.LibraryHandler = LibraryHandler; 80 | -------------------------------------------------------------------------------- /examples/advanced.js: -------------------------------------------------------------------------------- 1 | const { Session, initTLS, destroyTLS } = require("node-tls-client"); 2 | 3 | /** 4 | * @description Demonstrates an advanced usage scenario with the node-tls-client library, showcasing custom TLS client configuration. 5 | * 6 | * This example illustrates the creation of a TLS session with tailored settings and the execution of a GET request. 7 | * 8 | * Custom TLS settings encompass a wide array of configurations, including: 9 | * - JA3 string specification 10 | * - Fine-tuning HTTP/2 settings 11 | * - Defining supported signature algorithms 12 | * - Specifying ALPN (Application-Layer Protocol Negotiation) protocols 13 | * - Declaring supported TLS versions 14 | * - Setting key share curves for cryptographic key exchange 15 | * - Choosing a certificate compression algorithm 16 | * - Configuring connection and header flow parameters 17 | * - Defining the order of headers and priority frames 18 | * - Providing default headers for HTTP requests 19 | * 20 | * @see {@link https://sahil1337.github.io/node-tls-client/interfaces/SessionOptions.html SessionOptions} for more details on session options. 21 | */ 22 | 23 | (async () => { 24 | await initTLS(); 25 | 26 | const session = new Session({ 27 | ja3string: 28 | "771,2570-4865-4866-4867-49195-49199-49196-49200-52393-52392-49171-49172-156-157-47-53,2570-0-23-65281-10-11-35-16-5-13-18-51-45-43-27-17513-2570-21,2570-29-23-24,0", 29 | h2Settings: { 30 | HEADER_TABLE_SIZE: 65536, 31 | MAX_CONCURRENT_STREAMS: 1000, 32 | INITIAL_WINDOW_SIZE: 6291456, 33 | MAX_HEADER_LIST_SIZE: 262144, 34 | }, 35 | h2SettingsOrder: [ 36 | "HEADER_TABLE_SIZE", 37 | "MAX_CONCURRENT_STREAMS", 38 | "INITIAL_WINDOW_SIZE", 39 | "MAX_HEADER_LIST_SIZE", 40 | ], 41 | supportedSignatureAlgorithms: [ 42 | "ECDSAWithP256AndSHA256", 43 | "PSSWithSHA256", 44 | "PKCS1WithSHA256", 45 | "ECDSAWithP384AndSHA384", 46 | "PSSWithSHA384", 47 | "PKCS1WithSHA384", 48 | "PSSWithSHA512", 49 | "PKCS1WithSHA512", 50 | ], 51 | alpnProtocols: ["h2", "http/1.1"], 52 | alpsProtocols: ["h2"], 53 | supportedVersions: ["GREASE", "1.3", "1.2"], 54 | keyShareCurves: ["GREASE", "X25519"], 55 | certCompressionAlgo: "brotli", 56 | pseudoHeaderOrder: [":method", ":authority", ":scheme", ":path"], 57 | connectionFlow: 15663105, 58 | headerOrder: ["accept", "user-agent", "accept-encoding", "accept-language"], 59 | priorityFrames: [ 60 | { 61 | streamID: 1, 62 | priorityParam: { 63 | streamDep: 1, 64 | exclusive: true, 65 | weight: 1, 66 | }, 67 | }, 68 | ], 69 | headerPriority: { 70 | streamDep: 1, 71 | exclusive: true, 72 | weight: 1, 73 | }, 74 | headers: { 75 | accept: 76 | "application/json,text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9", 77 | "user-agent": 78 | "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Safari/537.36", 79 | "accept-encoding": "gzip, deflate, br", 80 | "accept-language": "de-DE,de;q=0.9,en-US;q=0.8,en;q=0.7", 81 | }, 82 | }); 83 | 84 | const response = await session.get("http://localhost:3000/"); 85 | console.log(response.status, await response.text()); 86 | await session.close(); 87 | 88 | await destroyTLS(); 89 | })(); 90 | -------------------------------------------------------------------------------- /typings/lib/Session.d.ts: -------------------------------------------------------------------------------- 1 | import { DeleteRequestOptions, GetRequestOptions, HeadRequestOptions, Methods, OptionsRequestOptions, PatchRequestOptions, PostRequestOptions, PutRequestOptions, RequestOptions, SessionOptions } from "../interface"; 2 | import { URL } from "url"; 3 | import { Response } from "./Response"; 4 | export declare class Session { 5 | private readonly config; 6 | private jar; 7 | private sessionId; 8 | constructor(config?: SessionOptions); 9 | cookies(): Promise; 10 | /** 11 | * The 'GET' method performs a GET request to the provided URL with the provided options. 12 | * 13 | * @param url - The URL to perform the GET request to. 14 | * @param options - The options for the GET request. 15 | * 16 | * @returns The response from the 'execute' method. 17 | */ 18 | get(url: string, options?: GetRequestOptions): Promise; 19 | /** 20 | * The 'DELETE' method performs a DELETE request to the provided URL with the provided options. 21 | * 22 | * @param url - The URL to perform the DELETE request to. 23 | * @param options - The options for the DELETE request. 24 | * 25 | * @returns The response from the 'execute' method. 26 | */ 27 | delete(url: string, options?: DeleteRequestOptions): Promise; 28 | /** 29 | * The 'OPTIONS' method performs an OPTIONS request to the provided URL with the provided options. 30 | * 31 | * @param url - The URL to perform the OPTIONS request to. 32 | * @param options - The options for the OPTIONS request. 33 | * 34 | * @returns The response from the 'execute' method. 35 | */ 36 | options(url: string, options?: OptionsRequestOptions): Promise; 37 | /** 38 | * The 'HEAD' method performs a HEAD request to the provided URL with the provided options. 39 | * 40 | * @param url - The URL to perform the HEAD request to. 41 | * @param options - The options for the HEAD request. 42 | * 43 | * @returns The response from the 'execute' method. 44 | */ 45 | head(url: string, options?: HeadRequestOptions): Promise; 46 | /** 47 | * The 'POST' method performs a POST request to the provided URL with the provided options. 48 | * 49 | * @param url - The URL to perform the POST request to. 50 | * @param options - The options for the POST request. 51 | * 52 | * @returns The response from the 'execute' method. 53 | */ 54 | post(url: string, options?: PostRequestOptions): Promise; 55 | /** 56 | * The 'PATCH' method performs a PATCH request to the provided URL with the provided options. 57 | * 58 | * @param url - The URL to perform the PATCH request to. 59 | * @param options - The options for the PATCH request. 60 | * 61 | * @returns The response from the 'execute' method. 62 | */ 63 | patch(url: string, options?: PatchRequestOptions): Promise; 64 | /** 65 | * The 'PUT' method performs a PUT request to the provided URL with the provided options. 66 | * 67 | * @param url - The URL to perform the PUT request to. 68 | * @param options - The options for the PUT request. 69 | * 70 | * @returns The response from the 'execute' method. 71 | */ 72 | put(url: string, options?: PutRequestOptions): Promise; 73 | /** 74 | * The 'close' method closes the current session. 75 | * 76 | * @returns The response from the 'destroySession' function. 77 | */ 78 | close(): Promise; 79 | protected execute(method: Methods, url: string | URL, options?: RequestOptions): Promise; 80 | private freeMemory; 81 | private getDefaultHeaders; 82 | } 83 | -------------------------------------------------------------------------------- /dist/interface/session.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | exports.ClientIdentifier = void 0; 4 | /** 5 | * Represents various client identifiers. 6 | * 7 | * The client identifiers are grouped by browser, mobile clients, and other clients. 8 | */ 9 | var ClientIdentifier; 10 | (function (ClientIdentifier) { 11 | // Chrome versions 12 | ClientIdentifier["chrome_103"] = "chrome_103"; 13 | ClientIdentifier["chrome_104"] = "chrome_104"; 14 | ClientIdentifier["chrome_105"] = "chrome_105"; 15 | ClientIdentifier["chrome_106"] = "chrome_106"; 16 | ClientIdentifier["chrome_107"] = "chrome_107"; 17 | ClientIdentifier["chrome_108"] = "chrome_108"; 18 | ClientIdentifier["chrome_109"] = "chrome_109"; 19 | ClientIdentifier["chrome_110"] = "chrome_110"; 20 | ClientIdentifier["chrome_111"] = "chrome_111"; 21 | ClientIdentifier["chrome_112"] = "chrome_112"; 22 | ClientIdentifier["chrome_116_PSK"] = "chrome_116_PSK"; 23 | ClientIdentifier["chrome_116_PSK_PQ"] = "chrome_116_PSK_PQ"; 24 | ClientIdentifier["chrome_117"] = "chrome_117"; 25 | ClientIdentifier["chrome_120"] = "chrome_120"; 26 | ClientIdentifier["chrome_124"] = "chrome_124"; 27 | ClientIdentifier["chrome_131"] = "chrome_131"; 28 | ClientIdentifier["chrome_131_psk"] = "chrome_131_PSK"; 29 | // Safari versions 30 | ClientIdentifier["safari_15_6_1"] = "safari_15_6_1"; 31 | ClientIdentifier["safari_16_0"] = "safari_16_0"; 32 | ClientIdentifier["safari_ipad_15_6"] = "safari_ipad_15_6"; 33 | ClientIdentifier["safari_ios_15_5"] = "safari_ios_15_5"; 34 | ClientIdentifier["safari_ios_15_6"] = "safari_ios_15_6"; 35 | ClientIdentifier["safari_ios_16_0"] = "safari_ios_16_0"; 36 | ClientIdentifier["safari_ios_17_0"] = "safari_ios_17_0"; 37 | ClientIdentifier["safari_ios_18_0"] = "safari_ios_18_0"; 38 | // Firefox versions 39 | ClientIdentifier["firefox_102"] = "firefox_102"; 40 | ClientIdentifier["firefox_104"] = "firefox_104"; 41 | ClientIdentifier["firefox_105"] = "firefox_105"; 42 | ClientIdentifier["firefox_106"] = "firefox_106"; 43 | ClientIdentifier["firefox_108"] = "firefox_108"; 44 | ClientIdentifier["firefox_110"] = "firefox_110"; 45 | ClientIdentifier["firefox_117"] = "firefox_117"; 46 | ClientIdentifier["firefox_120"] = "firefox_120"; 47 | ClientIdentifier["firefox_123"] = "firefox_123"; 48 | ClientIdentifier["firefox_132"] = "firefox_132"; 49 | ClientIdentifier["firefox_133"] = "firefox_133"; 50 | // Opera versions 51 | ClientIdentifier["opera_89"] = "opera_89"; 52 | ClientIdentifier["opera_90"] = "opera_90"; 53 | ClientIdentifier["opera_91"] = "opera_91"; 54 | // Zalando mobile clients 55 | ClientIdentifier["zalando_android_mobile"] = "zalando_android_mobile"; 56 | ClientIdentifier["zalando_ios_mobile"] = "zalando_ios_mobile"; 57 | // Nike mobile clients 58 | ClientIdentifier["nike_ios_mobile"] = "nike_ios_mobile"; 59 | ClientIdentifier["nike_android_mobile"] = "nike_android_mobile"; 60 | // Other clients 61 | ClientIdentifier["cloudscraper"] = "cloudscraper"; 62 | // MMS iOS versions 63 | ClientIdentifier["mms_ios"] = "mms_ios"; 64 | ClientIdentifier["mms_ios_1"] = "mms_ios_1"; 65 | ClientIdentifier["mms_ios_2"] = "mms_ios_2"; 66 | ClientIdentifier["mms_ios_3"] = "mms_ios_3"; 67 | // Mesh clients 68 | ClientIdentifier["mesh_ios"] = "mesh_ios"; 69 | ClientIdentifier["mesh_ios_1"] = "mesh_ios_1"; 70 | ClientIdentifier["mesh_ios_2"] = "mesh_ios_2"; 71 | ClientIdentifier["mesh_android"] = "mesh_android"; 72 | ClientIdentifier["mesh_android_1"] = "mesh_android_1"; 73 | ClientIdentifier["mesh_android_2"] = "mesh_android_2"; 74 | // Confirmed clients 75 | ClientIdentifier["confirmed_ios"] = "confirmed_ios"; 76 | ClientIdentifier["confirmed_android"] = "confirmed_android"; 77 | // OkHttp Android versions 78 | ClientIdentifier["okhttp4_android_7"] = "okhttp4_android_7"; 79 | ClientIdentifier["okhttp4_android_8"] = "okhttp4_android_8"; 80 | ClientIdentifier["okhttp4_android_9"] = "okhttp4_android_9"; 81 | ClientIdentifier["okhttp4_android_10"] = "okhttp4_android_10"; 82 | ClientIdentifier["okhttp4_android_11"] = "okhttp4_android_11"; 83 | ClientIdentifier["okhttp4_android_12"] = "okhttp4_android_12"; 84 | ClientIdentifier["okhttp4_android_13"] = "okhttp4_android_13"; 85 | })(ClientIdentifier || (exports.ClientIdentifier = ClientIdentifier = {})); 86 | -------------------------------------------------------------------------------- /docs/types/CertCompressionAlgo.html: -------------------------------------------------------------------------------- 1 | CertCompressionAlgo | node-tls-client

Type alias CertCompressionAlgo

CertCompressionAlgo: "zlib" | "brotli" | "zstd"

Represents various certificate compression algorithms.

2 |
-------------------------------------------------------------------------------- /docs/types/PseudoHeaderOrder.html: -------------------------------------------------------------------------------- 1 | PseudoHeaderOrder | node-tls-client

Type alias PseudoHeaderOrder

PseudoHeaderOrder: ":method" | ":authority" | ":scheme" | ":path"

Represents the order of pseudo headers in HTTP/2 requests.

2 |
-------------------------------------------------------------------------------- /docs/functions/initTLS.html: -------------------------------------------------------------------------------- 1 | initTLS | node-tls-client

Function initTLS

  • Returns Promise<void>

-------------------------------------------------------------------------------- /docs/types/SupportedVersions.html: -------------------------------------------------------------------------------- 1 | SupportedVersions | node-tls-client

Type alias SupportedVersions

SupportedVersions: "GREASE" | "1.3" | "1.2" | "1.1" | "1.0"

Represents various supported versions of TLS.

2 |
-------------------------------------------------------------------------------- /docs/functions/destroyTLS.html: -------------------------------------------------------------------------------- 1 | destroyTLS | node-tls-client

Function destroyTLS

  • Returns Promise<void>

-------------------------------------------------------------------------------- /docs/types/Methods.html: -------------------------------------------------------------------------------- 1 | Methods | node-tls-client

Type alias Methods

Methods: "GET" | "POST" | "PUT" | "DELETE" | "PATCH" | "OPTIONS" | "HEAD"

Represents various HTTP methods.

2 |
-------------------------------------------------------------------------------- /docs/types/KeyShareCurves.html: -------------------------------------------------------------------------------- 1 | KeyShareCurves | node-tls-client

Type alias KeyShareCurves

KeyShareCurves: "GREASE" | "P256" | "P384" | "P521" | "X25519" | "P256Kyber768" | "X25519Kyber512D" | "X25519Kyber768"

Represents various supported elliptic curves for key exchange.

2 |
-------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # 2.1.0 (June 21, 2025) 2 | > [!WARNING] 3 | > This version contains breaking changes. 4 | 5 | ### Breaking changes 6 | - **TLS Client Initialization Requirement** 7 | The new method `initTLS()` **must be called before** using any session methods. 8 | You must also call `destroyTLS()` when the session is no longer needed. 9 | - **Refactor Cookies API** 10 | `.cookies` is no longer a synchronous getter. 11 | It now returns a `Promise` that resolves to a cookie object. 12 | Usage: [session-cookies.md](https://github.com/Sahil1337/node-tls-client/tree/main/examples/samples/cookie-example.md) 13 | - **Redirect Handling Change** 14 | The `redirect` option in `requestOptions` is no longer supported. Use `followRedirects` instead. 15 | 16 | ### Additions/Fixes 17 | - **Node.js Compatibility Fix** 18 | The `process.clearLine()` bug has been resolved. Fixed issues [#2](https://github.com/Sahil1337/node-tls-client/issues/2) , [#3](https://github.com/Sahil1337/node-tls-client/issues/3) , [#6](https://github.com/Sahil1337/node-tls-client/issues/6) 19 | 20 | - **Shared Worker Pool (Performance Improvement)** 21 | A centralized shared worker pool has been introduced, leading to major performance gains across concurrent TLS sessions. 22 | 23 | Proof of concept: 24 | 25 | ![Performance Benchmark](https://media.discordapp.net/attachments/1358096526018220182/1358098103701340231/Node-Tls-Client-2025-04-05-151641.png?ex=68581e6c&is=6856ccec&hm=bbb07fe5910116c1f4f7f1f1f3b3d6a5e502e5788ea1bf0438cbf533ceb77b11&=&format=webp&quality=lossless&width=653&height=803) 26 | 27 | - **New: `transportOptions` in SessionOptions** 28 | Introduced `transportOptions` to customize low-level transport configuration. 29 | [Docs → transportOptions](https://sahil1337.github.io/node-tls-client/interfaces/SessionOptions.html#transportOptions) 30 | 31 | - **Additional Session Options Introduced** 32 | The following options provide extended control over stream output: 33 | - `serverNameOverwrite` 34 | - `streamOutputBlockSize` 35 | - `streamOutputEOFSymbol` 36 | - `streamOutputPath` 37 | [Docs → SessionOptions](https://sahil1337.github.io/node-tls-client/interfaces/SessionOptions) 38 | 39 | - **Enhanced Documentation** 40 | Executable compatibility instructions and examples have been added to the documentation. [Instructions](https://github.com/Sahil1337/node-tls-client/tree/main/examples/samples/executable.md) 41 | 42 | - **Refactor byteRequest handling** 43 | Taking into account the `Content-Encoding` and `Content-Transfer-Encoding` headers to determine if the response is a byte response. [Accounting for pull request #8](https://github.com/Sahil1337/node-tls-client/pull/8) 44 | 45 | # 2.0.0 (December 15, 2024) 46 | > [!WARNING] 47 | > This version contains breaking changes. 48 | - Call `.init()` after setting up a session and before using any HTTP methods. (See the documentation for more details.) 49 | - Resolved memory leak issues by moving to workerpool. 50 | - Added new profiles: `chrome_131`, `chrome_131_psk`, `firefox_132`, `firefox_133`, and `ios_safari_18`. The default profile is now `chrome_131` (previously `chrome_124`). 51 | - Introduced the `isRotatingProxy` option for handling rotating proxies. PS: [SessionOptions](https://sahil1337.github.io/node-tls-client/interfaces/SessionOptions.html) 52 | 53 | # 1.1.4 (July 29, 2024) 54 | > [!IMPORTANT] 55 | > This version includes significant updates and improvements. 56 | 57 | ### Breaking changes 58 | - `response.cookies` is now a property instead of a method. [Note: `response.cookies()` has been removed and replaced with `response.cookies`.] 59 | 60 | ### Additional updates 61 | - Added `session.cookies` property to retrieve all session cookies. For detailed information, see [examples/session-cookies.md](https://github.com/Sahil1337/node-tls-client/tree/main/examples/samples/cookie-example.md). 62 | - Added `byteResponse` option in requestOptions. Setting this to true ensures that the response is treated as a byte response. For detailed information, see [examples/images.js](https://github.com/Sahil1337/node-tls-client/tree/main/examples/images.js) 63 | - Added functionality to send binary data. Note: Ensure that the appropriate headers are set before sending binary data in the body. 64 | - Added `disableIPV6` and `disableIPV4` options in `SessionOptions`. For detailed information, see [SessionOptions](https://sahil1337.github.io/node-tls-client/interfaces/SessionOptions.html#disableIPV4) 65 | - Added `hostOverride` property in requestOptions. Used to override the Host header, typically needed when making requests directly to an IP address. 66 | - `chrome_124` profile will be used when no `client_identifier` is specified in session options. 67 | - Refactored cookies.ts and session typings for improved readability (internal change, no impact on existing use cases) 68 | - Updated TlsResponse according to new changes. 69 | 70 | # 1.1.3 (June 13, 2024) 71 | > [!WARNING] 72 | > This version contains breaking changes. 73 | 74 | ### Breaking changes 75 | - `response.json()` and `response.text()` methods now return a `Promise`. 76 | - `response.cookies()` now returns an object of cookies instead of a`Promise`. 77 | - `session.methods` no longer include the `timeout` and `rejectUnauthorized` options. Since timeout cannot be changed during a session, ensure to specify `timeout` & `rejectUnauthorized` in SessionOptions when creating a session. 78 | 79 | ### Additions 80 | - `fetch(fetchOptions)` method have been added to use different timeouts & rejectUnauthorized values in each request. [examples/timeout.js] for more information. 81 | 82 | ### Fixes 83 | - Fixed a typo that prevented timeout from working correctly. 84 | 85 | # 1.1.2 (June 9, 2024) 86 | ### Additions 87 | - Introduced client profile types. 88 | ### Changes 89 | - Enhanced documentation for improved clarity and usability. 90 | - Updated the README with minor adjustments. 91 | - Refined interface definitions for better readability and understanding. 92 | 93 | # 1.1.1 (June 4 2024) 94 | ### Additions 95 | - Implemented dynamic methods for downloading shared files in "node-tls-client", eliminating the inclusion of prebuilt files. 96 | ### Changes 97 | - Path used for storing the shared library files is strictly set to tmpdir path. 98 | ### Benefits 99 | - Reduces package size. 100 | - Ensures better support for executables. 101 | 102 | # 1.1.0 (June 3, 2024) 103 | ### Changes 104 | - Improved handling of shared library files: 105 | - Only the shared library file matching the current operating system is preserved. All other shared library files are deleted. 106 | - Added support for executables. 107 | -------------------------------------------------------------------------------- /src/utils/download.ts: -------------------------------------------------------------------------------- 1 | import { logger } from "./logger"; 2 | import https from "https"; 3 | import fs, { WriteStream, createWriteStream } from "fs"; 4 | import { IncomingMessage } from "http"; 5 | import { FileInfo } from "../interface/native"; 6 | import * as readline from "readline"; 7 | 8 | export class LibraryDownloader { 9 | private static file: FileInfo; 10 | private static path: string; 11 | 12 | private static readonly issueURL = 13 | "https://github.com/Sahil1337/node-tls-client/issues"; 14 | 15 | static async retrieveLibrary( 16 | file: FileInfo, 17 | libPath: string 18 | ): Promise { 19 | this.file = file; 20 | this.path = libPath; 21 | 22 | try { 23 | const latest = await this.getLatest(); 24 | if (latest) { 25 | await this.extract(latest.browser_download_url); 26 | logger.success("Extracted shared library."); 27 | return true; 28 | } else { 29 | logger.error( 30 | `Failed to find required asset: ${ 31 | this.file.name 32 | }, report ${logger.hyperlink("here", this.issueURL)}.` 33 | ); 34 | return false; 35 | } 36 | } catch (error) { 37 | logger.error(`Initialization failed: ${error}`); 38 | return false; 39 | } 40 | } 41 | 42 | private static formatBytes(bytes: number, decimals = 2): string { 43 | if (bytes === 0) return "0 Bytes"; 44 | const k = 1024; 45 | const dm = decimals < 0 ? 0 : decimals; 46 | const sizes = ["Bytes", "KB", "MB", "GB", "TB"]; 47 | const i = Math.floor(Math.log(bytes) / Math.log(k)); 48 | return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + " " + sizes[i]; 49 | } 50 | 51 | private static progress(downloaded: number, total: number) { 52 | const percentage = (downloaded / total) * 100; 53 | const progress = Math.floor(percentage / 2); 54 | const bar = "█".repeat(progress) + " ".repeat(50 - progress); 55 | readline.clearLine(process.stdout, 0); 56 | readline.cursorTo(process.stdout, 0); 57 | process.stdout.write( 58 | `${logger.stamp} DOWNLOADING:[${bar}] ${percentage.toFixed( 59 | 2 60 | )}% (${this.formatBytes(downloaded)} / ${this.formatBytes(total)})` 61 | ); 62 | } 63 | 64 | private static async download(url: string, file: WriteStream): Promise { 65 | return new Promise((resolve, reject) => { 66 | https 67 | .get(url, (response: IncomingMessage) => { 68 | if ( 69 | response.statusCode && 70 | response.statusCode >= 300 && 71 | response.statusCode < 400 && 72 | response.headers.location 73 | ) { 74 | const newURL = new URL(response.headers.location, url).toString(); 75 | logger.debug( 76 | `Fetched shared library ${logger.hyperlink("url", newURL)}` 77 | ); 78 | this.download(newURL, file).then(resolve).catch(reject); 79 | } else if ( 80 | response.statusCode && 81 | response.statusCode >= 200 && 82 | response.statusCode < 300 83 | ) { 84 | const totalBytes = parseInt( 85 | response.headers["content-length"] || "0", 86 | 10 87 | ); 88 | let downloadedBytes = 0; 89 | 90 | response.pipe(file); 91 | 92 | response.on("data", (chunk) => { 93 | downloadedBytes += chunk.length; 94 | this.progress(downloadedBytes, totalBytes); 95 | }); 96 | 97 | response.on("end", () => { 98 | file.close((err) => { 99 | if (err) { 100 | reject(err); 101 | } else { 102 | process.stdout.write("\n"); 103 | resolve(); 104 | } 105 | }); 106 | }); 107 | 108 | file.on("error", (err) => { 109 | fs.unlink(this.path, () => reject(err)); 110 | }); 111 | } else { 112 | logger.error( 113 | `Failed to download the file [statusCode:${response.statusCode}]` 114 | ); 115 | reject(); 116 | } 117 | }) 118 | .on("error", (err) => { 119 | fs.unlink(this.path, () => reject(err)); 120 | }); 121 | }); 122 | } 123 | 124 | private static async extract(url: string): Promise { 125 | return new Promise((resolve, reject) => { 126 | const file = createWriteStream(this.path); 127 | this.download(url, file).then(resolve).catch(reject); 128 | }); 129 | } 130 | 131 | private static async getLatest(): Promise { 132 | return new Promise((resolve) => { 133 | const options = { 134 | hostname: "api.github.com", 135 | path: "/repos/bogdanfinn/tls-client/releases/latest", 136 | method: "GET", 137 | headers: { 138 | "user-agent": "node-tls-client", 139 | }, 140 | }; 141 | 142 | https 143 | .get(options, (res: IncomingMessage) => { 144 | let data = ""; 145 | 146 | res.on("data", (chunk) => { 147 | data += chunk; 148 | }); 149 | 150 | res.on("end", () => { 151 | if (res.statusCode === 200) { 152 | try { 153 | const response = JSON.parse(data); 154 | const version = response.tag_name.replace("v", ""); 155 | logger.debug(`Fetched latest version: v${version}`); 156 | 157 | const assetName = this.file.downloadName.replace( 158 | "{version}", 159 | version 160 | ); 161 | const asset = response.assets.find( 162 | (asset: { name: string }) => asset.name === assetName 163 | ); 164 | 165 | if (!asset) { 166 | logger.error( 167 | `Failed to find required asset: ${ 168 | this.file.name 169 | }, report ${logger.hyperlink("here", this.issueURL)}.` 170 | ); 171 | resolve(null); 172 | } else { 173 | resolve(asset); 174 | } 175 | } catch (err) { 176 | logger.error(`Failed to parse response: ${err}`); 177 | resolve(null); 178 | } 179 | } else { 180 | logger.error( 181 | `Failed to fetch the latest version. Status code: ${res.statusCode}` 182 | ); 183 | resolve(null); 184 | } 185 | }); 186 | }) 187 | .on("error", (err) => { 188 | logger.error(`Failed to fetch the latest version: ${err}`); 189 | resolve(null); 190 | }); 191 | }); 192 | } 193 | } 194 | -------------------------------------------------------------------------------- /docs/types/SupportedSignatureAlgorithms.html: -------------------------------------------------------------------------------- 1 | SupportedSignatureAlgorithms | node-tls-client

Type alias SupportedSignatureAlgorithms

SupportedSignatureAlgorithms: "PKCS1WithSHA256" | "PKCS1WithSHA384" | "PKCS1WithSHA512" | "PSSWithSHA256" | "PSSWithSHA384" | "PSSWithSHA512" | "ECDSAWithP256AndSHA256" | "ECDSAWithP384AndSHA384" | "ECDSAWithP521AndSHA512" | "PKCS1WithSHA1" | "ECDSAWithSHA1" | "Ed25519"

Represents various supported signature algorithms for TLS.

2 |
-------------------------------------------------------------------------------- /docs/hierarchy.html: -------------------------------------------------------------------------------- 1 | node-tls-client
-------------------------------------------------------------------------------- /docs/functions/fetch.html: -------------------------------------------------------------------------------- 1 | fetch | node-tls-client

Function fetch

  • Makes an HTTP request using the specified URL and options.

    2 |

    Parameters

    • url: string

      The URL to make the request to.

      3 |
    • Optional options: fetchOptions

      Optional parameters for the request.

      4 |

    Returns Promise<Response>

    The response from the HTTP request.

    5 |

    Throws

    Will throw an error if the HTTP request fails or the method is not allowed.

    6 |
-------------------------------------------------------------------------------- /dist/lib/Session.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | exports.Session = void 0; 4 | const crypto_1 = require("crypto"); 5 | const Cookie_1 = require("./Cookie"); 6 | const interface_1 = require("../interface"); 7 | const utils_1 = require("../utils"); 8 | const Client_1 = require("./Client"); 9 | const Response_1 = require("./Response"); 10 | const __version__ = "2.1.0"; 11 | class Session { 12 | config; 13 | jar = new Cookie_1.Cookies(); 14 | sessionId = (0, crypto_1.randomUUID)(); 15 | constructor(config = {}) { 16 | this.config = config; 17 | } 18 | async cookies() { 19 | return this.jar.fetchAllCookies(); 20 | } 21 | /** 22 | * The 'GET' method performs a GET request to the provided URL with the provided options. 23 | * 24 | * @param url - The URL to perform the GET request to. 25 | * @param options - The options for the GET request. 26 | * 27 | * @returns The response from the 'execute' method. 28 | */ 29 | get(url, options = {}) { 30 | return this.execute("GET", url, options); 31 | } 32 | /** 33 | * The 'DELETE' method performs a DELETE request to the provided URL with the provided options. 34 | * 35 | * @param url - The URL to perform the DELETE request to. 36 | * @param options - The options for the DELETE request. 37 | * 38 | * @returns The response from the 'execute' method. 39 | */ 40 | delete(url, options = {}) { 41 | return this.execute("DELETE", url, options); 42 | } 43 | /** 44 | * The 'OPTIONS' method performs an OPTIONS request to the provided URL with the provided options. 45 | * 46 | * @param url - The URL to perform the OPTIONS request to. 47 | * @param options - The options for the OPTIONS request. 48 | * 49 | * @returns The response from the 'execute' method. 50 | */ 51 | options(url, options = {}) { 52 | return this.execute("OPTIONS", url, options); 53 | } 54 | /** 55 | * The 'HEAD' method performs a HEAD request to the provided URL with the provided options. 56 | * 57 | * @param url - The URL to perform the HEAD request to. 58 | * @param options - The options for the HEAD request. 59 | * 60 | * @returns The response from the 'execute' method. 61 | */ 62 | head(url, options = {}) { 63 | return this.execute("HEAD", url, options); 64 | } 65 | /** 66 | * The 'POST' method performs a POST request to the provided URL with the provided options. 67 | * 68 | * @param url - The URL to perform the POST request to. 69 | * @param options - The options for the POST request. 70 | * 71 | * @returns The response from the 'execute' method. 72 | */ 73 | post(url, options = {}) { 74 | return this.execute("POST", url, options); 75 | } 76 | /** 77 | * The 'PATCH' method performs a PATCH request to the provided URL with the provided options. 78 | * 79 | * @param url - The URL to perform the PATCH request to. 80 | * @param options - The options for the PATCH request. 81 | * 82 | * @returns The response from the 'execute' method. 83 | */ 84 | patch(url, options = {}) { 85 | return this.execute("PATCH", url, options); 86 | } 87 | /** 88 | * The 'PUT' method performs a PUT request to the provided URL with the provided options. 89 | * 90 | * @param url - The URL to perform the PUT request to. 91 | * @param options - The options for the PUT request. 92 | * 93 | * @returns The response from the 'execute' method. 94 | */ 95 | put(url, options = {}) { 96 | return this.execute("PUT", url, options); 97 | } 98 | /** 99 | * The 'close' method closes the current session. 100 | * 101 | * @returns The response from the 'destroySession' function. 102 | */ 103 | async close() { 104 | return Client_1.Client.getInstance().pool?.run(JSON.stringify({ 105 | sessionId: this.sessionId, 106 | }), { name: "destroySession" }); 107 | } 108 | async execute(method, url, options = {}) { 109 | const headers = options?.headers !== undefined 110 | ? options.headers 111 | : this.config.headers ?? this.getDefaultHeaders(); 112 | const requestCookies = await this.jar.mergeCookies(options?.cookies || {}, url.toString()); 113 | const payload = { 114 | sessionId: this.sessionId, 115 | followRedirects: options.followRedirects ?? false, 116 | forceHttp1: this.config.forceHttp1 ?? false, 117 | withDebug: this.config.debug ?? false, 118 | headers, 119 | headerOrder: options.headerOrder || this.config.headerOrder || [], 120 | insecureSkipVerify: this.config.insecureSkipVerify ?? false, 121 | proxyUrl: options.proxy || this.config.proxy || "", 122 | isRotatingProxy: options?.isRotatingProxy ?? this.config.isRotatingProxy ?? false, 123 | requestUrl: url, 124 | requestMethod: method, 125 | requestBody: options?.body || null, 126 | timeoutMilliseconds: this.config.timeout || 0, 127 | withRandomTLSExtensionOrder: this.config.randomTlsExtensionOrder ?? false, 128 | isByteResponse: options?.byteResponse ?? false, 129 | isByteRequest: (0, utils_1.isByteRequest)(headers), 130 | requestHostOverride: options?.hostOverride || null, 131 | disableIPV6: this.config.disableIPV6 ?? false, 132 | disableIPV4: this.config.disableIPV4 ?? false, 133 | transportOptions: this.config.transportOptions ?? undefined, 134 | catchPanics: false, 135 | streamOutputEOFSymbol: this.config.streamOutputEOFSymbol ?? null, 136 | streamOutputPath: this.config.streamOutputPath ?? null, 137 | streamOutputBlockSize: this.config.streamOutputBlockSize ?? null, 138 | serverNameOverwrite: this.config.serverNameOverwrite ?? "", 139 | connectHeaders: this.config.connectHeaders ?? options.connectHeaders ?? {}, 140 | localAddress: this.config.localAddress ?? null, 141 | withDefaultCookieJar: true, 142 | withoutCookieJar: false, 143 | requestCookies, 144 | }; 145 | if (this.config.clientIdentifier) { 146 | payload["tlsClientIdentifier"] = this.config.clientIdentifier; 147 | } 148 | else if (this.config.ja3string) { 149 | payload["customTlsClient"] = { 150 | ja3String: this.config.ja3string, 151 | h2Settings: this.config.h2Settings ?? {}, 152 | h2SettingsOrder: this.config.h2SettingsOrder ?? [], 153 | pseudoHeaderOrder: this.config.pseudoHeaderOrder ?? [], 154 | connectionFlow: this.config.connectionFlow ?? 0, 155 | priorityFrames: this.config.priorityFrames ?? [], 156 | headerPriority: this.config.headerPriority ?? { 157 | streamDep: 0, 158 | exclusive: false, 159 | weight: 0, 160 | }, 161 | certCompressionAlgo: this.config.certCompressionAlgo ?? "zlib", 162 | supportedVersions: this.config.supportedVersions ?? [], 163 | supportedSignatureAlgorithms: this.config.supportedSignatureAlgorithms ?? [], 164 | keyShareCurves: this.config.keyShareCurves ?? [], 165 | alpnProtocols: this.config.alpnProtocols ?? [], 166 | alpsProtocols: this.config.alpsProtocols ?? [], 167 | }; 168 | } 169 | else 170 | payload["tlsClientIdentifier"] = interface_1.ClientIdentifier.chrome_131; 171 | const requestPayloadString = JSON.stringify(payload); 172 | const rawResponse = await Client_1.Client.getInstance().pool.run(requestPayloadString, { 173 | name: "request", 174 | }); 175 | const response = JSON.parse(rawResponse); 176 | const cookies = await this.jar.syncCookies(response.cookies || {}, url.toString()); 177 | setImmediate(() => { 178 | this.freeMemory(response.id).catch(() => { }); 179 | }); 180 | return new Response_1.Response({ ...response, cookies }); 181 | } 182 | async freeMemory(id) { 183 | return Client_1.Client.getInstance().pool?.run(id.toString(), { 184 | name: "freeMemory", 185 | }); 186 | } 187 | getDefaultHeaders() { 188 | return { 189 | "User-Agent": `tls-client/${__version__}`, 190 | "Accept-Encoding": "gzip, deflate, br", 191 | Accept: "*/*", 192 | Connection: "keep-alive", 193 | }; 194 | } 195 | } 196 | exports.Session = Session; 197 | -------------------------------------------------------------------------------- /dist/utils/download.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { 3 | if (k2 === undefined) k2 = k; 4 | var desc = Object.getOwnPropertyDescriptor(m, k); 5 | if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { 6 | desc = { enumerable: true, get: function() { return m[k]; } }; 7 | } 8 | Object.defineProperty(o, k2, desc); 9 | }) : (function(o, m, k, k2) { 10 | if (k2 === undefined) k2 = k; 11 | o[k2] = m[k]; 12 | })); 13 | var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { 14 | Object.defineProperty(o, "default", { enumerable: true, value: v }); 15 | }) : function(o, v) { 16 | o["default"] = v; 17 | }); 18 | var __importStar = (this && this.__importStar) || (function () { 19 | var ownKeys = function(o) { 20 | ownKeys = Object.getOwnPropertyNames || function (o) { 21 | var ar = []; 22 | for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; 23 | return ar; 24 | }; 25 | return ownKeys(o); 26 | }; 27 | return function (mod) { 28 | if (mod && mod.__esModule) return mod; 29 | var result = {}; 30 | if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); 31 | __setModuleDefault(result, mod); 32 | return result; 33 | }; 34 | })(); 35 | var __importDefault = (this && this.__importDefault) || function (mod) { 36 | return (mod && mod.__esModule) ? mod : { "default": mod }; 37 | }; 38 | Object.defineProperty(exports, "__esModule", { value: true }); 39 | exports.LibraryDownloader = void 0; 40 | const logger_1 = require("./logger"); 41 | const https_1 = __importDefault(require("https")); 42 | const fs_1 = __importStar(require("fs")); 43 | const readline = __importStar(require("readline")); 44 | class LibraryDownloader { 45 | static file; 46 | static path; 47 | static issueURL = "https://github.com/Sahil1337/node-tls-client/issues"; 48 | static async retrieveLibrary(file, libPath) { 49 | this.file = file; 50 | this.path = libPath; 51 | try { 52 | const latest = await this.getLatest(); 53 | if (latest) { 54 | await this.extract(latest.browser_download_url); 55 | logger_1.logger.success("Extracted shared library."); 56 | return true; 57 | } 58 | else { 59 | logger_1.logger.error(`Failed to find required asset: ${this.file.name}, report ${logger_1.logger.hyperlink("here", this.issueURL)}.`); 60 | return false; 61 | } 62 | } 63 | catch (error) { 64 | logger_1.logger.error(`Initialization failed: ${error}`); 65 | return false; 66 | } 67 | } 68 | static formatBytes(bytes, decimals = 2) { 69 | if (bytes === 0) 70 | return "0 Bytes"; 71 | const k = 1024; 72 | const dm = decimals < 0 ? 0 : decimals; 73 | const sizes = ["Bytes", "KB", "MB", "GB", "TB"]; 74 | const i = Math.floor(Math.log(bytes) / Math.log(k)); 75 | return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + " " + sizes[i]; 76 | } 77 | static progress(downloaded, total) { 78 | const percentage = (downloaded / total) * 100; 79 | const progress = Math.floor(percentage / 2); 80 | const bar = "█".repeat(progress) + " ".repeat(50 - progress); 81 | readline.clearLine(process.stdout, 0); 82 | readline.cursorTo(process.stdout, 0); 83 | process.stdout.write(`${logger_1.logger.stamp} DOWNLOADING:[${bar}] ${percentage.toFixed(2)}% (${this.formatBytes(downloaded)} / ${this.formatBytes(total)})`); 84 | } 85 | static async download(url, file) { 86 | return new Promise((resolve, reject) => { 87 | https_1.default 88 | .get(url, (response) => { 89 | if (response.statusCode && 90 | response.statusCode >= 300 && 91 | response.statusCode < 400 && 92 | response.headers.location) { 93 | const newURL = new URL(response.headers.location, url).toString(); 94 | logger_1.logger.debug(`Fetched shared library ${logger_1.logger.hyperlink("url", newURL)}`); 95 | this.download(newURL, file).then(resolve).catch(reject); 96 | } 97 | else if (response.statusCode && 98 | response.statusCode >= 200 && 99 | response.statusCode < 300) { 100 | const totalBytes = parseInt(response.headers["content-length"] || "0", 10); 101 | let downloadedBytes = 0; 102 | response.pipe(file); 103 | response.on("data", (chunk) => { 104 | downloadedBytes += chunk.length; 105 | this.progress(downloadedBytes, totalBytes); 106 | }); 107 | response.on("end", () => { 108 | file.close((err) => { 109 | if (err) { 110 | reject(err); 111 | } 112 | else { 113 | process.stdout.write("\n"); 114 | resolve(); 115 | } 116 | }); 117 | }); 118 | file.on("error", (err) => { 119 | fs_1.default.unlink(this.path, () => reject(err)); 120 | }); 121 | } 122 | else { 123 | logger_1.logger.error(`Failed to download the file [statusCode:${response.statusCode}]`); 124 | reject(); 125 | } 126 | }) 127 | .on("error", (err) => { 128 | fs_1.default.unlink(this.path, () => reject(err)); 129 | }); 130 | }); 131 | } 132 | static async extract(url) { 133 | return new Promise((resolve, reject) => { 134 | const file = (0, fs_1.createWriteStream)(this.path); 135 | this.download(url, file).then(resolve).catch(reject); 136 | }); 137 | } 138 | static async getLatest() { 139 | return new Promise((resolve) => { 140 | const options = { 141 | hostname: "api.github.com", 142 | path: "/repos/bogdanfinn/tls-client/releases/latest", 143 | method: "GET", 144 | headers: { 145 | "user-agent": "node-tls-client", 146 | }, 147 | }; 148 | https_1.default 149 | .get(options, (res) => { 150 | let data = ""; 151 | res.on("data", (chunk) => { 152 | data += chunk; 153 | }); 154 | res.on("end", () => { 155 | if (res.statusCode === 200) { 156 | try { 157 | const response = JSON.parse(data); 158 | const version = response.tag_name.replace("v", ""); 159 | logger_1.logger.debug(`Fetched latest version: v${version}`); 160 | const assetName = this.file.downloadName.replace("{version}", version); 161 | const asset = response.assets.find((asset) => asset.name === assetName); 162 | if (!asset) { 163 | logger_1.logger.error(`Failed to find required asset: ${this.file.name}, report ${logger_1.logger.hyperlink("here", this.issueURL)}.`); 164 | resolve(null); 165 | } 166 | else { 167 | resolve(asset); 168 | } 169 | } 170 | catch (err) { 171 | logger_1.logger.error(`Failed to parse response: ${err}`); 172 | resolve(null); 173 | } 174 | } 175 | else { 176 | logger_1.logger.error(`Failed to fetch the latest version. Status code: ${res.statusCode}`); 177 | resolve(null); 178 | } 179 | }); 180 | }) 181 | .on("error", (err) => { 182 | logger_1.logger.error(`Failed to fetch the latest version: ${err}`); 183 | resolve(null); 184 | }); 185 | }); 186 | } 187 | } 188 | exports.LibraryDownloader = LibraryDownloader; 189 | -------------------------------------------------------------------------------- /src/lib/Session.ts: -------------------------------------------------------------------------------- 1 | import { randomUUID } from "crypto"; 2 | import { Cookies } from "./Cookie"; 3 | import { 4 | ClientIdentifier, 5 | DeleteRequestOptions, 6 | GetRequestOptions, 7 | HeadRequestOptions, 8 | Methods, 9 | OptionsRequestOptions, 10 | PatchRequestOptions, 11 | PostRequestOptions, 12 | PutRequestOptions, 13 | RequestOptions, 14 | SessionOptions, 15 | TlsResponse, 16 | } from "../interface"; 17 | import { OutgoingHttpHeaders } from "http2"; 18 | import { URL } from "url"; 19 | import { isByteRequest, logger } from "../utils"; 20 | import { Payload } from "../interface/payload"; 21 | import { Client } from "./Client"; 22 | import { Response } from "./Response"; 23 | 24 | const __version__ = "2.1.0"; 25 | 26 | export class Session { 27 | private jar = new Cookies(); 28 | private sessionId = randomUUID(); 29 | 30 | constructor(private readonly config: SessionOptions = {}) {} 31 | 32 | public async cookies() { 33 | return this.jar.fetchAllCookies(); 34 | } 35 | 36 | /** 37 | * The 'GET' method performs a GET request to the provided URL with the provided options. 38 | * 39 | * @param url - The URL to perform the GET request to. 40 | * @param options - The options for the GET request. 41 | * 42 | * @returns The response from the 'execute' method. 43 | */ 44 | public get(url: string, options: GetRequestOptions = {}) { 45 | return this.execute("GET", url, options); 46 | } 47 | 48 | /** 49 | * The 'DELETE' method performs a DELETE request to the provided URL with the provided options. 50 | * 51 | * @param url - The URL to perform the DELETE request to. 52 | * @param options - The options for the DELETE request. 53 | * 54 | * @returns The response from the 'execute' method. 55 | */ 56 | public delete(url: string, options: DeleteRequestOptions = {}) { 57 | return this.execute("DELETE", url, options); 58 | } 59 | 60 | /** 61 | * The 'OPTIONS' method performs an OPTIONS request to the provided URL with the provided options. 62 | * 63 | * @param url - The URL to perform the OPTIONS request to. 64 | * @param options - The options for the OPTIONS request. 65 | * 66 | * @returns The response from the 'execute' method. 67 | */ 68 | public options(url: string, options: OptionsRequestOptions = {}) { 69 | return this.execute("OPTIONS", url, options); 70 | } 71 | 72 | /** 73 | * The 'HEAD' method performs a HEAD request to the provided URL with the provided options. 74 | * 75 | * @param url - The URL to perform the HEAD request to. 76 | * @param options - The options for the HEAD request. 77 | * 78 | * @returns The response from the 'execute' method. 79 | */ 80 | public head(url: string, options: HeadRequestOptions = {}) { 81 | return this.execute("HEAD", url, options); 82 | } 83 | 84 | /** 85 | * The 'POST' method performs a POST request to the provided URL with the provided options. 86 | * 87 | * @param url - The URL to perform the POST request to. 88 | * @param options - The options for the POST request. 89 | * 90 | * @returns The response from the 'execute' method. 91 | */ 92 | public post(url: string, options: PostRequestOptions = {}) { 93 | return this.execute("POST", url, options); 94 | } 95 | 96 | /** 97 | * The 'PATCH' method performs a PATCH request to the provided URL with the provided options. 98 | * 99 | * @param url - The URL to perform the PATCH request to. 100 | * @param options - The options for the PATCH request. 101 | * 102 | * @returns The response from the 'execute' method. 103 | */ 104 | public patch(url: string, options: PatchRequestOptions = {}) { 105 | return this.execute("PATCH", url, options); 106 | } 107 | 108 | /** 109 | * The 'PUT' method performs a PUT request to the provided URL with the provided options. 110 | * 111 | * @param url - The URL to perform the PUT request to. 112 | * @param options - The options for the PUT request. 113 | * 114 | * @returns The response from the 'execute' method. 115 | */ 116 | public put(url: string, options: PutRequestOptions = {}) { 117 | return this.execute("PUT", url, options); 118 | } 119 | 120 | /** 121 | * The 'close' method closes the current session. 122 | * 123 | * @returns The response from the 'destroySession' function. 124 | */ 125 | public async close() { 126 | return Client.getInstance().pool?.run( 127 | JSON.stringify({ 128 | sessionId: this.sessionId, 129 | }), 130 | { name: "destroySession" } 131 | ); 132 | } 133 | 134 | protected async execute( 135 | method: Methods, 136 | url: string | URL, 137 | options: RequestOptions = {} 138 | ) { 139 | const headers = 140 | options?.headers !== undefined 141 | ? options.headers 142 | : this.config.headers ?? this.getDefaultHeaders(); 143 | 144 | const requestCookies = await this.jar.mergeCookies( 145 | options?.cookies || {}, 146 | url.toString() 147 | ); 148 | 149 | const payload: Payload = { 150 | sessionId: this.sessionId, 151 | followRedirects: options.followRedirects ?? false, 152 | forceHttp1: this.config.forceHttp1 ?? false, 153 | withDebug: this.config.debug ?? false, 154 | headers, 155 | headerOrder: options.headerOrder || this.config.headerOrder || [], 156 | insecureSkipVerify: this.config.insecureSkipVerify ?? false, 157 | proxyUrl: options.proxy || this.config.proxy || "", 158 | isRotatingProxy: 159 | options?.isRotatingProxy ?? this.config.isRotatingProxy ?? false, 160 | requestUrl: url, 161 | requestMethod: method, 162 | requestBody: options?.body || null, 163 | timeoutMilliseconds: this.config.timeout || 0, 164 | withRandomTLSExtensionOrder: this.config.randomTlsExtensionOrder ?? false, 165 | isByteResponse: options?.byteResponse ?? false, 166 | isByteRequest: isByteRequest(headers), 167 | requestHostOverride: options?.hostOverride || null, 168 | disableIPV6: this.config.disableIPV6 ?? false, 169 | disableIPV4: this.config.disableIPV4 ?? false, 170 | transportOptions: this.config.transportOptions ?? undefined, 171 | catchPanics: false, 172 | streamOutputEOFSymbol: this.config.streamOutputEOFSymbol ?? null, 173 | streamOutputPath: this.config.streamOutputPath ?? null, 174 | streamOutputBlockSize: this.config.streamOutputBlockSize ?? null, 175 | serverNameOverwrite: this.config.serverNameOverwrite ?? "", 176 | connectHeaders: 177 | this.config.connectHeaders ?? options.connectHeaders ?? {}, 178 | localAddress: this.config.localAddress ?? null, 179 | withDefaultCookieJar: true, 180 | withoutCookieJar: false, 181 | requestCookies, 182 | }; 183 | 184 | if (this.config.clientIdentifier) { 185 | payload["tlsClientIdentifier"] = this.config.clientIdentifier; 186 | } else if (this.config.ja3string) { 187 | payload["customTlsClient"] = { 188 | ja3String: this.config.ja3string, 189 | h2Settings: this.config.h2Settings ?? {}, 190 | h2SettingsOrder: this.config.h2SettingsOrder ?? [], 191 | pseudoHeaderOrder: this.config.pseudoHeaderOrder ?? [], 192 | connectionFlow: this.config.connectionFlow ?? 0, 193 | priorityFrames: this.config.priorityFrames ?? [], 194 | headerPriority: this.config.headerPriority ?? { 195 | streamDep: 0, 196 | exclusive: false, 197 | weight: 0, 198 | }, 199 | certCompressionAlgo: this.config.certCompressionAlgo ?? "zlib", 200 | supportedVersions: this.config.supportedVersions ?? [], 201 | supportedSignatureAlgorithms: 202 | this.config.supportedSignatureAlgorithms ?? [], 203 | keyShareCurves: this.config.keyShareCurves ?? [], 204 | alpnProtocols: this.config.alpnProtocols ?? [], 205 | alpsProtocols: this.config.alpsProtocols ?? [], 206 | }; 207 | } else payload["tlsClientIdentifier"] = ClientIdentifier.chrome_131; 208 | 209 | const requestPayloadString = JSON.stringify(payload); 210 | 211 | const rawResponse = await Client.getInstance().pool.run( 212 | requestPayloadString, 213 | { 214 | name: "request", 215 | } 216 | ); 217 | 218 | const response: TlsResponse = JSON.parse(rawResponse); 219 | 220 | const cookies = await this.jar.syncCookies( 221 | response.cookies || {}, 222 | url.toString() 223 | ); 224 | 225 | setImmediate(() => { 226 | this.freeMemory(response.id).catch(() => {}); 227 | }); 228 | 229 | return new Response({ ...response, cookies }); 230 | } 231 | 232 | private async freeMemory(id: string): Promise { 233 | return Client.getInstance().pool?.run(id.toString(), { 234 | name: "freeMemory", 235 | }); 236 | } 237 | 238 | private getDefaultHeaders(): OutgoingHttpHeaders { 239 | return { 240 | "User-Agent": `tls-client/${__version__}`, 241 | "Accept-Encoding": "gzip, deflate, br", 242 | Accept: "*/*", 243 | Connection: "keep-alive", 244 | }; 245 | } 246 | } 247 | -------------------------------------------------------------------------------- /docs/interfaces/PriorityFrames.html: -------------------------------------------------------------------------------- 1 | PriorityFrames | node-tls-client

Interface PriorityFrames

Represents priority frames for HTTP/2 streams.

2 |
interface PriorityFrames {
    priorityParam: PriorityParam;
    streamID: number;
}

Properties

Properties

priorityParam: PriorityParam

The parameters for priority settings.

5 |
streamID: number

The stream ID for which priority is set.

6 |
-------------------------------------------------------------------------------- /docs/assets/search.js: -------------------------------------------------------------------------------- 1 | window.searchData = "data:application/octet-stream;base64,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"; -------------------------------------------------------------------------------- /docs/interfaces/PriorityParam.html: -------------------------------------------------------------------------------- 1 | PriorityParam | node-tls-client

Interface PriorityParam

Represents parameters for setting priority of HTTP/2 streams.

2 |
interface PriorityParam {
    exclusive: boolean;
    streamDep: number;
    weight: number;
}

Properties

Properties

exclusive: boolean

Indicates whether the priority is exclusive.

6 |
streamDep: number

The stream dependency for priority.

7 |
weight: number

The weight of the priority.

8 |
-------------------------------------------------------------------------------- /docs/modules.html: -------------------------------------------------------------------------------- 1 | node-tls-client
--------------------------------------------------------------------------------