# fetch() Source: https://wreq.sqdsh.win/api-reference/fetch Make HTTP requests with browser profile and transport options. ## Signature ```typescript theme={null} function fetch(input: string | URL | Request, init?: RequestInit): Promise ``` ## Parameters The resource to fetch. Can be a URL string, URL object, or a Request object. Optional request configuration. ## RequestInit options HTTP method: `GET`, `POST`, `PUT`, `DELETE`, `PATCH`, `HEAD`, `OPTIONS`. Request headers. Can be a `Headers` object, plain object, or array of key-value pairs. Request body. Supported types: `string`, `Buffer`, `URLSearchParams`, `ArrayBuffer`, `ArrayBufferView` (for example `Uint8Array`), `Blob`, `FormData`, `ReadableStream`, and any sync or async iterable of `Uint8Array`. Stream and iterable bodies are read fully into memory before the request is sent, so an unbounded stream means an unbounded allocation. Reusable transport context for this request (proxy + emulation settings, with connection behavior handled by the native layer). When provided, you must not also set `browser`, `os`, `proxy`, or `insecure`. Browser fingerprint profile to use (e.g., `'chrome_142'`, `'firefox_139'`), or a family alias such as `'firefox'` that resolves to the newest profile in that family. See [browser profiles](/concepts/browser-profiles#family-aliases). Operating system to emulate: `'windows'`, `'macos'`, `'linux'`, `'android'`, `'ios'`. Proxy URL. Support depends on the native layer and proxy scheme. Request timeout in milliseconds. Set to `0` to disable the timeout. AbortSignal for cancelling the request. Redirect handling mode. When `true`, prevents browser emulation headers from being automatically added. When `true`, accepts invalid/self-signed certificates. **Use only in development.** Optional callback for structured request lifecycle events emitted by the native layer. Use this to observe phases such as request start, response headers, and body download progress. When `true`, captures a final diagnostics payload on the response where supported by the native layer. This can include timing, address, and TLS peer details. ## Response Returns a `Response` object with: * `status`: HTTP status code * `statusText`: HTTP status text * `headers`: response headers * `ok`: `true` if status is 200-299 * `url`: final URL after redirects * `redirected`: `true` if the response is the result of a redirect * `body`: `ReadableStream` or `null` * `bodyUsed`: `true` if body has been consumed * `contentLength`: content length from headers, or `null` * `cookies`: parsed response cookies as `Record` * `diagnostics`: optional native diagnostics payload, or `null` ### Response methods * `json()`: parse body as JSON * `text()`: get body as string * `arrayBuffer()`: get body as ArrayBuffer * `bytes()`: get body as Uint8Array * `blob()`: get body as Blob * `formData()`: parse body as FormData * `clone()`: clone the response See [/concepts/compatibility-matrix](/concepts/compatibility-matrix) for detailed compatibility notes and intentional deviations. ## Request lifecycle events When `onRequestEvent` is provided, `fetch()` emits structured events from the native bridge. | Event | Meaning | | ------------------ | -------------------------------------------------------------------------------------------------------- | | `request_start` | The request has started in the native layer. | | `request_sent` | Request headers/body have been handed off to the socket and the client is waiting for a response. | | `response_headers` | Response headers have been received. Includes `status` and optional `contentLength`. | | `body_progress` | Additional response body bytes were downloaded. Includes `downloadedBytes` and optional `contentLength`. | | `body_complete` | The response body finished downloading. | | `done` | The native request lifecycle completed successfully. | | `error` | The native request lifecycle failed. Includes `message` when available. | Each event includes a `timestamp`, and some events include `status`, `url`, `contentLength`, `downloadedBytes`, or `message`. For a full worked example, see [/guides/request-events](/guides/request-events). ## Convenience helpers ```typescript theme={null} import { get, post, request } from 'wreq-js'; ``` * `get(url, init?)` calls `fetch(url, { ...init, method: "GET" })`. * `post(url, body?, init?)` calls `fetch(url, { ...init, method: "POST", body })`. * `request(options)` is deprecated and kept for compatibility. Prefer `fetch(url, init)`. ## Examples ### Basic GET request ```typescript theme={null} import { fetch } from 'wreq-js'; const response = await fetch('https://api.example.com/data', { browser: 'chrome_142', }); const data = await response.json(); ``` ### POST with JSON body ```typescript theme={null} const response = await fetch('https://api.example.com/submit', { method: 'POST', browser: 'chrome_142', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ name: 'John', email: 'john@example.com' }), }); ``` ### POST with form data ```typescript theme={null} const response = await fetch('https://example.com/login', { method: 'POST', browser: 'chrome_142', body: new URLSearchParams({ username: 'user', password: 'pass', }), }); ``` ### Observe request events and diagnostics ```typescript theme={null} const response = await fetch('https://example.com/large-file', { browser: 'chrome_142', captureDiagnostics: true, onRequestEvent(event) { if (event.type === 'response_headers') { console.log('status:', event.status); console.log('content-length:', event.contentLength); } if (event.type === 'body_progress' && event.contentLength) { const pct = ((event.downloadedBytes ?? 0) / event.contentLength) * 100; console.log(`downloaded ${pct.toFixed(1)}%`); } }, }); console.log(response.diagnostics); ``` ### With timeout and abort ```typescript theme={null} const controller = new AbortController(); const timeoutId = setTimeout(() => controller.abort(), 5000); try { const response = await fetch('https://example.com/slow', { browser: 'chrome_142', timeout: 10000, signal: controller.signal, }); console.log(await response.text()); } finally { clearTimeout(timeoutId); } ``` ### Reuse connections via Transport ```typescript theme={null} import { createTransport, fetch } from "wreq-js"; const transport = await createTransport({ proxy: "http://proxy.example.com:8080" }); try { const response = await fetch("https://example.com", { transport }); console.log(await response.text()); } finally { await transport.close(); } ``` ### Custom headers without defaults ```typescript theme={null} const response = await fetch('https://api.example.com', { browser: 'chrome_142', headers: { 'User-Agent': 'MyBot/1.0', 'Accept': 'application/json', }, disableDefaultHeaders: true, }); ``` # API Overview Source: https://wreq.sqdsh.win/api-reference/overview Complete API reference for wreq-js. ## Exports wreq-js exports the following functions and classes: ```typescript theme={null} import { // Core functions fetch, request, get, post, createTransport, createSession, withSession, websocket, // Utilities getProfiles, getOperatingSystems, getEmulationHeaders, resolveProfile, // Classes Headers, Response, Transport, Session, WebSocket, // Errors RequestError, } from 'wreq-js'; ``` ## Quick reference | Function | Description | | ----------------------------------------------------------------------- | ----------------------------------------------- | | [`fetch()`](/api-reference/fetch) | Make HTTP requests with browser profile options | | `get()` / `post()` | Convenience wrappers around `fetch()` | | `request()` | Deprecated helper kept for compatibility | | [`createTransport()`](/api-reference/transport) | Create a reusable transport context | | [`createSession()`](/api-reference/sessions) | Create a persistent session with cookie storage | | [`withSession()`](/api-reference/sessions#withsession) | Auto-disposing session helper | | [`websocket()`](/api-reference/websocket) | Connect to WebSocket servers | | [`getProfiles()`](/api-reference/utilities#getprofiles) | List available browser profiles | | [`getOperatingSystems()`](/api-reference/utilities#getoperatingsystems) | List available operating systems | | [`getEmulationHeaders()`](/api-reference/utilities#getemulationheaders) | Read the headers a browser profile injects | | [`resolveProfile()`](/api-reference/utilities#resolveprofile) | Resolve a family alias to a concrete profile | ## TypeScript support wreq-js includes TypeScript definitions for its public API: ```typescript theme={null} import type { BrowserProfile, EmulationOS, RequestInit, CreateTransportOptions, CreateSessionOptions, Transport, Session, } from 'wreq-js'; ``` ## Fetch style surface wreq-js provides a fetch like API surface with additional transport and profile options: | Surface | wreq-js | | ---------------------- | ----------------------------------- | | `fetch(url, init)` | Available | | `fetch(Request, init)` | Available | | `Request` class export | Not currently exposed | | `Response` class | Available from the package | | `Headers` class | Available from the package | | `AbortController` | Standard signal inputs are accepted | | `ReadableStream` body | Available on response bodies | `Session`, `Transport`, and `WebSocket` are exported classes, but you should create them via `createSession()`, `createTransport()`, and `websocket()` or `new WebSocket(url, ...)`. Detailed compatibility notes live at [/concepts/compatibility-matrix](/concepts/compatibility-matrix). ## wreq-js extensions Additional options beyond the standard Fetch API: ```typescript theme={null} interface RequestInit { // Standard options method?: string; headers?: HeadersInit; body?: BodyInit | null; signal?: AbortSignal | null; redirect?: 'follow' | 'manual' | 'error'; // wreq-js extensions transport?: Transport; // Reusable transport (pool/proxy/browser/os) browser?: BrowserProfile; // Browser fingerprint profile os?: EmulationOS; // Operating system emulation proxy?: string; // Proxy URL timeout?: number; // Request timeout in ms session?: Session; // Bind to an existing session sessionId?: string; // Bind to a session by ID cookieMode?: 'session' | 'ephemeral'; // Cookie scoping strategy disableDefaultHeaders?: boolean; // Disable auto-added headers insecure?: boolean; // Accept invalid certificates } ``` # Sessions Source: https://wreq.sqdsh.win/api-reference/sessions Create and manage persistent sessions with cookie storage. ## createSession() Create a persistent session context for related requests. Within a session, `browser`, `os`, and `proxy` are fixed at creation time (unless you pass an explicit [`transport`](/api-reference/transport) per request). ### Signature ```typescript theme={null} function createSession(options?: CreateSessionOptions): Promise ``` ### Options Default browser fingerprint profile for all session requests. Default operating system to emulate. Default proxy URL for all session requests. Default request timeout in milliseconds. Default headers to include in every session request. Can be a `Headers` object, plain object, or array of key-value pairs. Explicit session identifier. When omitted, a random ID is generated. Accept invalid certificates for all session requests. **Use only in development.** Enable extra connection and TLS diagnostics for requests made through this session by default. ### Session object The returned `Session` object has: #### session.fetch(url, init?) Make a request using the session context. ```typescript theme={null} const response = await session.fetch('https://example.com/api', { method: 'POST', body: JSON.stringify({ data: 'value' }), }); ``` Per-request options override session defaults. `session.fetch()` also accepts request-scoped `onRequestEvent` and `captureDiagnostics` options from [`fetch()`](/api-reference/fetch). When diagnostics are enabled, inspect `response.diagnostics` on the returned response. #### session.websocket(url, options?) Open a WebSocket that reuses the session transport and context. Use this after login or any other HTTP flow that sets cookies. ```typescript theme={null} const ws = await session.websocket('wss://example.com/ws', { headers: { Authorization: 'Bearer token', }, }); ws.onmessage = (event) => { console.log(event.data); }; ws.close(); ``` `session.websocket(...)` accepts `headers`, `protocols`, and `binaryType`. It does not accept `browser`, `os`, or `proxy` because those are owned by the session transport. `protocols` values are validated for non-empty unique entries and sent in the `Sec-WebSocket-Protocol` handshake header. #### session.getCookies(url) Return cookies that would be sent to the given URL (RFC 6265 domain/path matching). ```typescript theme={null} const cookies: Record = session.getCookies('https://example.com'); // { "session_id": "abc123", "theme": "dark" } ``` Target URL. Only cookies whose domain and path match this URL are returned. **Returns** `Record` — cookie name/value pairs. #### session.getAllCookies() Return every cookie currently stored in the session jar, regardless of URL matching. ```typescript theme={null} const cookies = session.getAllCookies(); // [ // { // name: 'session_id', // value: 'abc123', // secure: true, // httpOnly: true, // domain: 'example.com', // path: '/', // }, // ] ``` **Returns** `SessionCookie[]` — all cookies in the jar, with scope metadata such as `domain`, `path`, `sameSite`, and `expiresAtMs` when available. #### session.setCookie(name, value, url) Add a cookie to the session jar, scoped to the domain/path of the given URL. ```typescript theme={null} session.setCookie('token', 'abc123', 'https://example.com'); ``` Cookie name. Cookie value. URL that determines the cookie's domain and path scope. #### session.clearCookies() Clear all cookies from the session cookie jar. ```typescript theme={null} await session.clearCookies(); ``` #### session.close() Close the session and release resources. Always call this when done. ```typescript theme={null} await session.close(); ``` ### Example ```typescript theme={null} import { createSession } from 'wreq-js'; const session = await createSession({ browser: 'chrome_142', os: 'windows', }); // Login in the same session context await session.fetch('https://example.com/login', { method: 'POST', body: new URLSearchParams({ user: 'name', pass: 'secret' }), }); // Subsequent requests use the same session context const profile = await session.fetch('https://example.com/profile'); console.log(await profile.json()); // Always close when done await session.close(); ``` *** ## withSession() Auto-disposing session helper that closes the session when the callback completes. ### Signature ```typescript theme={null} function withSession( fn: (session: Session) => Promise | T, options?: CreateSessionOptions ): Promise ``` ### Example ```typescript theme={null} import { withSession } from 'wreq-js'; const result = await withSession(async (session) => { await session.fetch('https://example.com/login', { method: 'POST', body: 'credentials', }); const response = await session.fetch('https://example.com/data'); return response.json(); }, { browser: 'chrome_142', }); // Session is automatically closed console.log(result); ``` ### With options ```typescript theme={null} const data = await withSession( async (session) => { const response = await session.fetch('https://example.com/api'); return response.json(); }, { browser: 'firefox_139', proxy: 'http://proxy.example.com:8080', } ); ``` *** ## Session vs. Ephemeral | Feature | Ephemeral (default `fetch`) | Session | | ------------------ | --------------------------- | --------------------------------------------- | | Cookies | Separate request context | Shared session context | | Transport settings | Request scoped | Session scoped unless overridden by transport | | Use case | Isolated requests | Multi-step flows | # Transport Source: https://wreq.sqdsh.win/api-reference/transport Reusable transport configuration for high-volume request workflows. ## What is a Transport? A `Transport` is a reusable network context handle for transport level settings such as browser profile, OS emulation, proxy, and TLS verification options. Use it when you want reusable transport settings without creating a full session per proxy, for example when you keep one transport handle per proxy in a long running worker. ## createTransport() Create a reusable transport. ### Signature ```typescript theme={null} function createTransport(options?: CreateTransportOptions): Promise ``` ### Options Proxy URL for all requests made through this transport. Support depends on the native layer and proxy scheme. Browser fingerprint profile to use for this transport, or a family alias such as `'firefox'` that resolves to the newest profile in that family. Operating system to emulate for this transport. When `true`, accepts invalid/self-signed certificates. Use only if you understand the security tradeoffs. Native transport idle timeout option (ms). Native transport per host idle connection limit option. Native transport total connection limit option. TCP connect timeout (ms). Read timeout (ms). Enable extra connection and TLS diagnostics for requests made through this transport by default. ## Using a transport with fetch() Pass the transport via `RequestInit.transport`. ```typescript theme={null} import { createTransport, fetch } from "wreq-js"; const transport = await createTransport({ proxy: "http://user:pass@proxy.example.com:8080", browser: "chrome_142", poolMaxSize: 64, }); try { const res = await fetch("https://httpbin.org/get", { transport, timeout: 10_000, }); console.log(res.status); } finally { await transport.close(); } ``` You can still pass per-request `onRequestEvent` callbacks when using a transport. If `captureDiagnostics` is enabled on the transport, returned responses expose `response.diagnostics` without having to repeat the flag on every request. ### Important: request options that become invalid When you provide `transport`, you must not also set `browser`, `os`, `proxy`, or `insecure` on that request. Those settings are owned by the transport. ## Thousands of proxies: recommended pattern Create **one transport per proxy**, reuse it for all requests that should go through that proxy, and close transports when you no longer need them. ```typescript theme={null} import { createTransport, fetch, type Transport } from "wreq-js"; const transports = new Map(); async function getTransportForProxy(proxy: string): Promise { const cached = transports.get(proxy); if (cached && !cached.closed) return cached; const transport = await createTransport({ proxy, poolMaxSize: 32 }); transports.set(proxy, transport); return transport; } export async function fetchViaProxy(url: string, proxy: string) { const transport = await getTransportForProxy(proxy); return fetch(url, { transport, timeout: 30_000 }); } export async function shutdown() { await Promise.all([...transports.values()].map((t) => t.close())); transports.clear(); } ``` ## Transport lifecycle ### transport.close() Always close transports you create. ```typescript theme={null} await transport.close(); ``` After closing, `transport.closed` becomes `true` and the transport can no longer be used. ## Sharing a transport across cookie jars If you need separate cookie jars with shared transport settings (for example, multiple sessions through the same proxy), you can pass the same transport to multiple `Session.fetch()` calls. # Utilities Source: https://wreq.sqdsh.win/api-reference/utilities Utility functions for browser profiles and configuration. ## getProfiles() Get a list of all available browser profile labels. ### Signature ```typescript theme={null} function getProfiles(): BrowserProfile[] ``` ### Returns Array of profile names that can be used with the `browser` option. ### Example ```typescript theme={null} import { getProfiles } from 'wreq-js'; const profiles = getProfiles(); console.log(profiles); // Example output: ['chrome_142', 'firefox_139', 'safari_18', ...] ``` ### Using a random profile ```typescript theme={null} import { fetch, getProfiles } from 'wreq-js'; const profiles = getProfiles(); const randomProfile = profiles[Math.floor(Math.random() * profiles.length)]; const response = await fetch('https://example.com', { browser: randomProfile, }); ``` *** ## getOperatingSystems() Get a list of all available operating systems for emulation. ### Signature ```typescript theme={null} function getOperatingSystems(): EmulationOS[] ``` ### Returns Array of OS names that can be used with the `os` option. ### Example ```typescript theme={null} import { getOperatingSystems } from 'wreq-js'; const systems = getOperatingSystems(); console.log(systems); // Example output: ['windows', 'macos', 'linux', 'android', 'ios'] ``` ### Combining browser and OS ```typescript theme={null} import { fetch, getProfiles, getOperatingSystems } from 'wreq-js'; // Chrome on Windows const response = await fetch('https://example.com', { browser: 'chrome_142', os: 'windows', }); // Safari on iOS const mobileResponse = await fetch('https://example.com', { browser: 'safari_18', os: 'ios', }); ``` *** ## resolveProfile() Resolve a browser family alias to the concrete profile it points at. ### Signature ```typescript theme={null} function resolveProfile(browser: BrowserProfile | BrowserAlias): BrowserProfile ``` ### Returns The concrete profile. Concrete profiles pass through unchanged, so this is safe to call on any value accepted by the `browser` option. ### Example ```typescript theme={null} import { resolveProfile } from 'wreq-js'; resolveProfile('firefox'); // 'firefox_149' resolveProfile('firefox_143'); // 'firefox_143' ``` An alias resolves against the profile set shipped with your installed version of wreq-js, so the result moves when you upgrade. Log it when you need to know which fingerprint a given run actually used. *** ## getEmulationHeaders() Get the headers a browser profile injects into every request, without sending one. ### Signature ```typescript theme={null} function getEmulationHeaders(browser?: BrowserProfile, os?: EmulationOS): Headers ``` Both arguments default to the same profile and OS as [`fetch`](/api-reference/fetch). ### Returns A `Headers` instance holding the profile's headers, in the profile's own order and casing. Transport-level headers are not included: `Host`, `Connection`, `Content-Length`, and `Accept-Encoding` are added per request rather than by the emulation profile. ### Example ```typescript theme={null} import { getEmulationHeaders } from 'wreq-js'; const defaults = getEmulationHeaders('firefox_147'); console.log(defaults.get('user-agent')); // Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:147.0) Gecko/20100101 Firefox/147.0 ``` ### Reusing a profile's User-Agent Passing a header through `headers` replaces the profile's matching header and leaves the rest of the fingerprint intact, so read the value first when you want to build on it. ```typescript theme={null} import { fetch, getEmulationHeaders } from 'wreq-js'; const userAgent = getEmulationHeaders('firefox_147', 'windows').get('user-agent'); const response = await fetch('https://example.com', { browser: 'firefox_147', os: 'windows', headers: { 'X-Forwarded-User-Agent': userAgent ?? '' }, }); ``` *** ## Headers The `Headers` class for working with HTTP headers. ### Constructor ```typescript theme={null} declare class Headers { constructor(init?: HeadersInit); } ``` ### Methods * `append(name, value)`: add a header value * `delete(name)`: remove a header * `get(name)`: get a header value * `has(name)`: check if header exists * `set(name, value)`: set a header value * `entries()`: iterate over header entries * `keys()`: iterate over header names * `values()`: iterate over header values ### Example ```typescript theme={null} import { fetch, Headers } from 'wreq-js'; const headers = new Headers(); headers.set('Authorization', 'Bearer token'); headers.set('Content-Type', 'application/json'); const response = await fetch('https://api.example.com', { browser: 'chrome_142', headers, }); ``` *** ## Response The `Response` class representing HTTP responses. ### Properties * `status`: HTTP status code * `statusText`: HTTP status text * `headers`: response headers * `ok`: `true` if status is 200-299 * `url`: final URL after redirects * `redirected`: `true` if the response is the result of a redirect * `body`: `ReadableStream` or `null` * `bodyUsed`: `true` if body has been read * `contentLength`: content length from headers, or `null` * `cookies`: parsed response cookies as `Record` ### Methods * `json()`: parse body as JSON * `text()`: get body as string * `arrayBuffer()`: get body as ArrayBuffer * `bytes()`: get body as Uint8Array * `blob()`: get body as Blob * `formData()`: parse body as FormData * `clone()`: clone the response # websocket() Source: https://wreq.sqdsh.win/api-reference/websocket Connect to WebSocket servers with browser profile options. ## Signature ```typescript theme={null} function websocket(url: string | URL, options?: WebSocketOptions): Promise ``` `websocket(...)` resolves after the connection opens. ## Constructor shape `WebSocket` also supports constructor usage for browser-style ergonomics. ```typescript theme={null} declare class WebSocket { constructor(url: string | URL, protocols?: string | string[]); constructor(url: string | URL, options?: WebSocketOptions); constructor(url: string | URL, protocols?: string | string[], options?: WebSocketOptions); } ``` ## WebSocketOptions Browser fingerprint profile for the connection. Operating system fingerprint for the connection. Proxy URL for the connection. Additional headers for the WebSocket handshake. Optional subprotocol list for compatibility with standard WebSocket shape. Values are validated for non-empty unique entries and sent in the `Sec-WebSocket-Protocol` handshake header. Maximum size in bytes for a single incoming WebSocket frame. Increase this when the peer sends large unfragmented frames. Maximum size in bytes for a complete incoming WebSocket message. Increase this when the peer sends very large fragmented messages. Binary payload format exposed at `event.data`. ## Returned WebSocket instance The instance mirrors familiar WebSocket APIs. 1. Properties 1. `url` 2. `readyState` 3. `binaryType` 4. `bufferedAmount` 5. `protocol` 6. `extensions` 7. `onopen` 8. `onmessage` 9. `onclose` 10. `onerror` `protocol` and `extensions` reflect negotiated values from the upgrade response when the server provides them. 2. Methods 1. `send(data)` where data can be `string`, `Buffer`, `ArrayBuffer`, `ArrayBufferView`, or `Blob` 2. `close(code?, reason?)` 3. `addEventListener(type, listener)` 4. `removeEventListener(type, listener)` `close(code, reason)` accepts code `1000` or codes in the `3000` to `4999` range. When providing a reason, the UTF-8 byte length must be `123` or fewer. 3. Constants 1. `WebSocket.CONNECTING` 2. `WebSocket.OPEN` 3. `WebSocket.CLOSING` 4. `WebSocket.CLOSED` ## Session support For authenticated socket flows, use [`createSession()`](/api-reference/sessions) and then `session.websocket(url, options)`. Within a session, WebSocket uses the same session context and transport settings. ```typescript theme={null} import { createSession } from 'wreq-js'; const session = await createSession({ browser: 'chrome_142' }); await session.fetch('https://example.com/login', { method: 'POST', body: new URLSearchParams({ user: 'name', pass: 'secret' }), }); const ws = await session.websocket('wss://example.com/ws'); ws.onmessage = (event) => { console.log(event.data); }; ``` ## Examples ### Helper style ```typescript theme={null} import { websocket } from 'wreq-js'; const ws = await websocket('wss://example.com/socket', { browser: 'chrome_142', headers: { Authorization: 'Bearer token' }, }); ws.onmessage = (event) => { console.log(event.data); }; void ws.send('hello'); ``` ### Constructor style ```typescript theme={null} import { WebSocket } from 'wreq-js'; const ws = new WebSocket('wss://example.com/socket', { browser: 'firefox_139', proxy: 'http://proxy.example.com:8080', }); ws.addEventListener('open', () => { void ws.send(JSON.stringify({ type: 'ping' })); }); ws.addEventListener('close', (event) => { console.log(event.code, event.reason); }); ``` ### Binary payload mode ```typescript theme={null} const ws = await websocket('wss://example.com/socket', { browser: 'chrome_142' }); ws.binaryType = 'arraybuffer'; ws.onmessage = (event) => { if (event.data instanceof ArrayBuffer) { console.log('received array buffer', event.data.byteLength); } }; ``` ### Large incoming messages Some providers send very large WebSocket payloads in a single frame. If you see an error such as `Space limit exceeded: Message too long`, raise the frame or message limits explicitly. ```typescript theme={null} const ws = await websocket('wss://example.com/socket', { browser: 'chrome_142', maxFrameSize: 32 * 1024 * 1024, maxMessageSize: 32 * 1024 * 1024, }); ``` # Browser Profiles Source: https://wreq.sqdsh.win/concepts/browser-profiles Understand browser profiles and operating system emulation. ## What are browser profiles? Browser profiles define the network profile labels that `wreq-js` sends to the native layer. Profiles can influence behavior such as: 1. TLS handshake preferences 2. HTTP protocol behavior 3. Default request headers 4. Platform-specific header values Final wire behavior is determined by the native engine and may vary by profile and runtime. ## Available browsers wreq-js profile families include: 1. Chrome 2. Firefox 3. Safari 4. Edge 5. Opera 6. OkHttp ## Listing profiles ```typescript theme={null} import { getProfiles } from 'wreq-js'; const profiles = getProfiles(); console.log(profiles); // ['chrome_142', 'chrome_141', 'firefox_139', 'safari_18', ...] ``` ## Using a profile Specify the `browser` option in your fetch call: ```typescript theme={null} import { fetch } from 'wreq-js'; const response = await fetch('https://example.com', { browser: 'chrome_142', }); ``` ## Family aliases Instead of a concrete profile you can pass a family alias, which resolves to the newest profile in that family: ```typescript theme={null} import { fetch, resolveProfile } from 'wreq-js'; const response = await fetch('https://example.com', { browser: 'firefox', }); resolveProfile('firefox'); // 'firefox_149' ``` Available aliases: `chrome`, `firefox`, `safari`, `edge`, `opera`, `okhttp`, `firefox_private`, `firefox_android`, `safari_ios`, `safari_ipad`. Families are matched exactly, so `safari` resolves to the newest desktop Safari and never to an iOS or iPad profile. Those have their own aliases. An alias resolves to the newest profile shipped with the version of `wreq-js` you have installed, so upgrading the library changes the fingerprint an alias produces. That is the point of using one, but it does mean a `wreq-js` upgrade can change how a target responds to you without any change in your own code. Pin a concrete profile when you need a fingerprint that never moves, and use `resolveProfile()` to record which one an alias picked. The default `browser` is the `chrome` alias, so requests that do not set `browser` track the newest Chrome profile rather than a pinned version that goes stale over time. ## Operating systems Different operating systems have different header values and behaviors. Use the `os` option to emulate a specific platform: ```typescript theme={null} import { getOperatingSystems } from 'wreq-js'; console.log(getOperatingSystems()); // ['windows', 'macos', 'linux', 'android', 'ios'] ``` ### Example: Windows Chrome ```typescript theme={null} const response = await fetch('https://example.com', { browser: 'chrome_142', os: 'windows', }); ``` ### Example: iOS Safari ```typescript theme={null} const response = await fetch('https://example.com', { browser: 'safari_18', os: 'ios', }); ``` ## Profile updates Profile labels are sourced from the native layer and can evolve with upstream updates. Use a recent version of `wreq-js` if you want the latest profile set. ## Custom headers By default, browser emulation headers are automatically added. To use only your custom headers: ```typescript theme={null} const response = await fetch('https://api.example.com', { browser: 'chrome_142', headers: { 'Accept': '*/*', 'User-Agent': 'CustomBot/1.0', }, disableDefaultHeaders: true, }); ``` # Compatibility Matrix Source: https://wreq.sqdsh.win/concepts/compatibility-matrix Detailed compatibility notes for fetch and WebSocket APIs. # Compatibility Matrix This page documents API compatibility with WHATWG and Node runtime behavior. It also highlights intentional extensions and current native limitations from the Rust `wreq` layer. ## Fetch compatibility | Feature | Status | Notes | | ---------------------------------------------------------------------------------------------------- | ------------------- | ------------------------------------------------------------------------------------------------------------------------ | | `fetch(string \| URL, init)` | Supported | Core entry point. | | `fetch(Request, init)` | Supported | Request fields are used unless explicitly overridden by `init`. | | Unsupported fetch init fields (`credentials`, `mode`, `cache`, `referrer`, `integrity`, `keepalive`) | Not supported | These fields are currently ignored by `wreq-js` runtime options. | | `duplex` | Accepted, no effect | Stream bodies are buffered, which satisfies half-duplex on its own. Accepted so Fetch API code that sets it type-checks. | | `Request` class export | Not supported | `Request` can be used as input, but is not exported by this package. | | `Response.json/text/arrayBuffer/bytes/clone` | Supported | Includes stream handling and clone semantics. | | `Response.blob/formData` | Supported | Implemented through runtime `Response` parsing. | | `ReadableStream` and iterable request bodies | Accepted, buffered | Read fully into memory before sending, so an unbounded stream means an unbounded allocation. | | Streaming request body uploads | Not supported | The native request bridge expects a buffered body, so bodies are never chunked onto the wire. | | Standard timeout behavior | Extended | `wreq-js` defaults to a 30000 ms timeout for safety. | | Error type shape | Extended | Errors are `RequestError` which extends `TypeError`. | ## WebSocket compatibility | Feature | Status | Notes | | ------------------------------------------------------------------ | --------- | ---------------------------------------------------------------------- | | `websocket(url, options)` helper | Supported | Async helper resolves when open. | | `new WebSocket(url, ...)` constructor | Supported | Includes `CONNECTING` state and standard constants. | | `onopen/onmessage/onclose/onerror` | Supported | Settable properties with event dispatch ordering by registration time. | | `addEventListener/removeEventListener` | Supported | Supports function listeners, object listeners, `once`, and `signal`. | | Unknown event names | Supported | Ignored for compatibility with EventTarget behavior. | | `send(string \| Buffer \| ArrayBuffer \| ArrayBufferView \| Blob)` | Supported | Blob is converted to bytes before bridge send. | | `binaryType="nodebuffer"` | Extension | Node-oriented default for performance and ergonomics. | | `binaryType="arraybuffer"` | Supported | Standard compatible binary mode. | | `binaryType="blob"` | Supported | Standard compatible binary mode. | | `bufferedAmount` | Supported | Best effort byte count based on pending JS side sends. | ## Session and transport compatibility | Feature | Status | Notes | | ------------------------------------------------------- | ------------- | --------------------------------------------------------------------------------------- | | `createSession` cookie persistence | Supported | Session cookie jar is reused across session requests and session WebSocket connections. | | `session.websocket(...)` | Supported | Reuses session transport plus session cookies. | | Per request transport override in session fetch | Supported | Use `transport` to override transport details on a specific request. | | Per request `browser/os/proxy` inside session websocket | Not supported | Session websocket uses transport from the session context. | ## Native constraints and roadmap notes 1. Request upload streaming is currently buffered because the native bridge request API takes full byte payloads. 2. WebSocket helper remains async by design because connection establishment runs through native upgrade flow. 3. Additional parity work can be added while preserving current Node-first defaults. # Sessions Source: https://wreq.sqdsh.win/concepts/sessions Learn about session management and request isolation. ## Ephemeral vs. Session mode By default, each `fetch()` call runs in **ephemeral mode**. This is a good fit for one-off requests. For multi-step flows (like login sequences), use **sessions** to persist state. | Scenario | Recommended | Why | | ------------------------------------- | ---------------------------- | ------------------------------------ | | One-off request, no cookie carryover | Ephemeral (default) | Request context is isolated per call | | Multi-step login or reuse cookies | Session | Shared session context | | Parallel jobs that must stay isolated | Ephemeral or per-job session | Avoid cross-talk between tasks | ## Creating a session ```typescript theme={null} import { createSession } from 'wreq-js'; const session = await createSession({ browser: 'chrome_142' }); // All requests share the same cookie jar await session.fetch('https://example.com/login', { method: 'POST', body: new URLSearchParams({ user: 'name', pass: 'secret' }), }); // Cookies from login are automatically included const dashboard = await session.fetch('https://example.com/dashboard'); console.log(await dashboard.text()); // Always close when done await session.close(); ``` ## Auto-disposing sessions Use `withSession()` to automatically close the session when done: ```typescript theme={null} import { withSession } from 'wreq-js'; await withSession(async (session) => { await session.fetch('https://example.com/login', { method: 'POST', body: 'credentials', }); const data = await session.fetch('https://example.com/data'); console.log(await data.json()); }); // Session is automatically closed here ``` ## Session options Sessions accept `browser`, `os`, `proxy`, `timeout`, `insecure`, and `defaultHeaders`: ```typescript theme={null} const session = await createSession({ browser: 'chrome_142', os: 'windows', proxy: 'http://proxy.example.com:8080', insecure: false, }); ``` ## Per-request overrides Within a session, `browser`, `os`, and `proxy` are fixed at creation time unless you pass an explicit `transport` for that request. You can still override per-request values like `timeout`, `headers`, `redirect`, and `body`: ```typescript theme={null} const session = await createSession({ browser: 'chrome_142', timeout: 30_000, }); // Override timeout for a single request await session.fetch('https://example.com', { timeout: 5_000, headers: { 'accept': 'text/html,application/xhtml+xml', }, }); ``` ## Cookie management Sessions automatically handle cookies across requests, but you can also read and write cookies directly. ### Reading cookies Use `getCookies(url)` to inspect which cookies would be sent to a URL: ```typescript theme={null} await session.fetch('https://example.com/login', { method: 'POST', body: new URLSearchParams({ user: 'name', pass: 'secret' }), }); const cookies = session.getCookies('https://example.com'); console.log(cookies); // { "session_id": "abc123", "csrf": "xyz" } ``` Use `getAllCookies()` when you want to inspect the entire session jar without already knowing the matching domain/path: ```typescript theme={null} const cookies = session.getAllCookies(); console.log(cookies); // [ // { name: "session_id", value: "abc123", secure: true, httpOnly: true, domain: "example.com", path: "/" } // ] ``` If available, each entry also includes scope metadata such as `domain`, `path`, `sameSite`, and `expiresAtMs`. ### Setting cookies manually Use `setCookie(name, value, url)` to inject a cookie into the session jar: ```typescript theme={null} session.setCookie('auth_token', 'my-token', 'https://example.com'); // Subsequent requests to example.com will include the cookie const resp = await session.fetch('https://example.com/api'); ``` ### Clearing cookies Use `clearCookies()` to remove all cookies from the session: ```typescript theme={null} await session.clearCookies(); ``` ## Session isolation Each session maintains its own: 1. Cookie jar: cookies are not shared between sessions 2. Session identifier and defaults If you want separate cookie jars but shared transport settings (for example, multiple sessions through the same proxy), use a shared **Transport** per request. ```typescript theme={null} // These sessions are completely isolated const session1 = await createSession({ browser: 'chrome_142' }); const session2 = await createSession({ browser: 'firefox_139' }); // Cookies set in session1 do not affect session2 await session1.fetch('https://example.com/set-cookie'); await session2.fetch('https://example.com/check-cookie'); // No cookie present ``` ## Best practices Call `session.close()` or use `withSession()` to prevent resource leaks. Use a dedicated session for each logical user flow or task. For parallel scraping, create separate sessions to avoid cookie cross-contamination. Sessions keep one context for multi-step flows. # Transport Source: https://wreq.sqdsh.win/concepts/transport Learn how Transport controls reusable network settings such as proxy and emulation options. ## What is a transport? A **transport** is a reusable network layer handle that owns: 1. Transport-level settings like `proxy`, `browser`, `os`, and `insecure` 2. Reusable network context used by requests and sessions Think of it as a "shared network context" you can attach to requests. ## When should I use Transport vs Sessions? Use the simplest tool that matches your needs: | You need… | Use | Why | | ---------------------------------------------------- | --------------------------- | ------------------------------------------------------- | | One-off request with maximum isolation | Ephemeral `fetch()` | Separate request context per call | | Multi-step flow with cookies (login, checkout, etc.) | Sessions | Shared session context across requests | | Reuse a single proxy across many requests | Transport | You create it once and reuse it | | Separate cookie jars with shared transport config | Sessions + shared Transport | Sessions stay isolated while sharing transport settings | ## Creating and reusing a transport A common pattern is **one transport per proxy**, reused across many requests: ```typescript theme={null} import { createTransport, fetch } from 'wreq-js'; const transport = await createTransport({ proxy: 'http://user:pass@proxy.example.com:8080', browser: 'chrome_142', }); try { const r1 = await fetch('https://example.com', { transport }); const r2 = await fetch('https://example.com/pricing', { transport }); console.log(r1.status, r2.status); } finally { await transport.close(); } ``` ## Using Transport with sessions Sessions are the right default for cookie-based flows. If you want **multiple sessions** (separate cookies) to share a **single transport context** (same proxy/emulation), pass the same transport per request: ```typescript theme={null} import { createSession, createTransport } from 'wreq-js'; const transport = await createTransport({ proxy: 'http://proxy.example.com:8080', browser: 'chrome_142', }); const sessionA = await createSession(); const sessionB = await createSession(); try { await sessionA.fetch('https://example.com', { transport }); await sessionB.fetch('https://example.com', { transport }); } finally { await Promise.all([sessionA.close(), sessionB.close(), transport.close()]); } ``` ## Ownership rules (important) When you pass a `transport`, it owns `browser`, `os`, `proxy`, and `insecure`. * Do **not** also set `browser`, `os`, `proxy`, or `insecure` on the request. * Prefer creating a separate transport if you need different settings. ## Lifecycle Always close transports you create: 1. Close when you no longer need the transport: `await transport.close()` 2. After closing, the transport cannot be used again ## Related 1. API details: [`createTransport()`](/api-reference/transport) 2. Cookie flows: [Sessions](/concepts/sessions) # Proxy Usage Source: https://wreq.sqdsh.win/guides/proxy-usage Configure proxy URLs for your requests. ## Basic proxy usage Pass the `proxy` option to route requests through a proxy server: ```typescript theme={null} import { fetch } from 'wreq-js'; const response = await fetch('https://example.com', { browser: 'chrome_142', proxy: 'http://proxy.example.com:8080', }); ``` ## Authenticated proxies Include credentials in the proxy URL: ```typescript theme={null} const response = await fetch('https://example.com', { browser: 'chrome_142', proxy: 'http://username:password@proxy.example.com:8080', }); ``` ## SOCKS proxies SOCKS proxy behavior depends on native layer support in your environment: ```typescript theme={null} const response = await fetch('https://example.com', { browser: 'chrome_142', proxy: 'socks5://proxy.example.com:1080', }); // With authentication const authedResponse = await fetch('https://example.com', { browser: 'chrome_142', proxy: 'socks5://user:pass@proxy.example.com:1080', }); ``` ## Proxy rotation Rotate through a list of proxies for each request: ```typescript theme={null} import { fetch } from 'wreq-js'; const proxies = [ 'http://user:pass@proxy-1.example.com:8080', 'http://user:pass@proxy-2.example.com:8080', 'http://user:pass@proxy-3.example.com:8080', ]; function getRandomProxy() { return proxies[Math.floor(Math.random() * proxies.length)]; } // Each request uses a random proxy for (let i = 0; i < 10; i++) { const response = await fetch('https://example.com', { browser: 'chrome_142', proxy: getRandomProxy(), }); console.log(`Request ${i + 1}: ${response.status}`); } ``` ## Session with proxy Set a default proxy for all session requests: ```typescript theme={null} import { createSession } from 'wreq-js'; const session = await createSession({ browser: 'chrome_142', proxy: 'http://proxy.example.com:8080', }); // All requests use the session proxy await session.fetch('https://example.com/page1'); await session.fetch('https://example.com/page2'); await session.close(); ``` ## Common proxy URL formats | Protocol | URL Format | Notes | | -------- | --------------------- | -------------------------------------------- | | HTTP | `http://host:port` | Common format | | HTTPS | `https://host:port` | Availability depends on native layer support | | SOCKS5 | `socks5://host:port` | Availability depends on native layer support | | SOCKS5h | `socks5h://host:port` | Availability depends on native layer support | ## Related 1. Transport concept: [/concepts/transport](/concepts/transport) 2. Transport API: [`createTransport()`](/api-reference/transport) 3. Fetch API options: [`fetch()`](/api-reference/fetch) # Request Events and Diagnostics Source: https://wreq.sqdsh.win/guides/request-events Observe native request lifecycle events and inspect optional diagnostics payloads. ## Overview `wreq-js` can emit structured native request lifecycle events through `onRequestEvent` and can attach an optional diagnostics payload to the final `Response` when `captureDiagnostics` is enabled. Use this when you need to: * render transport-phase progress such as connecting, waiting, and loading * observe native download progress without consuming `response.body` first * capture timing, address, or TLS peer details for debugging ## Enable request events ```typescript theme={null} import { fetch } from 'wreq-js'; const response = await fetch('https://example.com/file.zip', { browser: 'chrome_142', onRequestEvent(event) { console.log(event.type, event); }, }); console.log(response.status); ``` ## Event types | Event | Meaning | Common fields | | ------------------ | --------------------------------------------------------------- | ------------------------------------------------------ | | `request_start` | Request has started in the native layer. | `timestamp`, `url` | | `request_sent` | Request has been sent and the client is waiting for a response. | `timestamp`, `url` | | `response_headers` | Response headers have arrived. | `timestamp`, `status`, `contentLength`, `url` | | `body_progress` | More response bytes were downloaded. | `timestamp`, `downloadedBytes`, `contentLength`, `url` | | `body_complete` | Response body download finished. | `timestamp`, `contentLength`, `url` | | `done` | Native request lifecycle completed successfully. | `timestamp`, `status`, `url` | | `error` | Native request lifecycle failed. | `timestamp`, `message`, `url` | ## Progress example ```typescript theme={null} const response = await fetch('https://example.com/file.zip', { browser: 'chrome_142', onRequestEvent(event) { switch (event.type) { case 'request_start': console.log('connecting'); break; case 'request_sent': console.log('waiting'); break; case 'response_headers': console.log('status:', event.status); break; case 'body_progress': if (event.contentLength) { const downloaded = event.downloadedBytes ?? 0; const pct = (downloaded / event.contentLength) * 100; console.log(`loading ${pct.toFixed(1)}%`); } break; case 'body_complete': console.log('download complete'); break; case 'error': console.error(event.message); break; } }, }); console.log(await response.arrayBuffer()); ``` ## Enable diagnostics ```typescript theme={null} const response = await fetch('https://example.com', { browser: 'chrome_142', captureDiagnostics: true, }); console.log(response.diagnostics); ``` When available, `response.diagnostics` may include: * `totalDurationMs` * `headersDurationMs` * `status` * `localAddr` * `remoteAddr` * `tlsPeerCertificatePresent` * `tlsPeerCertificateChainLength` ## Session and transport defaults You can enable diagnostics by default on a session or transport: ```typescript theme={null} import { createSession, createTransport } from 'wreq-js'; const session = await createSession({ browser: 'chrome_142', captureDiagnostics: true, }); const transport = await createTransport({ proxy: 'http://proxy.example.com:8080', captureDiagnostics: true, }); ``` `onRequestEvent` remains a per-request callback, so you still pass it to `fetch()` or `session.fetch()` for the specific requests you want to observe. ## Notes * Request events come from the native layer and reflect transport lifecycle phases, not application-level parsing. * `body_progress` is emitted during native download. You can still consume `response.body`, `response.text()`, `response.json()`, and the other body helpers normally. * Diagnostics are optional and may vary by platform or native support level. ## Related * [`fetch()`](/api-reference/fetch) * [`Sessions`](/api-reference/sessions) * [`Transport`](/api-reference/transport) * [`Streaming Responses`](/guides/streaming) # Streaming Responses Source: https://wreq.sqdsh.win/guides/streaming Process large responses incrementally without loading them into memory. ## Streaming basics The `Response` object supports streaming via the standard `body` property, which returns a `ReadableStream`. This allows you to process large responses incrementally. ```typescript theme={null} import { fetch } from 'wreq-js'; const response = await fetch('https://example.com/large-file', { browser: 'chrome_142', }); const stream = response.body; if (stream) { const reader = stream.getReader(); while (true) { const { done, value } = await reader.read(); if (done) break; console.log(`Received ${value.byteLength} bytes`); } } ``` ## Key behaviors The `body` property is lazily initialized. It returns `null` for empty responses or a `ReadableStream` for non-empty responses. Accessing `response.body` does **not** mark it as consumed. Only reading from the stream sets `bodyUsed` to `true`. You can call `response.clone()` to create a duplicate response before the body is consumed. Once consumed via `json()`, `text()`, `arrayBuffer()`, or stream reading, the body cannot be read again. ## Processing chunks Process data as it arrives: ```typescript theme={null} const response = await fetch('https://example.com/stream', { browser: 'chrome_142', }); const reader = response.body?.getReader(); if (!reader) throw new Error('No response body'); const decoder = new TextDecoder(); let result = ''; while (true) { const { done, value } = await reader.read(); if (done) break; // Decode chunk and process const text = decoder.decode(value, { stream: true }); result += text; // Process incrementally console.log('Chunk:', text.substring(0, 100)); } ``` ## Download with progress Track download progress from the response stream itself: ```typescript theme={null} const response = await fetch('https://example.com/file.zip', { browser: 'chrome_142', }); const contentLength = response.headers.get('content-length'); const total = contentLength ? parseInt(contentLength, 10) : 0; const reader = response.body?.getReader(); if (!reader) throw new Error('No response body'); let received = 0; const chunks: Uint8Array[] = []; while (true) { const { done, value } = await reader.read(); if (done) break; chunks.push(value); received += value.byteLength; if (total) { const progress = ((received / total) * 100).toFixed(1); console.log(`Progress: ${progress}%`); } } // Combine chunks into single array const allChunks = new Uint8Array(received); let position = 0; for (const chunk of chunks) { allChunks.set(chunk, position); position += chunk.byteLength; } ``` ## Transport-level request progress If you want progress before you start consuming `response.body`, use `onRequestEvent`. This gives you visibility into request start, headers, and native body download progress. ```typescript theme={null} const response = await fetch('https://example.com/file.zip', { browser: 'chrome_142', onRequestEvent(event) { switch (event.type) { case 'request_start': console.log('connecting'); break; case 'request_sent': console.log('waiting for response'); break; case 'response_headers': console.log('status:', event.status); console.log('length:', event.contentLength); break; case 'body_progress': if (event.contentLength) { const pct = ((event.downloadedBytes ?? 0) / event.contentLength) * 100; console.log(`downloaded ${pct.toFixed(1)}%`); } break; case 'body_complete': console.log('download complete'); break; } }, }); console.log(await response.arrayBuffer()); ``` For more detail on event payloads and diagnostics, see [/guides/request-events](/guides/request-events). ## Server-Sent Events (SSE) Parse Server-Sent Events from a stream: ```typescript theme={null} const response = await fetch('https://example.com/events', { browser: 'chrome_142', headers: { Accept: 'text/event-stream' }, }); const reader = response.body?.getReader(); if (!reader) throw new Error('No response body'); const decoder = new TextDecoder(); let buffer = ''; while (true) { const { done, value } = await reader.read(); if (done) break; buffer += decoder.decode(value, { stream: true }); // Process complete events const events = buffer.split('\n\n'); buffer = events.pop() || ''; // Keep incomplete event in buffer for (const event of events) { if (event.startsWith('data: ')) { const data = event.slice(6); console.log('Event:', JSON.parse(data)); } } } ``` ## Related 1. Fetch API response shape: [`fetch()`](/api-reference/fetch) 2. Session concept for multi-step flows: [/concepts/sessions](/concepts/sessions) # WebSockets Source: https://wreq.sqdsh.win/guides/websockets Connect to WebSocket servers with browser profile options. wreq-js supports both a convenience helper and a constructor-style API. ## 1. Quick connection with the helper Use `websocket(url, options)` when you want a connected socket from a single `await`. ```typescript theme={null} import { websocket } from 'wreq-js'; const ws = await websocket('wss://example.com/socket', { browser: 'chrome_142', headers: { Authorization: 'Bearer token', }, }); ws.onmessage = (event) => { console.log('Received:', event.data); }; void ws.send('hello'); ws.close(); ``` ## 2. Constructor style Use `new WebSocket(...)` when you want browser-like shape with `CONNECTING` state. ```typescript theme={null} import { WebSocket } from 'wreq-js'; const ws = new WebSocket('wss://example.com/socket', { browser: 'chrome_142', os: 'windows', }); ws.onopen = () => { void ws.send('hello from constructor api'); }; ws.addEventListener('message', (event) => { console.log(event.data); }); ws.onerror = () => { console.error('WebSocket error'); }; ``` ## 3. Sessions, impersonation, and cookies For authenticated flows, create a session, log in with HTTP, then open the WebSocket with the same session. `session.websocket(...)` reuses the session transport and context. ```typescript theme={null} import { createSession } from 'wreq-js'; const session = await createSession({ browser: 'chrome_142', os: 'windows', proxy: 'http://proxy.example.com:8080', }); try { await session.fetch('https://example.com/login', { method: 'POST', body: new URLSearchParams({ user: 'name', pass: 'secret' }), }); const ws = await session.websocket('wss://example.com/ws', { headers: { 'X-Client': 'dashboard', }, }); ws.onmessage = (event) => { console.log(event.data); }; void ws.send(JSON.stringify({ type: 'subscribe', channel: 'updates' })); ws.close(1000, 'done'); } finally { await session.close(); } ``` ## 4. Event model Event handlers and listeners follow familiar WebSocket patterns. ```typescript theme={null} const ws = await websocket('wss://example.com/socket', { browser: 'chrome_142' }); ws.onmessage = (event) => { console.log(event.data); }; ws.onclose = (event) => { console.log(event.code, event.reason, event.wasClean); }; ws.addEventListener('error', () => { console.error('error'); }); ``` ## 5. Binary messages `binaryType` defaults to `nodebuffer`. You can set it to `arraybuffer` or `blob`. ```typescript theme={null} const ws = await websocket('wss://example.com/socket', { browser: 'chrome_142' }); ws.binaryType = 'arraybuffer'; ws.onmessage = (event) => { if (event.data instanceof ArrayBuffer) { console.log('ArrayBuffer bytes:', event.data.byteLength); return; } if (Buffer.isBuffer(event.data)) { console.log('Buffer bytes:', event.data.byteLength); return; } console.log('Text:', event.data); }; ``` ```typescript theme={null} ws.binaryType = 'blob'; ``` ## 6. Close behavior Use `close()` or `close(code, reason)`. ```typescript theme={null} ws.close(); ws.close(1000, 'normal shutdown'); ``` If you pass a custom close code, use `1000` or a code in the `3000` to `4999` range. If you pass a reason, keep it to `123` UTF-8 bytes or fewer. ## 7. Large frames and message limits Incoming WebSocket data is bounded by default to avoid unbounded memory use. If a provider sends a very large payload in one frame, you may see an error like `Space limit exceeded: Message too long`. Raise `maxFrameSize` when the peer sends large unfragmented frames. Raise `maxMessageSize` when the peer sends very large fragmented messages. ```typescript theme={null} const ws = await websocket('wss://example.com/socket', { browser: 'chrome_142', maxFrameSize: 32 * 1024 * 1024, maxMessageSize: 32 * 1024 * 1024, }); ``` ## Related 1. API reference: [`websocket()`](/api-reference/websocket) 2. Session API: [`createSession()`](/api-reference/sessions) 3. Session concepts: [/concepts/sessions](/concepts/sessions) # Installation Source: https://wreq.sqdsh.win/installation Install wreq-js and get ready for development. ## Requirements * **Node.js** v20.0.0 or higher * One of the supported platforms (see below) ## Install via package manager ```bash npm theme={null} npm install wreq-js ``` ```bash yarn theme={null} yarn add wreq-js ``` ```bash pnpm theme={null} pnpm add wreq-js ``` ```bash bun theme={null} bun add wreq-js ``` ## Supported platforms Configured native targets in `package.json` include: | Platform | Architecture | | -------- | --------------------- | | macOS | Intel (x64) | | macOS | Apple Silicon (arm64) | | Linux | x64 (glibc) | | Linux | x64 (musl) | | Linux | arm64 (glibc) | | Windows | x64 | ## Building from source If a prebuilt binary for your platform is unavailable, installation may require building from source. Make sure you have the following installed: ### Prerequisites 1. **Rust toolchain**: install via [rustup](https://rustup.rs/): ```bash theme={null} curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh ``` 2. **Build essentials**: C compiler and related tools: ```bash theme={null} xcode-select --install ``` ```bash theme={null} sudo apt-get install build-essential ``` Install [Visual Studio Build Tools](https://visualstudio.microsoft.com/downloads/#build-tools-for-visual-studio-2022) with the "C++ build tools" workload. ### Build After installing prerequisites, the package will automatically build when you run: ```bash theme={null} npm install wreq-js ``` ## Verify installation ```typescript theme={null} import { fetch, getProfiles } from 'wreq-js'; // Check available browser profiles console.log('Available profiles:', getProfiles()); // Make a test request const response = await fetch('https://httpbin.org/get', { browser: 'chrome_142', }); console.log('Status:', response.status); ``` ## Troubleshooting If you see an error about missing binaries, ensure you're using a supported platform or have the build prerequisites installed. If you encounter permission issues, try: ```bash theme={null} sudo chown -R $(whoami) ~/.npm ``` # Introduction Source: https://wreq.sqdsh.win/introduction Node.js/TypeScript HTTP client with browser profile and transport controls backed by native Rust bindings. # wreq-js Node.js/TypeScript HTTP client with browser profile and transport controls exposed by native Rust bindings. No browser process management. Requests run through native Rust bindings. Browser and operating system profiles exposed through a fetch-like API. A fetch-style API with extra options for browser profiles and sessions. WebSocket API with helper and constructor styles. ## Why wreq-js? Standard HTTP clients like `axios`, `fetch`, `got`, and `curl` can differ from browsers on the network layer. Signals often inspected by servers can include: 1. **TLS handshake** details such as cipher suite order and extension sets 2. **HTTP behavior** details such as protocol settings and framing choices 3. **Header defaults** such as ordering and platform-specific values Some anti-bot systems inspect these signals. `wreq-js` uses the [`wreq`](https://github.com/0x676e67/wreq) Rust engine underneath and exposes profile controls through a TypeScript friendly API. ## When to use wreq-js 1. Web scraping and data collection 2. API automation with browser profile controls 3. Multiple HTTP requests with shared session or transport settings 4. Login flows and session management 5. Proxy usage scenarios with per request or transport scoped settings 1. DOM or JavaScript execution (not a browser runtime) 2. CAPTCHA solving or page automation 3. Full browser automation (use Playwright/Puppeteer instead) ## Quick Example If your script makes more than one request, start with a **session** and reuse it. Sessions reuse the same session context across requests, which is the recommended shape for multi-step flows. ```typescript theme={null} import { fetch } from 'wreq-js'; const response = await fetch('https://example.com/api', { browser: 'chrome_142', os: 'windows', }); console.log(await response.json()); ``` That's it. You can select browser profiles with a familiar fetch-style API. For a detailed compatibility breakdown, see [/concepts/compatibility-matrix](/concepts/compatibility-matrix). ## Next Steps Start with a minimal request and session flow. Detailed installation instructions for all platforms. # Quickstart Source: https://wreq.sqdsh.win/quickstart Get started with wreq-js. ## Install the package ```bash npm theme={null} npm install wreq-js ``` ```bash yarn theme={null} yarn add wreq-js ``` ```bash pnpm theme={null} pnpm add wreq-js ``` ```bash bun theme={null} bun add wreq-js ``` ## Make your first request For multi-step flows, prefer **sessions** after your first request. One-off `fetch()` calls use an isolated request context by default. ```typescript theme={null} import { fetch } from 'wreq-js'; const response = await fetch('https://httpbin.org/get', { browser: 'chrome_142', }); console.log(await response.json()); ``` ## Use a session for multiple requests Sessions keep a shared session context across requests: ```typescript theme={null} import { createSession } from 'wreq-js'; const session = await createSession({ browser: 'chrome_142' }); // Login await session.fetch('https://example.com/login', { method: 'POST', body: new URLSearchParams({ user: 'name', pass: 'secret' }), }); // Access authenticated endpoint in the same session context const account = await session.fetch('https://example.com/account'); console.log(await account.text()); // Clean up await session.close(); ``` ## Use a proxy ```typescript theme={null} import { fetch } from 'wreq-js'; const response = await fetch('https://example.com', { browser: 'chrome_142', proxy: 'http://user:pass@proxy.example.com:8080', }); ``` ## What's next? Learn about available browser profiles and operating systems. Understand session management and cookie isolation. Reuse transport settings across requests (ideal per proxy). Explore the full API documentation. Connect to WebSocket servers with browser profile options.