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 +123 -181
- package/dist/test/helpers/local-test-server.d.ts +7 -0
- package/dist/test/helpers/local-test-server.d.ts.map +1 -0
- package/dist/test/helpers/local-test-server.js +305 -0
- package/dist/test/helpers/local-test-server.js.map +1 -0
- package/dist/test/http.spec.js +141 -12
- package/dist/test/http.spec.js.map +1 -1
- package/dist/test/run-with-local-server.d.ts +2 -0
- package/dist/test/run-with-local-server.d.ts.map +1 -0
- package/dist/test/run-with-local-server.js +61 -0
- package/dist/test/run-with-local-server.js.map +1 -0
- package/dist/test/websocket.spec.js +13 -16
- package/dist/test/websocket.spec.js.map +1 -1
- package/dist/types.d.ts +285 -28
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +15 -0
- package/dist/types.js.map +1 -1
- package/dist/wreq-js.d.ts +79 -54
- package/dist/wreq-js.d.ts.map +1 -1
- package/dist/wreq-js.js +563 -63
- package/dist/wreq-js.js.map +1 -1
- package/package.json +13 -10
- package/rust/wreq-js.darwin-arm64.node +0 -0
- package/rust/wreq-js.darwin-x64.node +0 -0
- package/rust/wreq-js.linux-arm64-gnu.node +0 -0
- package/rust/wreq-js.linux-x64-gnu.node +0 -0
- package/rust/wreq-js.win32-x64-msvc.node +0 -0
package/README.md
CHANGED
|
@@ -1,260 +1,202 @@
|
|
|
1
1
|
# wreq-js
|
|
2
2
|
|
|
3
|
-
High-performance
|
|
3
|
+
High-performance HTTP client for Node.JS with real-browser TLS and HTTP/2 fingerprints, powered by Rust.
|
|
4
4
|
|
|
5
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
-
|
|
32
|
-
-
|
|
33
|
-
-
|
|
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
|
-
|
|
53
|
-
- macOS (Intel
|
|
54
|
-
- Linux (x64
|
|
31
|
+
Prebuilt binaries are provided for:
|
|
32
|
+
- macOS (Intel & Apple Silicon)
|
|
33
|
+
- Linux (x64 & ARM64)
|
|
55
34
|
- Windows (x64)
|
|
56
35
|
|
|
57
|
-
|
|
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
|
-
##
|
|
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
|
-
|
|
65
|
+
## Quick Start
|
|
62
66
|
|
|
63
67
|
```typescript
|
|
64
|
-
import {
|
|
68
|
+
import { fetch } from 'wreq-js';
|
|
65
69
|
|
|
66
|
-
const response = await
|
|
67
|
-
|
|
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.
|
|
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
|
-
|
|
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 {
|
|
84
|
+
import { fetch, Headers } from 'wreq-js';
|
|
81
85
|
|
|
82
|
-
const response = await
|
|
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
|
-
|
|
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
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
'
|
|
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
|
-
|
|
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 {
|
|
125
|
+
import { createSession, withSession } from 'wreq-js';
|
|
113
126
|
|
|
114
|
-
|
|
115
|
-
|
|
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
|
-
//
|
|
118
|
-
|
|
119
|
-
'https://
|
|
120
|
-
|
|
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
|
-
|
|
138
|
+
For finer control:
|
|
125
139
|
|
|
126
140
|
```typescript
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
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
|
-
|
|
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: '
|
|
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
|
-
|
|
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
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
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)**
|
|
248
|
-
- **[Build Instructions](docs/BUILD.md)**
|
|
249
|
-
- **[Publishing Guide](docs/PUBLISHING.md)**
|
|
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)
|
|
258
|
-
- [wreq-util](https://github.com/0x676e67/wreq-util)
|
|
259
|
-
- [Neon](https://neon-bindings.com/)
|
|
260
|
-
-
|
|
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 @@
|
|
|
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"}
|