wreq-js 0.2.0 → 1.1.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 CHANGED
@@ -1,260 +1,202 @@
1
1
  # wreq-js
2
2
 
3
- High-performance Node.js bindings for the Rust-based wreq HTTP client with native TLS and HTTP/2 browser impersonation.
3
+ High-performance HTTP client for Node.JS with real-browser TLS and HTTP/2 fingerprints, powered by Rust.
4
4
 
5
- Note: This is a personal fork of [will-work-for-meal/node-wreq](https://github.com/will-work-for-meal/node-wreq) (originally named node-wreq) with ongoing maintenance and faster dependency updates.
5
+ - ⚡️ A modern, actively maintained alternative to outdated browser-impersonating clients and legacy wrappers.
6
+ - When it comes to web scraping and automation, keeping up with the latest developments is NOT optional. Detection systems like Akamai and Cloudflare change every day using machine learning, old fingerprints are quickly detected.
7
+ - `wreq-js` builds upon the Rust-based [`wreq`](https://github.com/0x676e67/wreq) engine to deliver drop-in Node.js bindings that feel like `fetch()` but behave like a real browser.
6
8
 
7
- ## Features
8
-
9
- - Native performance (no process spawning)
10
- - TLS fingerprinting (JA3/JA4) aligned with real browsers
11
- - HTTP/2 fingerprinting: SETTINGS, PRIORITY, and header ordering
12
- - Multiple browser profiles (Chrome, Firefox, Safari, Edge, Opera, OkHttp)
13
- - WebSocket support
14
- - TypeScript definitions included
15
-
16
- ## How It Works
17
-
18
- The library provides Node.js bindings over [wreq](https://github.com/0x676e67/wreq), a Rust HTTP client that uses BoringSSL to replicate browser network behavior at the TLS and HTTP/2 layers.
19
-
20
- ### Why It Works
9
+ > This is my maintained fork of [will-work-for-meal/node-wreq](https://github.com/will-work-for-meal/node-wreq), originally named `node-wreq`, with ongoing updates and dependency refreshes for compatibility and speed.
21
10
 
22
- Traditional HTTP clients (axios, fetch, curl) have differences in:
23
- - **TLS handshake signatures** — Different cipher suites and extensions
24
- - **HTTP/2 frame ordering** — Different SETTINGS and PRIORITY patterns
25
- - **Header ordering** — Different sequence and values
26
-
27
- This library reproduces browser network behavior with high fidelity.
28
-
29
- ### Browser Profiles and wreq-util
11
+ ## Features
30
12
 
31
- - Browser profiles are generally tracked in the upstream `wreq-util` project; we depend on it for compatibility and support.
32
- - Profiles in this package are available in `src/generated-types.ts` and are automatically generated from the `wreq-util` codebase to improve update speed and reduce maintenance overhead.
33
- - Use `getProfiles()` to query the current set of supported profiles programmatically.
13
+ - **Native performance** no process spawning or browser overhead
14
+ - **Real browser TLS fingerprints** (JA3/JA4)
15
+ - **HTTP/2 impersonation** replicates SETTINGS, PRIORITY, and header ordering
16
+ - **Multiple browser profiles** — Chrome, Firefox, Safari, Edge, Opera, OkHttp
17
+ - **WebSocket support** with browser fingerprint consistency
18
+ - **Prebuilt native binaries** for macOS, Linux, and Windows
19
+ - **TypeScript-ready** with generated definitions
34
20
 
35
21
  ## Installation
36
22
 
37
23
  ```bash
38
- # From GitHub (this fork)
39
- # Latest master branch
40
24
  npm install wreq-js
25
+ # or
41
26
  yarn add wreq-js
42
27
  pnpm add wreq-js
43
28
  bun add wreq-js
44
-
45
- # From npm registry (original repo as node-wreq)
46
- npm install node-wreq
47
- yarn add node-wreq
48
- pnpm add node-wreq
49
- bun add node-wreq
50
29
  ```
51
30
 
52
- Pre-built native modules are included for major platforms:
53
- - macOS (Intel and Apple Silicon)
54
- - Linux (x64 and ARM64)
31
+ Prebuilt binaries are provided for:
32
+ - macOS (Intel & Apple Silicon)
33
+ - Linux (x64 & ARM64)
55
34
  - Windows (x64)
56
35
 
57
- Note on GitHub installs: if a matching prebuilt binary is not available for the referenced tag/commit, installation may build from source. Ensure a Rust toolchain and platform build prerequisites are installed.
36
+ > ⚠️ If a prebuilt binary for your platform or commit is unavailable, the package will build from source.
37
+ > Make sure a Rust toolchain and required build dependencies are installed.
58
38
 
59
- ## Usage
39
+ ## Why It Exists
40
+
41
+ HTTP clients like `axios`, `fetch`, `got`, `curl` do not behave like browsers on the network layer.
42
+ They differ in:
43
+
44
+ - **TLS handshake** - unique cipher suite order and extension sets
45
+ - **HTTP/2 frames** - different SETTINGS and PRIORITY sequences
46
+ - **Header ordering** - deterministic but non-browser-compliant
47
+
48
+ These subtle differences are enough for modern detection systems to identify automation.
49
+ `wreq-js` reproduces browser networking behavior using the `wreq` Rust engine underneath.
50
+ Your job is to write scripts, ours is to make them undetectable, yet effortless.
51
+
52
+ ## Architecture Overview
53
+
54
+ `wreq-js` provides Node.js bindings over [`wreq`](https://github.com/0x676e67/wreq), a Rust HTTP client built on **BoringSSL** to emulate browser TLS and HTTP/2 stacks.
55
+ Browser profiles are defined in the upstream [`wreq-util`](https://github.com/0x676e67/wreq-util) project and automatically synchronized here for faster updates.
56
+
57
+ To query supported profiles:
58
+
59
+ ```typescript
60
+ import { getProfiles } from 'wreq-js';
61
+ console.log(getProfiles());
62
+ // ['chrome_142', 'firefox_139', 'edge_120', 'safari_18', ...]
63
+ ```
60
64
 
61
- ### Basic Request
65
+ ## Quick Start
62
66
 
63
67
  ```typescript
64
- import { request } from 'wreq-js';
68
+ import { fetch } from 'wreq-js';
65
69
 
66
- const response = await request({
67
- url: 'https://example.com/api',
68
- browser: 'chrome_137',
70
+ const response = await fetch('https://example.com/api', {
71
+ browser: 'chrome_142',
69
72
  });
70
73
 
71
- console.log(response.status); // 200
72
- console.log(response.body); // Response body
73
- console.log(response.headers); // Response headers
74
- console.log(response.cookies); // Cookies
74
+ console.log(await response.json());
75
75
  ```
76
76
 
77
- ### With Custom Headers
77
+ That’s it, you now have full browser impersonation, drop-in compatibility with the `fetch()` API.
78
+
79
+ ## Advanced Usage
80
+
81
+ ### Custom Headers
78
82
 
79
83
  ```typescript
80
- import { request } from 'wreq-js';
84
+ import { fetch, Headers } from 'wreq-js';
81
85
 
82
- const response = await request({
83
- url: 'https://api.example.com/data',
86
+ const response = await fetch('https://api.example.com/data', {
84
87
  browser: 'firefox_139',
85
- headers: {
86
- 'Authorization': 'Bearer token123',
88
+ headers: new Headers({
89
+ Authorization: 'Bearer token123',
87
90
  'Custom-Header': 'value',
91
+ }),
92
+ });
93
+ ```
94
+
95
+ By default, browser emulation headers (like `Accept`, `Accept-Language`, `User-Agent`, etc.) are automatically added and may be appended to your custom headers. To prevent this and use **only** your custom headers:
96
+
97
+ ```typescript
98
+ const response = await fetch('https://api.example.com/data', {
99
+ browser: 'chrome_142',
100
+ headers: {
101
+ 'Accept': '*/*',
102
+ 'User-Agent': 'CustomBot/1.0',
88
103
  },
104
+ disableDefaultHeaders: true, // Disable emulation headers
89
105
  });
90
106
  ```
91
107
 
92
108
  ### POST Request
93
109
 
94
110
  ```typescript
95
- import { post } from 'wreq-js';
96
-
97
- const response = await post(
98
- 'https://api.example.com/submit',
99
- JSON.stringify({ foo: 'bar' }),
100
- {
101
- browser: 'chrome_137',
102
- headers: {
103
- 'Content-Type': 'application/json',
104
- },
105
- }
106
- );
111
+ const res = await fetch('https://api.example.com/submit', {
112
+ method: 'POST',
113
+ browser: 'chrome_142',
114
+ headers: { 'Content-Type': 'application/json' },
115
+ body: JSON.stringify({ foo: 'bar' }),
116
+ });
107
117
  ```
108
118
 
109
- ### Convenience Methods
119
+ ## Session & Cookie Isolation
120
+
121
+ Each `fetch()` call runs in **ephemeral mode** so that TLS caches, cookies, and session data never leak across requests.
122
+ To persist state, use `createSession()` or `withSession()`:
110
123
 
111
124
  ```typescript
112
- import { get, post } from 'wreq-js';
125
+ import { createSession, withSession } from 'wreq-js';
113
126
 
114
- // GET request
115
- const data = await get('https://api.example.com/users');
127
+ const session = await createSession({ browser: 'chrome_142' });
128
+ await session.fetch('https://example.com/login', { method: 'POST', body: '...' });
129
+ await session.fetch('https://example.com/dashboard');
130
+ await session.close();
116
131
 
117
- // POST request
118
- const result = await post(
119
- 'https://api.example.com/users',
120
- JSON.stringify({ name: 'John' })
121
- );
122
- ```
132
+ // Auto-disposing helper
133
+ await withSession(async (s) => {
134
+ await s.fetch('https://example.com/a');
135
+ await s.fetch('https://example.com/b');
136
+ });
123
137
 
124
- ### With Proxy
138
+ For finer control:
125
139
 
126
140
  ```typescript
127
- import { request } from 'wreq-js';
128
-
129
- const response = await request({
130
- url: 'https://example.com',
131
- browser: 'chrome_137',
132
- // proxy: 'http://proxy.example.com:8080',
133
- // proxy: 'http://username:password@proxy.example.com:8080',
134
- // proxy: 'socks5://proxy.example.com:1080',
141
+ await fetch('https://example.com', {
142
+ sessionId: 'user-42',
143
+ cookieMode: 'session',
135
144
  });
136
145
  ```
137
146
 
138
- ### WebSocket Connection
147
+ ## WebSocket Example
139
148
 
140
149
  ```typescript
141
150
  import { websocket } from 'wreq-js';
142
151
 
143
152
  const ws = await websocket({
144
153
  url: 'wss://echo.websocket.org',
145
- browser: 'chrome_137',
146
- onMessage: (data) => {
147
- console.log('Received:', data);
148
- },
149
- onClose: () => {
150
- console.log('Connection closed');
151
- },
152
- onError: (error) => {
153
- console.error('Error:', error);
154
- },
154
+ browser: 'chrome_142',
155
+ onMessage: (data) => console.log('Received:', data),
155
156
  });
156
157
 
157
- // Send text message
158
158
  await ws.send('Hello!');
159
-
160
- // Send binary message
161
- await ws.send(Buffer.from([1, 2, 3]));
162
-
163
- // Close connection
164
159
  await ws.close();
165
160
  ```
166
161
 
167
162
  ## API Reference
168
163
 
169
- ### `request(options:` [`RequestOptions`](#requestoptions)`): Promise<`[`Response`](#response)`>`
170
-
171
- Main function for making HTTP requests with browser impersonation.
172
-
173
- **Options:**
174
- <a name="requestoptions"></a>
164
+ The API is aiming to be `fetch`-compatible, with a few `wreq`-specific extensions.
165
+ See inline TypeScript definitions for complete typings.
175
166
 
176
167
  ```typescript
177
- interface RequestOptions {
178
- url: string; // Required: URL to request
179
- browser?: BrowserProfile; // Default: 'chrome_137'
180
- method?: HttpMethod; // Default: 'GET'
181
- headers?: Record<string, string>;
182
- body?: string;
183
- proxy?: string; // HTTP/HTTPS/SOCKS5 proxy URL
184
- timeout?: number; // Default: 30000ms
168
+ interface RequestInit {
169
+ method?: string;
170
+ headers?: HeadersInit;
171
+ body?: BodyInit | null;
172
+ signal?: AbortSignal | null;
173
+ redirect?: 'follow';
174
+ browser?: BrowserProfile;
175
+ proxy?: string;
176
+ timeout?: number;
177
+ cookieMode?: 'session' | 'ephemeral';
178
+ session?: Session;
179
+ sessionId?: string;
180
+ disableDefaultHeaders?: boolean; // Prevent emulation headers from being appended
185
181
  }
186
182
  ```
187
183
 
188
- **Response:**
189
- <a name="response"></a>
190
-
191
- ```typescript
192
- interface Response {
193
- status: number;
194
- headers: Record<string, string>;
195
- body: string;
196
- cookies: Record<string, string>;
197
- url: string; // Final URL after redirects
198
- }
199
- ```
200
-
201
- ### `get(url: string, options?): Promise<`[`Response`](#response)`>`
202
-
203
- ### `post(url: string, body?: string, options?): Promise<`[`Response`](#response)`>`
204
-
205
- ### `websocket(options:` [`WebSocketOptions`](#websocketoptions)`): Promise<WebSocket>`
206
-
207
-
208
- **Options:**
209
- <a name="websocketoptions"></a>
210
-
211
- ```typescript
212
- interface WebSocketOptions {
213
- url: string; // Required: WebSocket URL (ws:// or wss://)
214
- browser?: BrowserProfile; // Default: 'chrome_137'
215
- headers?: Record<string, string>;
216
- proxy?: string; // HTTP/HTTPS/SOCKS5 proxy URL
217
- onMessage: (data: string | Buffer) => void; // Required: Message callback
218
- onClose?: () => void; // Optional: Close callback
219
- onError?: (error: string) => void; // Optional: Error callback
220
- }
221
- ```
222
-
223
- **WebSocket Methods:**
224
-
225
- ```typescript
226
- class WebSocket {
227
- send(data: string | Buffer): Promise<void>;
228
- close(): Promise<void>;
229
- }
230
- ```
231
-
232
- ### `getProfiles():` [`BrowserProfile[]`](#browser-profiles)
233
-
234
- Get list of available browser profiles.
235
-
236
- ```typescript
237
- import { getProfiles } from 'wreq-js';
238
-
239
- const profiles = getProfiles();
240
-
241
- console.log(profiles);
242
- // ['chrome_100', 'chrome_101', ..., 'chrome_137', 'edge_101', ..., 'safari_18', ...]
243
- ```
244
-
245
184
  ## Documentation
246
185
 
247
- - **[Architecture Guide](docs/ARCHITECTURE.md)** Technical details about TLS/HTTP2 fingerprinting, how browser impersonation works
248
- - **[Build Instructions](docs/BUILD.md)** Developer guide for building from source
249
- - **[Publishing Guide](docs/PUBLISHING.md)** How to publish the package
186
+ - **[Architecture Guide](docs/ARCHITECTURE.md)** - How fingerprinting and impersonation work
187
+ - **[Build Instructions](docs/BUILD.md)** - Build from source
188
+ - **[Publishing Guide](docs/PUBLISHING.md)** - Releasing new versions
250
189
 
251
190
  ## Contributing
252
191
 
253
192
  Please read the [Contributing Guide](CONTRIBUTING.md).
254
193
 
194
+ ## Origins
195
+ This project began as a fork of [will-work-for-meal/node-wreq](https://github.com/will-work-for-meal/node-wreq) but has since evolved into an independent implementation with extensive rewrites, new APIs, and active maintenance. It is not affiliated with the original project.
196
+
255
197
  ## Acknowledgments
256
198
 
257
- - [wreq](https://github.com/0x676e67/wreq) Rust HTTP client with browser impersonation
258
- - [wreq-util](https://github.com/0x676e67/wreq-util) Upstream utility project that tracks and ships browser fingerprint updates rapidly
259
- - [Neon](https://neon-bindings.com/) Rust ↔ Node.js bindings
260
- - Original Node.js wrapper: [will-work-for-meal/node-wreq](https://github.com/will-work-for-meal/node-wreq) (named node-wreq) clean, well-written baseline this fork builds on
199
+ - [wreq](https://github.com/0x676e67/wreq) - Rust HTTP client with browser impersonation
200
+ - [wreq-util](https://github.com/0x676e67/wreq-util) - Source of up-to-date browser profiles
201
+ - [Neon](https://neon-bindings.com/) - Rust ↔ Node.js bindings
202
+ - [will-work-for-meal/node-wreq](https://github.com/will-work-for-meal/node-wreq) - Original Node.js wrapper foundation
@@ -0,0 +1,7 @@
1
+ export interface LocalTestServer {
2
+ httpBaseUrl: string;
3
+ wsUrl: string;
4
+ close(): Promise<void>;
5
+ }
6
+ export declare function startLocalTestServer(): Promise<LocalTestServer>;
7
+ //# sourceMappingURL=local-test-server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"local-test-server.d.ts","sourceRoot":"","sources":["../../../src/test/helpers/local-test-server.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,eAAe;IAC9B,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB;AAED,wBAAsB,oBAAoB,IAAI,OAAO,CAAC,eAAe,CAAC,CA2MrE"}