httpcloak 1.6.0-beta.8 → 1.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +27 -27
- package/lib/index.d.ts +37 -9
- package/lib/index.js +103 -27
- package/npm/darwin-arm64/package.json +1 -1
- package/npm/darwin-x64/package.json +1 -1
- package/npm/linux-arm64/package.json +1 -1
- package/npm/linux-x64/package.json +1 -1
- package/npm/win32-arm64/package.json +1 -1
- package/npm/win32-x64/package.json +1 -1
- package/package.json +7 -7
package/README.md
CHANGED
|
@@ -16,7 +16,7 @@ npm install httpcloak
|
|
|
16
16
|
const { Session } = require("httpcloak");
|
|
17
17
|
|
|
18
18
|
async function main() {
|
|
19
|
-
const session = new Session({ preset: "chrome-
|
|
19
|
+
const session = new Session({ preset: "chrome-145" });
|
|
20
20
|
|
|
21
21
|
try {
|
|
22
22
|
// GET request
|
|
@@ -53,7 +53,7 @@ main();
|
|
|
53
53
|
```javascript
|
|
54
54
|
import { Session } from "httpcloak";
|
|
55
55
|
|
|
56
|
-
const session = new Session({ preset: "chrome-
|
|
56
|
+
const session = new Session({ preset: "chrome-145" });
|
|
57
57
|
|
|
58
58
|
const response = await session.get("https://example.com");
|
|
59
59
|
console.log(response.text);
|
|
@@ -66,7 +66,7 @@ session.close();
|
|
|
66
66
|
```javascript
|
|
67
67
|
const { Session } = require("httpcloak");
|
|
68
68
|
|
|
69
|
-
const session = new Session({ preset: "chrome-
|
|
69
|
+
const session = new Session({ preset: "chrome-145" });
|
|
70
70
|
|
|
71
71
|
// Sync GET
|
|
72
72
|
const response = session.getSync("https://example.com");
|
|
@@ -86,7 +86,7 @@ session.close();
|
|
|
86
86
|
```javascript
|
|
87
87
|
const { Session } = require("httpcloak");
|
|
88
88
|
|
|
89
|
-
const session = new Session({ preset: "chrome-
|
|
89
|
+
const session = new Session({ preset: "chrome-145" });
|
|
90
90
|
|
|
91
91
|
// GET with callback
|
|
92
92
|
session.getCb("https://example.com", (err, response) => {
|
|
@@ -121,7 +121,7 @@ const { Session } = require("httpcloak");
|
|
|
121
121
|
const fs = require("fs");
|
|
122
122
|
|
|
123
123
|
async function downloadFile() {
|
|
124
|
-
const session = new Session({ preset: "chrome-
|
|
124
|
+
const session = new Session({ preset: "chrome-145" });
|
|
125
125
|
|
|
126
126
|
try {
|
|
127
127
|
// Start streaming request
|
|
@@ -158,7 +158,7 @@ downloadFile();
|
|
|
158
158
|
```javascript
|
|
159
159
|
const { Session } = require("httpcloak");
|
|
160
160
|
|
|
161
|
-
const session = new Session({ preset: "chrome-
|
|
161
|
+
const session = new Session({ preset: "chrome-145" });
|
|
162
162
|
|
|
163
163
|
// Stream GET
|
|
164
164
|
const getStream = session.getStream("https://example.com/data");
|
|
@@ -195,19 +195,19 @@ const { Session } = require("httpcloak");
|
|
|
195
195
|
|
|
196
196
|
// Basic HTTP proxy
|
|
197
197
|
const session = new Session({
|
|
198
|
-
preset: "chrome-
|
|
198
|
+
preset: "chrome-145",
|
|
199
199
|
proxy: "http://host:port",
|
|
200
200
|
});
|
|
201
201
|
|
|
202
202
|
// With authentication
|
|
203
203
|
const sessionAuth = new Session({
|
|
204
|
-
preset: "chrome-
|
|
204
|
+
preset: "chrome-145",
|
|
205
205
|
proxy: "http://user:pass@host:port",
|
|
206
206
|
});
|
|
207
207
|
|
|
208
208
|
// HTTPS proxy
|
|
209
209
|
const sessionHttps = new Session({
|
|
210
|
-
preset: "chrome-
|
|
210
|
+
preset: "chrome-145",
|
|
211
211
|
proxy: "https://user:pass@host:port",
|
|
212
212
|
});
|
|
213
213
|
```
|
|
@@ -219,13 +219,13 @@ const { Session } = require("httpcloak");
|
|
|
219
219
|
|
|
220
220
|
// SOCKS5 proxy (with DNS resolution on proxy)
|
|
221
221
|
const session = new Session({
|
|
222
|
-
preset: "chrome-
|
|
222
|
+
preset: "chrome-145",
|
|
223
223
|
proxy: "socks5h://host:port",
|
|
224
224
|
});
|
|
225
225
|
|
|
226
226
|
// With authentication
|
|
227
227
|
const sessionAuth = new Session({
|
|
228
|
-
preset: "chrome-
|
|
228
|
+
preset: "chrome-145",
|
|
229
229
|
proxy: "socks5h://user:pass@host:port",
|
|
230
230
|
});
|
|
231
231
|
|
|
@@ -242,7 +242,7 @@ const { Session } = require("httpcloak");
|
|
|
242
242
|
|
|
243
243
|
// MASQUE proxy (auto-detected for known providers like Bright Data)
|
|
244
244
|
const session = new Session({
|
|
245
|
-
preset: "chrome-
|
|
245
|
+
preset: "chrome-145",
|
|
246
246
|
proxy: "https://user:pass@brd.superproxy.io:10001",
|
|
247
247
|
});
|
|
248
248
|
|
|
@@ -258,7 +258,7 @@ Use different proxies for TCP (HTTP/1.1, HTTP/2) and UDP (HTTP/3) traffic:
|
|
|
258
258
|
const { Session } = require("httpcloak");
|
|
259
259
|
|
|
260
260
|
const session = new Session({
|
|
261
|
-
preset: "chrome-
|
|
261
|
+
preset: "chrome-145",
|
|
262
262
|
tcpProxy: "http://tcp-proxy:port", // For HTTP/1.1, HTTP/2
|
|
263
263
|
udpProxy: "https://masque-proxy:port", // For HTTP/3
|
|
264
264
|
});
|
|
@@ -275,7 +275,7 @@ const { Session } = require("httpcloak");
|
|
|
275
275
|
|
|
276
276
|
// Enable ECH for Cloudflare domains
|
|
277
277
|
const session = new Session({
|
|
278
|
-
preset: "chrome-
|
|
278
|
+
preset: "chrome-145",
|
|
279
279
|
echConfigDomain: "cloudflare-ech.com",
|
|
280
280
|
});
|
|
281
281
|
|
|
@@ -293,7 +293,7 @@ const { Session } = require("httpcloak");
|
|
|
293
293
|
|
|
294
294
|
// Connect to example.com's IP but request www.cloudflare.com
|
|
295
295
|
const session = new Session({
|
|
296
|
-
preset: "chrome-
|
|
296
|
+
preset: "chrome-145",
|
|
297
297
|
connectTo: { "www.cloudflare.com": "example.com" },
|
|
298
298
|
});
|
|
299
299
|
|
|
@@ -308,7 +308,7 @@ Get HTTP/3 with encrypted SNI through a SOCKS5 proxy:
|
|
|
308
308
|
const { Session } = require("httpcloak");
|
|
309
309
|
|
|
310
310
|
const session = new Session({
|
|
311
|
-
preset: "chrome-
|
|
311
|
+
preset: "chrome-145",
|
|
312
312
|
proxy: "socks5h://user:pass@host:port",
|
|
313
313
|
echConfigDomain: "cloudflare-ech.com",
|
|
314
314
|
});
|
|
@@ -349,7 +349,7 @@ session.close();
|
|
|
349
349
|
const { Session } = require("httpcloak");
|
|
350
350
|
|
|
351
351
|
const session = new Session({
|
|
352
|
-
preset: "chrome-
|
|
352
|
+
preset: "chrome-145", // Browser fingerprint preset
|
|
353
353
|
proxy: null, // Proxy URL
|
|
354
354
|
tcpProxy: null, // Separate TCP proxy
|
|
355
355
|
udpProxy: null, // Separate UDP proxy (MASQUE)
|
|
@@ -371,8 +371,8 @@ const session = new Session({
|
|
|
371
371
|
const { availablePresets } = require("httpcloak");
|
|
372
372
|
|
|
373
373
|
console.log(availablePresets());
|
|
374
|
-
// ['chrome-144', 'chrome-143', 'chrome-141', 'chrome-133',
|
|
375
|
-
// 'firefox-133', 'safari-18', '
|
|
374
|
+
// ['chrome-145', 'chrome-144', 'chrome-143', 'chrome-141', 'chrome-133',
|
|
375
|
+
// 'firefox-133', 'safari-18', 'chrome-145-ios', ...]
|
|
376
376
|
```
|
|
377
377
|
|
|
378
378
|
## Response Object
|
|
@@ -428,7 +428,7 @@ stream.close();
|
|
|
428
428
|
```javascript
|
|
429
429
|
const { Session } = require("httpcloak");
|
|
430
430
|
|
|
431
|
-
const session = new Session({ preset: "chrome-
|
|
431
|
+
const session = new Session({ preset: "chrome-145" });
|
|
432
432
|
|
|
433
433
|
// GET
|
|
434
434
|
const response = await session.get("https://example.com");
|
|
@@ -490,7 +490,7 @@ HTTPCloak includes TypeScript definitions out of the box:
|
|
|
490
490
|
```typescript
|
|
491
491
|
import { Session, Response, StreamResponse, HTTPCloakError } from "httpcloak";
|
|
492
492
|
|
|
493
|
-
const session = new Session({ preset: "chrome-
|
|
493
|
+
const session = new Session({ preset: "chrome-145" });
|
|
494
494
|
|
|
495
495
|
async function fetchData(): Promise<Response> {
|
|
496
496
|
return session.get("https://example.com");
|
|
@@ -519,7 +519,7 @@ const { LocalProxy } = require("httpcloak");
|
|
|
519
519
|
const axios = require("axios");
|
|
520
520
|
|
|
521
521
|
// Start local proxy with Chrome fingerprint
|
|
522
|
-
const proxy = new LocalProxy({ preset: "chrome-
|
|
522
|
+
const proxy = new LocalProxy({ preset: "chrome-145" });
|
|
523
523
|
console.log(`Proxy running on ${proxy.proxyUrl}`);
|
|
524
524
|
|
|
525
525
|
// Use X-HTTPCloak-Scheme header for HTTPS with fingerprinting + streaming
|
|
@@ -558,7 +558,7 @@ const { LocalProxy } = require("httpcloak");
|
|
|
558
558
|
const axios = require("axios");
|
|
559
559
|
|
|
560
560
|
// Start local proxy with Chrome fingerprint
|
|
561
|
-
const proxy = new LocalProxy({ preset: "chrome-
|
|
561
|
+
const proxy = new LocalProxy({ preset: "chrome-145" });
|
|
562
562
|
|
|
563
563
|
// Standard HTTPS (uses CONNECT tunnel - fingerprinting via upstream proxy only)
|
|
564
564
|
const response = await axios.get("https://example.com", {
|
|
@@ -590,7 +590,7 @@ When your client already provides authentic browser headers, use TLS-only mode:
|
|
|
590
590
|
const { LocalProxy } = require("httpcloak");
|
|
591
591
|
|
|
592
592
|
// Only apply TLS fingerprint, pass headers through
|
|
593
|
-
const proxy = new LocalProxy({ preset: "chrome-
|
|
593
|
+
const proxy = new LocalProxy({ preset: "chrome-145", tlsOnly: true });
|
|
594
594
|
|
|
595
595
|
// Your client's headers are preserved
|
|
596
596
|
const response = await fetch("https://example.com", {
|
|
@@ -608,10 +608,10 @@ Route different requests through different browser fingerprints:
|
|
|
608
608
|
```javascript
|
|
609
609
|
const { LocalProxy, Session } = require("httpcloak");
|
|
610
610
|
|
|
611
|
-
const proxy = new LocalProxy({ preset: "chrome-
|
|
611
|
+
const proxy = new LocalProxy({ preset: "chrome-145" });
|
|
612
612
|
|
|
613
613
|
// Create sessions with different fingerprints
|
|
614
|
-
const chromeSession = new Session({ preset: "chrome-
|
|
614
|
+
const chromeSession = new Session({ preset: "chrome-145" });
|
|
615
615
|
const firefoxSession = new Session({ preset: "firefox-133" });
|
|
616
616
|
|
|
617
617
|
// Register sessions with the proxy
|
|
@@ -638,7 +638,7 @@ proxy.close();
|
|
|
638
638
|
```javascript
|
|
639
639
|
const proxy = new LocalProxy({
|
|
640
640
|
port: 0, // Port (0 = auto-select)
|
|
641
|
-
preset: "chrome-
|
|
641
|
+
preset: "chrome-145", // Browser fingerprint
|
|
642
642
|
timeout: 30, // Request timeout in seconds
|
|
643
643
|
maxConnections: 1000, // Max concurrent connections
|
|
644
644
|
tcpProxy: null, // Default upstream TCP proxy
|
package/lib/index.d.ts
CHANGED
|
@@ -195,7 +195,7 @@ export class StreamResponse {
|
|
|
195
195
|
}
|
|
196
196
|
|
|
197
197
|
export interface SessionOptions {
|
|
198
|
-
/** Browser preset to use (default: "chrome-
|
|
198
|
+
/** Browser preset to use (default: "chrome-145") */
|
|
199
199
|
preset?: string;
|
|
200
200
|
/** Proxy URL (e.g., "http://user:pass@host:port" or "socks5://host:port") */
|
|
201
201
|
proxy?: string;
|
|
@@ -272,6 +272,19 @@ export class Session {
|
|
|
272
272
|
/** Close the session and release resources */
|
|
273
273
|
close(): void;
|
|
274
274
|
|
|
275
|
+
/** Simulate a real browser page load to warm TLS sessions, cookies, and cache.
|
|
276
|
+
* Fetches the HTML page and its subresources (CSS, JS, images) with
|
|
277
|
+
* realistic headers, priorities, and timing.
|
|
278
|
+
*/
|
|
279
|
+
warmup(url: string, options?: { timeout?: number }): void;
|
|
280
|
+
|
|
281
|
+
/** Create n forked sessions sharing cookies and TLS session caches.
|
|
282
|
+
* Forked sessions simulate multiple browser tabs from the same browser:
|
|
283
|
+
* same cookies, same TLS resumption tickets, same fingerprint, but
|
|
284
|
+
* independent connections for parallel requests.
|
|
285
|
+
*/
|
|
286
|
+
fork(n?: number): Session[];
|
|
287
|
+
|
|
275
288
|
/** Refresh the session by closing all connections while keeping TLS session tickets.
|
|
276
289
|
* This simulates a browser page refresh - connections are severed but 0-RTT
|
|
277
290
|
* early data can be used on reconnection due to preserved session tickets.
|
|
@@ -596,7 +609,7 @@ export class Session {
|
|
|
596
609
|
export interface LocalProxyOptions {
|
|
597
610
|
/** Port to listen on (default: 0 for auto-assign) */
|
|
598
611
|
port?: number;
|
|
599
|
-
/** Browser preset to use (default: "chrome-
|
|
612
|
+
/** Browser preset to use (default: "chrome-145") */
|
|
600
613
|
preset?: string;
|
|
601
614
|
/** Request timeout in seconds (default: 30) */
|
|
602
615
|
timeout?: number;
|
|
@@ -636,7 +649,7 @@ export interface LocalProxyStats {
|
|
|
636
649
|
*
|
|
637
650
|
* @example
|
|
638
651
|
* // Basic usage
|
|
639
|
-
* const proxy = new LocalProxy({ preset: "chrome-
|
|
652
|
+
* const proxy = new LocalProxy({ preset: "chrome-145", tlsOnly: true });
|
|
640
653
|
* console.log(`Proxy running on ${proxy.proxyUrl}`);
|
|
641
654
|
* // Use with any HTTP client pointing to the proxy
|
|
642
655
|
* proxy.close();
|
|
@@ -793,22 +806,37 @@ export function request(method: string, url: string, options?: RequestOptions):
|
|
|
793
806
|
|
|
794
807
|
/** Available browser presets */
|
|
795
808
|
export const Preset: {
|
|
809
|
+
CHROME_145: string;
|
|
810
|
+
CHROME_145_WINDOWS: string;
|
|
811
|
+
CHROME_145_LINUX: string;
|
|
812
|
+
CHROME_145_MACOS: string;
|
|
813
|
+
CHROME_144: string;
|
|
814
|
+
CHROME_144_WINDOWS: string;
|
|
815
|
+
CHROME_144_LINUX: string;
|
|
816
|
+
CHROME_144_MACOS: string;
|
|
796
817
|
CHROME_143: string;
|
|
797
818
|
CHROME_143_WINDOWS: string;
|
|
798
819
|
CHROME_143_LINUX: string;
|
|
799
820
|
CHROME_143_MACOS: string;
|
|
800
821
|
CHROME_141: string;
|
|
801
822
|
CHROME_133: string;
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
823
|
+
CHROME_143_IOS: string;
|
|
824
|
+
CHROME_144_IOS: string;
|
|
825
|
+
CHROME_145_IOS: string;
|
|
826
|
+
CHROME_143_ANDROID: string;
|
|
827
|
+
CHROME_144_ANDROID: string;
|
|
828
|
+
CHROME_145_ANDROID: string;
|
|
829
|
+
FIREFOX_133: string;
|
|
830
|
+
SAFARI_18: string;
|
|
831
|
+
SAFARI_17_IOS: string;
|
|
832
|
+
SAFARI_18_IOS: string;
|
|
833
|
+
// Backwards compatibility aliases
|
|
806
834
|
IOS_CHROME_143: string;
|
|
807
835
|
IOS_CHROME_144: string;
|
|
836
|
+
IOS_CHROME_145: string;
|
|
808
837
|
ANDROID_CHROME_143: string;
|
|
809
838
|
ANDROID_CHROME_144: string;
|
|
810
|
-
|
|
811
|
-
SAFARI_18: string;
|
|
839
|
+
ANDROID_CHROME_145: string;
|
|
812
840
|
IOS_SAFARI_17: string;
|
|
813
841
|
IOS_SAFARI_18: string;
|
|
814
842
|
all(): string[];
|
package/lib/index.js
CHANGED
|
@@ -31,7 +31,19 @@ class HTTPCloakError extends Error {
|
|
|
31
31
|
* const session = new httpcloak.Session({ preset: httpcloak.Preset.FIREFOX_133 });
|
|
32
32
|
*/
|
|
33
33
|
const Preset = {
|
|
34
|
-
// Chrome
|
|
34
|
+
// Chrome 145 (latest)
|
|
35
|
+
CHROME_145: "chrome-145",
|
|
36
|
+
CHROME_145_WINDOWS: "chrome-145-windows",
|
|
37
|
+
CHROME_145_LINUX: "chrome-145-linux",
|
|
38
|
+
CHROME_145_MACOS: "chrome-145-macos",
|
|
39
|
+
|
|
40
|
+
// Chrome 144
|
|
41
|
+
CHROME_144: "chrome-144",
|
|
42
|
+
CHROME_144_WINDOWS: "chrome-144-windows",
|
|
43
|
+
CHROME_144_LINUX: "chrome-144-linux",
|
|
44
|
+
CHROME_144_MACOS: "chrome-144-macos",
|
|
45
|
+
|
|
46
|
+
// Chrome 143
|
|
35
47
|
CHROME_143: "chrome-143",
|
|
36
48
|
CHROME_143_WINDOWS: "chrome-143-windows",
|
|
37
49
|
CHROME_143_LINUX: "chrome-143-linux",
|
|
@@ -44,18 +56,30 @@ const Preset = {
|
|
|
44
56
|
CHROME_133: "chrome-133",
|
|
45
57
|
|
|
46
58
|
// Mobile Chrome
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
59
|
+
CHROME_143_IOS: "chrome-143-ios",
|
|
60
|
+
CHROME_144_IOS: "chrome-144-ios",
|
|
61
|
+
CHROME_145_IOS: "chrome-145-ios",
|
|
62
|
+
CHROME_143_ANDROID: "chrome-143-android",
|
|
63
|
+
CHROME_144_ANDROID: "chrome-144-android",
|
|
64
|
+
CHROME_145_ANDROID: "chrome-145-android",
|
|
51
65
|
|
|
52
66
|
// Firefox
|
|
53
67
|
FIREFOX_133: "firefox-133",
|
|
54
68
|
|
|
55
69
|
// Safari (desktop and mobile)
|
|
56
70
|
SAFARI_18: "safari-18",
|
|
57
|
-
|
|
58
|
-
|
|
71
|
+
SAFARI_17_IOS: "safari-17-ios",
|
|
72
|
+
SAFARI_18_IOS: "safari-18-ios",
|
|
73
|
+
|
|
74
|
+
// Backwards compatibility aliases (old naming convention)
|
|
75
|
+
IOS_CHROME_143: "chrome-143-ios",
|
|
76
|
+
IOS_CHROME_144: "chrome-144-ios",
|
|
77
|
+
IOS_CHROME_145: "chrome-145-ios",
|
|
78
|
+
ANDROID_CHROME_143: "chrome-143-android",
|
|
79
|
+
ANDROID_CHROME_144: "chrome-144-android",
|
|
80
|
+
ANDROID_CHROME_145: "chrome-145-android",
|
|
81
|
+
IOS_SAFARI_17: "safari-17-ios",
|
|
82
|
+
IOS_SAFARI_18: "safari-18-ios",
|
|
59
83
|
|
|
60
84
|
/**
|
|
61
85
|
* Get all available preset names
|
|
@@ -63,12 +87,14 @@ const Preset = {
|
|
|
63
87
|
*/
|
|
64
88
|
all() {
|
|
65
89
|
return [
|
|
90
|
+
this.CHROME_145, this.CHROME_145_WINDOWS, this.CHROME_145_LINUX, this.CHROME_145_MACOS,
|
|
66
91
|
this.CHROME_144, this.CHROME_144_WINDOWS, this.CHROME_144_LINUX, this.CHROME_144_MACOS,
|
|
67
92
|
this.CHROME_143, this.CHROME_143_WINDOWS, this.CHROME_143_LINUX, this.CHROME_143_MACOS,
|
|
68
93
|
this.CHROME_141, this.CHROME_133,
|
|
69
|
-
this.
|
|
94
|
+
this.CHROME_145_IOS, this.CHROME_144_IOS, this.CHROME_143_IOS,
|
|
95
|
+
this.CHROME_145_ANDROID, this.CHROME_144_ANDROID, this.CHROME_143_ANDROID,
|
|
70
96
|
this.FIREFOX_133,
|
|
71
|
-
this.SAFARI_18, this.
|
|
97
|
+
this.SAFARI_18, this.SAFARI_17_IOS, this.SAFARI_18_IOS,
|
|
72
98
|
];
|
|
73
99
|
},
|
|
74
100
|
};
|
|
@@ -757,6 +783,8 @@ function getLib() {
|
|
|
757
783
|
httpcloak_session_free: nativeLibHandle.func("httpcloak_session_free", "void", ["int64"]),
|
|
758
784
|
httpcloak_session_refresh: nativeLibHandle.func("httpcloak_session_refresh", "void", ["int64"]),
|
|
759
785
|
httpcloak_session_refresh_protocol: nativeLibHandle.func("httpcloak_session_refresh_protocol", "str", ["int64", "str"]),
|
|
786
|
+
httpcloak_session_warmup: nativeLibHandle.func("httpcloak_session_warmup", "str", ["int64", "str", "int64"]),
|
|
787
|
+
httpcloak_session_fork: nativeLibHandle.func("httpcloak_session_fork", "int64", ["int64"]),
|
|
760
788
|
httpcloak_get: nativeLibHandle.func("httpcloak_get", "str", ["int64", "str", "str"]),
|
|
761
789
|
httpcloak_post: nativeLibHandle.func("httpcloak_post", "str", ["int64", "str", "str", "str"]),
|
|
762
790
|
httpcloak_request: nativeLibHandle.func("httpcloak_request", "str", ["int64", "str"]),
|
|
@@ -996,11 +1024,11 @@ function addParamsToUrl(url, params) {
|
|
|
996
1024
|
return url;
|
|
997
1025
|
}
|
|
998
1026
|
|
|
999
|
-
const
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
return
|
|
1027
|
+
const sep = url.includes('?') ? '&' : '?';
|
|
1028
|
+
const parts = Object.entries(params).map(
|
|
1029
|
+
([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(String(value))}`
|
|
1030
|
+
);
|
|
1031
|
+
return url + sep + parts.join('&');
|
|
1004
1032
|
}
|
|
1005
1033
|
|
|
1006
1034
|
/**
|
|
@@ -1134,7 +1162,7 @@ function version() {
|
|
|
1134
1162
|
/**
|
|
1135
1163
|
* Get available browser presets with their supported protocols.
|
|
1136
1164
|
* Returns an object mapping preset names to their info:
|
|
1137
|
-
* { "chrome-
|
|
1165
|
+
* { "chrome-145": { protocols: ["h1", "h2", "h3"] }, ... }
|
|
1138
1166
|
*/
|
|
1139
1167
|
function availablePresets() {
|
|
1140
1168
|
const nativeLib = getLib();
|
|
@@ -1200,7 +1228,7 @@ class Session {
|
|
|
1200
1228
|
/**
|
|
1201
1229
|
* Create a new session
|
|
1202
1230
|
* @param {Object} options - Session options
|
|
1203
|
-
* @param {string} [options.preset="chrome-
|
|
1231
|
+
* @param {string} [options.preset="chrome-145"] - Browser preset to use
|
|
1204
1232
|
* @param {string} [options.proxy] - Proxy URL (e.g., "http://user:pass@host:port" or "socks5://host:port")
|
|
1205
1233
|
* @param {string} [options.tcpProxy] - Proxy URL for TCP protocols (HTTP/1.1, HTTP/2) - use with udpProxy for split config
|
|
1206
1234
|
* @param {string} [options.udpProxy] - Proxy URL for UDP protocols (HTTP/3 via MASQUE) - use with tcpProxy for split config
|
|
@@ -1221,7 +1249,7 @@ class Session {
|
|
|
1221
1249
|
*/
|
|
1222
1250
|
constructor(options = {}) {
|
|
1223
1251
|
const {
|
|
1224
|
-
preset = "chrome-
|
|
1252
|
+
preset = "chrome-145",
|
|
1225
1253
|
proxy = null,
|
|
1226
1254
|
tcpProxy = null,
|
|
1227
1255
|
udpProxy = null,
|
|
@@ -1242,7 +1270,7 @@ class Session {
|
|
|
1242
1270
|
quicIdleTimeout = 0,
|
|
1243
1271
|
localAddress = null,
|
|
1244
1272
|
keyLogFile = null,
|
|
1245
|
-
|
|
1273
|
+
enableSpeculativeTls = false,
|
|
1246
1274
|
switchProtocol = null,
|
|
1247
1275
|
} = options;
|
|
1248
1276
|
|
|
@@ -1304,8 +1332,8 @@ class Session {
|
|
|
1304
1332
|
if (keyLogFile) {
|
|
1305
1333
|
config.key_log_file = keyLogFile;
|
|
1306
1334
|
}
|
|
1307
|
-
if (
|
|
1308
|
-
config.
|
|
1335
|
+
if (enableSpeculativeTls) {
|
|
1336
|
+
config.enable_speculative_tls = true;
|
|
1309
1337
|
}
|
|
1310
1338
|
if (switchProtocol) {
|
|
1311
1339
|
config.switch_protocol = switchProtocol;
|
|
@@ -1351,6 +1379,54 @@ class Session {
|
|
|
1351
1379
|
}
|
|
1352
1380
|
}
|
|
1353
1381
|
|
|
1382
|
+
/**
|
|
1383
|
+
* Simulate a real browser page load to warm TLS sessions, cookies, and cache.
|
|
1384
|
+
* Fetches the HTML page and its subresources (CSS, JS, images) with
|
|
1385
|
+
* realistic headers, priorities, and timing.
|
|
1386
|
+
* @param {string} url - The page URL to warm up.
|
|
1387
|
+
* @param {Object} [options] - Options.
|
|
1388
|
+
* @param {number} [options.timeout] - Timeout in milliseconds (default: 60000).
|
|
1389
|
+
*/
|
|
1390
|
+
warmup(url, options = {}) {
|
|
1391
|
+
if (this._handle) {
|
|
1392
|
+
const timeoutMs = options.timeout || 0;
|
|
1393
|
+
const result = this._lib.httpcloak_session_warmup(this._handle, url, timeoutMs);
|
|
1394
|
+
if (result) {
|
|
1395
|
+
const data = JSON.parse(result);
|
|
1396
|
+
if (data.error) {
|
|
1397
|
+
throw new HTTPCloakError(data.error);
|
|
1398
|
+
}
|
|
1399
|
+
}
|
|
1400
|
+
}
|
|
1401
|
+
}
|
|
1402
|
+
|
|
1403
|
+
/**
|
|
1404
|
+
* Create n forked sessions sharing cookies and TLS session caches.
|
|
1405
|
+
*
|
|
1406
|
+
* Forked sessions simulate multiple browser tabs from the same browser:
|
|
1407
|
+
* same cookies, same TLS resumption tickets, same fingerprint, but
|
|
1408
|
+
* independent connections for parallel requests.
|
|
1409
|
+
*
|
|
1410
|
+
* @param {number} n - Number of sessions to create
|
|
1411
|
+
* @returns {Session[]} Array of new Session objects
|
|
1412
|
+
*/
|
|
1413
|
+
fork(n = 1) {
|
|
1414
|
+
const forks = [];
|
|
1415
|
+
for (let i = 0; i < n; i++) {
|
|
1416
|
+
const handle = this._lib.httpcloak_session_fork(this._handle);
|
|
1417
|
+
if (handle < 0 || handle === 0n) {
|
|
1418
|
+
throw new HTTPCloakError("Failed to fork session");
|
|
1419
|
+
}
|
|
1420
|
+
const session = Object.create(Session.prototype);
|
|
1421
|
+
session._lib = this._lib;
|
|
1422
|
+
session._handle = handle;
|
|
1423
|
+
session.headers = { ...this.headers };
|
|
1424
|
+
session.auth = this.auth;
|
|
1425
|
+
forks.push(session);
|
|
1426
|
+
}
|
|
1427
|
+
return forks;
|
|
1428
|
+
}
|
|
1429
|
+
|
|
1354
1430
|
/**
|
|
1355
1431
|
* Merge session headers with request headers
|
|
1356
1432
|
*/
|
|
@@ -1989,7 +2065,7 @@ class Session {
|
|
|
1989
2065
|
* @param {string} path - Path to save the session file
|
|
1990
2066
|
*
|
|
1991
2067
|
* Example:
|
|
1992
|
-
* const session = new httpcloak.Session({ preset: "chrome-
|
|
2068
|
+
* const session = new httpcloak.Session({ preset: "chrome-145" });
|
|
1993
2069
|
* await session.get("https://example.com"); // Acquire cookies
|
|
1994
2070
|
* session.save("session.json");
|
|
1995
2071
|
*
|
|
@@ -2627,7 +2703,7 @@ let _defaultConfig = {};
|
|
|
2627
2703
|
/**
|
|
2628
2704
|
* Configure defaults for module-level functions
|
|
2629
2705
|
* @param {Object} options - Configuration options
|
|
2630
|
-
* @param {string} [options.preset="chrome-
|
|
2706
|
+
* @param {string} [options.preset="chrome-145"] - Browser preset
|
|
2631
2707
|
* @param {Object} [options.headers] - Default headers
|
|
2632
2708
|
* @param {Array} [options.auth] - Default basic auth [username, password]
|
|
2633
2709
|
* @param {string} [options.proxy] - Proxy URL
|
|
@@ -2641,7 +2717,7 @@ let _defaultConfig = {};
|
|
|
2641
2717
|
*/
|
|
2642
2718
|
function configure(options = {}) {
|
|
2643
2719
|
const {
|
|
2644
|
-
preset = "chrome-
|
|
2720
|
+
preset = "chrome-145",
|
|
2645
2721
|
headers = null,
|
|
2646
2722
|
auth = null,
|
|
2647
2723
|
proxy = null,
|
|
@@ -2699,7 +2775,7 @@ function configure(options = {}) {
|
|
|
2699
2775
|
*/
|
|
2700
2776
|
function _getDefaultSession() {
|
|
2701
2777
|
if (!_defaultSession) {
|
|
2702
|
-
const preset = _defaultConfig.preset || "chrome-
|
|
2778
|
+
const preset = _defaultConfig.preset || "chrome-145";
|
|
2703
2779
|
const proxy = _defaultConfig.proxy || null;
|
|
2704
2780
|
const timeout = _defaultConfig.timeout || 30;
|
|
2705
2781
|
const httpVersion = _defaultConfig.httpVersion || "auto";
|
|
@@ -2802,7 +2878,7 @@ function request(method, url, options = {}) {
|
|
|
2802
2878
|
* Without registration, cache callbacks will not be triggered for that session.
|
|
2803
2879
|
*
|
|
2804
2880
|
* @example
|
|
2805
|
-
* const proxy = new LocalProxy({ preset: "chrome-
|
|
2881
|
+
* const proxy = new LocalProxy({ preset: "chrome-145", tlsOnly: true });
|
|
2806
2882
|
* console.log(`Proxy running on ${proxy.proxyUrl}`);
|
|
2807
2883
|
*
|
|
2808
2884
|
* // Use with any HTTP client pointing to the proxy
|
|
@@ -2831,7 +2907,7 @@ class LocalProxy {
|
|
|
2831
2907
|
* Create and start a local HTTP proxy server.
|
|
2832
2908
|
* @param {Object} options - Proxy configuration options
|
|
2833
2909
|
* @param {number} [options.port=0] - Port to listen on (0 = auto-select)
|
|
2834
|
-
* @param {string} [options.preset="chrome-
|
|
2910
|
+
* @param {string} [options.preset="chrome-145"] - Browser fingerprint preset
|
|
2835
2911
|
* @param {number} [options.timeout=30] - Request timeout in seconds
|
|
2836
2912
|
* @param {number} [options.maxConnections=1000] - Maximum concurrent connections
|
|
2837
2913
|
* @param {string} [options.tcpProxy] - Default upstream TCP proxy URL
|
|
@@ -2841,7 +2917,7 @@ class LocalProxy {
|
|
|
2841
2917
|
constructor(options = {}) {
|
|
2842
2918
|
const {
|
|
2843
2919
|
port = 0,
|
|
2844
|
-
preset = "chrome-
|
|
2920
|
+
preset = "chrome-145",
|
|
2845
2921
|
timeout = 30,
|
|
2846
2922
|
maxConnections = 1000,
|
|
2847
2923
|
tcpProxy = null,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "httpcloak",
|
|
3
|
-
"version": "1.6.0
|
|
3
|
+
"version": "1.6.0",
|
|
4
4
|
"description": "Browser fingerprint emulation HTTP client with HTTP/1.1, HTTP/2, and HTTP/3 support",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"module": "lib/index.mjs",
|
|
@@ -49,12 +49,12 @@
|
|
|
49
49
|
"koffi": "^2.9.0"
|
|
50
50
|
},
|
|
51
51
|
"optionalDependencies": {
|
|
52
|
-
"@httpcloak/darwin-arm64": "1.6.0
|
|
53
|
-
"@httpcloak/darwin-x64": "1.6.0
|
|
54
|
-
"@httpcloak/linux-arm64": "1.6.0
|
|
55
|
-
"@httpcloak/linux-x64": "1.6.0
|
|
56
|
-
"@httpcloak/win32-arm64": "1.6.0
|
|
57
|
-
"@httpcloak/win32-x64": "1.6.0
|
|
52
|
+
"@httpcloak/darwin-arm64": "1.6.0",
|
|
53
|
+
"@httpcloak/darwin-x64": "1.6.0",
|
|
54
|
+
"@httpcloak/linux-arm64": "1.6.0",
|
|
55
|
+
"@httpcloak/linux-x64": "1.6.0",
|
|
56
|
+
"@httpcloak/win32-arm64": "1.6.0",
|
|
57
|
+
"@httpcloak/win32-x64": "1.6.0"
|
|
58
58
|
},
|
|
59
59
|
"devDependencies": {
|
|
60
60
|
"@types/node": "^25.1.0",
|