### Install curl-cffi Source: https://github.com/tocha688/curl-cffi-node/blob/main/README.md Install the curl-cffi package using npm. ```bash npm install curl-cffi ``` -------------------------------- ### Configure Full Request Options Source: https://context7.com/tocha688/curl-cffi-node/llms.txt Use RequestOptions to configure all aspects of a request, including TLS fingerprinting, proxies, certificates, IP resolution, and raw libcurl option overrides. This example demonstrates setting query parameters, request body, headers, authentication, timeouts, redirects, proxies, TLS impersonation, HTTP version, IP type, SSL verification, client certificates, retry counts, encoding, referer, speed limits, keep-alive, sync mode, debug output, CORS preflight, and raw libcurl options. ```typescript import { req, CurlOpt } from "curl-cffi"; const res = await req.request({ url: "https://httpbin.org/post", method: "POST", // Query parameters appended to the URL params: { page: "1", limit: "10" }, // Request body: object → JSON, URLSearchParams → form-encoded, string → raw data: { username: "alice", password: "s3cret" }, // Custom headers headers: { "X-Request-ID": "req-001", "Accept": "application/json" }, // HTTP Basic Auth auth: { username: "admin", password: "pass" }, // Timeouts timeout: 30000, // Redirects allowRedirects: true, maxRedirects: 10, // Proxy: supports http, https, socks4, socks5 proxy: "http://user:pass@proxy.example.com:8080", // Browser TLS/JA3 impersonation impersonate: "chrome136", // Or provide raw JA3 / Akamai fingerprint strings // ja3: "771,4865-4866-ldots", // akamai: "1:65536;3:1000;ldots", // HTTP version: "v1", "v2", "v3", "v3only", "v2tls" httpVersion: "v2", // IP resolution preference ipType: "ipv4", // "ipv4" | "ipv6" | "auto" // SSL certificate verification verify: true, // Client certificate (path string or { cert, key }) cert: { cert: "/path/to/client.crt", key: "/path/to/client.key" }, // Cookie jar // jar: new CookieJar(), // Retry on failure retryCount: 3, // Accept encoding acceptEncoding: "gzip, deflate, br, zstd", // Referer header referer: "https://example.com", // Max download speed in bytes/s maxRecvSpeed: 1024 * 1024, // 1 MB/s // Force new TCP connection (no keep-alive) keepAlive: false, // Synchronous mode (blocks event loop) sync: false, // Enable verbose curl debug output dev: false, // Simulate browser CORS preflight before the actual request cors: false, // Raw libcurl option overrides curlOptions: { [CurlOpt.ConnectTimeout]: 5000, }, }); console.log(res.status); // HTTP status code, e.g. 200 console.log(res.url); // Final URL after redirects console.log(res.redirects); // Number of redirects followed console.log(res.headers.first("content-type")); // "application/json" console.log(res.text); // Raw UTF-8 response body console.log(res.data); // Auto-parsed JSON or raw text console.log(res.stacks.length); // Number of request/redirect hops ``` -------------------------------- ### Make a Simple Asynchronous GET Request Source: https://github.com/tocha688/curl-cffi-node/blob/main/README.md Demonstrates how to make an asynchronous GET request using the req.get method, simulating a specific browser version. Ensure the 'curl-cffi' module is required. ```javascript const { req } = require("curl-cffi"); // Asynchronous request async function makeGetRequest() { try { const response = await req.get("https://api.example.com/data", { impersonate: "chrome136", // Simulate Chrome 136 }); console.log("Status Code:", response.statusCode); console.log("Response Data:", response.data); } catch (error) { console.error("Request failed:", error); } } makeGetRequest(); ``` -------------------------------- ### Get libcurl Version and Path Source: https://context7.com/tocha688/curl-cffi-node/llms.txt Inspect the underlying libcurl version and binary path at runtime using libVersion() and libPath(). ```typescript import { libVersion, libPath } from "curl-cffi"; console.log(libVersion()); // e.g. "libcurl/8.x.x curl-impersonate/0.x nghttp2/1.x OpenSSL/3.x" console.log(libPath()); // e.g. "/home/user/.npm/.../@tocha688/libcurl/bin/libcurl.so" ``` -------------------------------- ### Access CurlResponse Properties Source: https://context7.com/tocha688/curl-cffi-node/llms.txt Every request returns a CurlResponse instance. Key properties include status, url, headers, dataRaw, text, data, stacks, redirects, and jar. This example shows how to access these properties, including iterating through the redirect chain and accessing cookies. ```typescript import { req } from "curl-cffi"; const res = await req.get("https://httpbin.org/redirect/3", { allowRedirects: true }); console.log(res.status); // 200 (final) console.log(res.url); // final URL after all redirects console.log(res.redirects); // 3 console.log(res.stacks.length); // 4 (3 redirects + 1 final) // Headers (HttpHeaders instance — case-insensitive, normalised) console.log(res.headers.first("content-type")); // "application/json" console.log(res.headers.get("set-cookie")); // string[] | null console.log(res.headers.status); // 200 // Body access const raw: Buffer | undefined = res.dataRaw; const text: string | undefined = res.text; // UTF-8 decoded const data: any = res.data; // JSON.parse(text) or text if not JSON // Redirect chain inspection res.stacks.forEach((stack, i) => { console.log(`Hop ${i}: ${stack.url} → ${stack.response.status}`); }); // Cookie jar (populated when using CurlSession or jar option) const cookies = res.jar?.getCookiesSync(res.url); console.log(cookies); ``` -------------------------------- ### `req` — Global Singleton Request Client Source: https://context7.com/tocha688/curl-cffi-node/llms.txt The default export `req` is a globally shared `CurlRequestMulti` instance, ideal for making requests without managing client lifecycle. It supports common HTTP methods like GET and POST, with options for query parameters, JSON bodies, and browser fingerprint impersonation. ```APIDOC ## `req` — Global Singleton Request Client ### Description The default export `req` is a globally shared `CurlRequestMulti` instance, lazily initialized and automatically cleaned up on process exit. It is the fastest way to make requests without managing any client lifecycle. ### Methods - `get(url, options)` - `post(url, data, options)` - `put(url, data, options)` - `delete(url, options)` - `patch(url, data, options)` - `head(url, options)` - `options(url, options)` ### Parameters #### Options for `get`, `post`, `put`, `delete`, `patch`, `head`, `options` - **params** (object) - Optional - Query parameters to be appended to the URL. - **data** (object | string | Buffer) - Optional - The request body for POST, PUT, and PATCH requests. - **impersonate** (string) - Optional - Specifies the browser fingerprint to impersonate (e.g., "chrome136"). - **timeout** (number) - Optional - Request timeout in milliseconds. ### Request Example ```typescript import { req } from "curl-cffi"; // Simple async GET const res = await req.get("https://httpbin.org/get"); console.log(res.status); // 200 console.log(res.data); // parsed JSON object // GET with query params const r2 = await req.get("https://httpbin.org/get", { params: { foo: "bar" } }); // POST with JSON body const r3 = await req.post("https://httpbin.org/post", { name: "curl-cffi", version: "0.1.49" }); console.log(r3.data.json); // { name: "curl-cffi", version: "0.1.49" } // Browser fingerprint impersonation const r4 = await req.get("https://tls.peet.ws/api/all", { impersonate: "chrome136" }); console.log(r4.status); // 200 — responds with detected TLS fingerprint info ``` ### Response - **status** (number) - The HTTP status code of the response. - **data** (any) - The response body, automatically parsed if the content type is JSON. ``` -------------------------------- ### RequestOptions - Full Request Configuration Reference Source: https://context7.com/tocha688/curl-cffi-node/llms.txt Demonstrates the extensive configuration options available for making HTTP requests, including URL, method, parameters, data, headers, authentication, timeouts, redirects, proxies, TLS impersonation, HTTP version, IP type, certificate verification, client certificates, cookie jars, retries, encoding, referer, speed limits, keep-alive, sync mode, debug output, CORS simulation, and raw libcurl option overrides. ```APIDOC ## `req.request` - Making HTTP Requests ### Description This method allows for making HTTP requests with a comprehensive set of configuration options. ### Method `req.request(options)` ### Parameters #### RequestOptions Object - **url** (string) - Required - The URL to make the request to. - **method** (string) - Optional - The HTTP method (e.g., 'GET', 'POST'). Defaults to 'GET'. - **params** (object) - Optional - Query parameters to append to the URL. - **data** (object | URLSearchParams | string) - Optional - The request body. Can be a JSON object, URLSearchParams, or a raw string. - **headers** (object) - Optional - Custom headers for the request. - **auth** (object) - Optional - HTTP Basic Authentication credentials. - **username** (string) - Required - Username for authentication. - **password** (string) - Required - Password for authentication. - **timeout** (number) - Optional - Request timeout in milliseconds. - **allowRedirects** (boolean) - Optional - Whether to follow redirects. - **maxRedirects** (number) - Optional - Maximum number of redirects to follow. - **proxy** (string) - Optional - Proxy configuration string (e.g., 'http://user:pass@proxy.example.com:8080'). - **impersonate** (string) - Optional - Browser TLS/JA3 fingerprint to impersonate (e.g., 'chrome136'). - **ja3** (string) - Optional - Raw JA3 fingerprint string. - **akamai** (string) - Optional - Akamai fingerprint string. - **httpVersion** (string) - Optional - HTTP version to use ('v1', 'v2', 'v3', 'v3only', 'v2tls'). - **ipType** (string) - Optional - IP resolution preference ('ipv4', 'ipv6', 'auto'). - **verify** (boolean) - Optional - Whether to verify SSL certificates. - **cert** (object | string) - Optional - Client certificate configuration. Can be a path string or an object with `cert` and `key` properties. - **cert** (string) - Path to the client certificate file. - **key** (string) - Path to the client private key file. - **jar** (object) - Optional - Cookie jar instance. - **retryCount** (number) - Optional - Number of times to retry the request on failure. - **acceptEncoding** (string) - Optional - Accept-Encoding header value. - **referer** (string) - Optional - Referer header value. - **maxRecvSpeed** (number) - Optional - Maximum download speed in bytes per second. - **keepAlive** (boolean) - Optional - Whether to use keep-alive connections. - **sync** (boolean) - Optional - Whether to run in synchronous mode. - **dev** (boolean) - Optional - Whether to enable verbose curl debug output. - **cors** (boolean) - Optional - Whether to simulate browser CORS preflight. - **curlOptions** (object) - Optional - Raw libcurl option overrides. ### Request Example ```typescript import { req, CurlOpt } from "curl-cffi"; const res = await req.request({ url: "https://httpbin.org/post", method: "POST", params: { page: "1", limit: "10" }, data: { username: "alice", password: "s3cret" }, headers: { "X-Request-ID": "req-001", "Accept": "application/json" }, auth: { username: "admin", password: "pass" }, timeout: 30000, allowRedirects: true, maxRedirects: 10, proxy: "http://user:pass@proxy.example.com:8080", impersonate: "chrome136", httpVersion: "v2", ipType: "ipv4", verify: true, cert: { cert: "/path/to/client.crt", key: "/path/to/client.key" }, retryCount: 3, acceptEncoding: "gzip, deflate, br, zstd", referer: "https://example.com", maxRecvSpeed: 1024 * 1024, // 1 MB/s keepAlive: false, sync: false, dev: false, cors: false, curlOptions: { [CurlOpt.ConnectTimeout]: 5000, }, }); console.log(res.status); console.log(res.url); console.log(res.redirects); console.log(res.headers.first("content-type")); console.log(res.text); console.log(res.data); console.log(res.stacks.length); ``` ### Response #### Success Response (200) - **status** (number) - HTTP status code. - **url** (string) - Final URL after redirects. - **redirects** (number) - Number of redirects followed. - **headers** (HttpHeaders) - Case-insensitive headers object. - **text** (string) - Raw UTF-8 response body. - **data** (any) - Auto-parsed JSON response body or raw text. - **stacks** (array) - Array of request/redirect hops. - **jar** (object) - Cookie jar reference. ``` -------------------------------- ### Session Management with CurlSession Source: https://github.com/tocha688/curl-cffi-node/blob/main/README.md Illustrates creating request instances for session management, supporting both asynchronous and synchronous operations with connection reuse. ```javascript // Session request const req1 = new CurlSession(); // Asynchronous request without connection reuse const req2 = new CurlSessionSync(); ``` -------------------------------- ### Performance Optimization with Global Interface Source: https://github.com/tocha688/curl-cffi-node/blob/main/README.md Utilizes a global interface (gimpl) to reuse connections, enhancing performance for subsequent requests. ```javascript // Use global interface to reuse connections and improve performance const req1=new CurlSession({impl:gimpl}) ``` -------------------------------- ### Synchronous and Asynchronous Request Implementations Source: https://github.com/tocha688/curl-cffi-node/blob/main/README.md Shows how to instantiate synchronous and asynchronous request handlers. CurlMultiImpl can be used for multi-based asynchronous requests to reuse connections. ```javascript // Synchronous request const { CurlRequestSync, CurlRequest, CurlMultiImpl } = require("curl-cffi"); const req = new CurlRequestSync(); // Asynchronous request implementation const req2 = new CurlRequest(); // Multi-based asynchronous request const req3 = new CurlClient({ // Enable multi requests, which will reuse connections, not reused by default impl: new CurlMultiImpl(), }); ``` -------------------------------- ### `fetch(url, options)` — Low-level One-shot Fetch Source: https://context7.com/tocha688/curl-cffi-node/llms.txt A stateless function for making individual HTTP requests without connection reuse. It creates a new `Curl` handle for each call and accepts `FetchOptions` which include standard request options plus a `body` alias and a `sync` flag for synchronous execution. ```APIDOC ## `fetch(url, options)` — Low-level One-shot Fetch ### Description A stateless function that creates a fresh `Curl` handle for each call. Suitable for one-off requests where no connection reuse or session state is required. Accepts `FetchOptions` which extends `RequestOptions` with an additional `body` alias for `data` and a `sync` flag. ### Method - `fetch(url, options)` ### Parameters #### `url` - **url** (string) - The URL to fetch. #### `options` - **method** (string) - Optional - The HTTP method (e.g., 'GET', 'POST'). Defaults to 'GET'. - **headers** (object) - Optional - Custom request headers. - **impersonate** (string) - Optional - Specifies the browser fingerprint to impersonate (e.g., "firefox135"). - **timeout** (number) - Optional - Request timeout in milliseconds. - **body** (object | string | Buffer) - Optional - Alias for `data` for the request body. - **sync** (boolean) - Optional - If true, the request will be synchronous, blocking the event loop. ### Request Example ```typescript import { fetch } from "curl-cffi"; // Async fetch with custom headers and impersonation const res = await fetch("https://httpbin.org/headers", { method: "GET", headers: { "Accept-Language": "en-US,en;q=0.9", "X-Custom-Header": "my-value", }, impersonate: "firefox135", timeout: 15000, }); console.log(res.status); // 200 console.log(res.text); // raw UTF-8 response body string console.log(res.data); // auto-parsed JSON if response is JSON // Synchronous fetch (blocks the event loop) const syncRes = await fetch("https://httpbin.org/get", { sync: true }); console.log(syncRes.status); // 200 ``` ### Response - **status** (number) - The HTTP status code of the response. - **text** (string) - The raw response body as a UTF-8 string. - **data** (any) - The response body, automatically parsed if the content type is JSON. ``` -------------------------------- ### Global Singleton Request Client (req) Source: https://context7.com/tocha688/curl-cffi-node/llms.txt Use the default export `req` for quick, one-off requests without managing client lifecycle. It's a pre-configured `CurlRequestMulti` instance. ```typescript import { req } from "curl-cffi"; // Simple async GET const res = await req.get("https://httpbin.org/get"); console.log(res.status); // 200 console.log(res.data); // parsed JSON object // GET with query params const r2 = await req.get("https://httpbin.org/get", { params: { foo: "bar" } }); // POST with JSON body const r3 = await req.post("https://httpbin.org/post", { name: "curl-cffi", version: "0.1.49" }); console.log(r3.data.json); // { name: "curl-cffi", version: "0.1.49" } // Browser fingerprint impersonation const r4 = await req.get("https://tls.peet.ws/api/all", { impersonate: "chrome136" }); console.log(r4.status); // 200 — responds with detected TLS fingerprint info ``` -------------------------------- ### Manage HTTP Headers with HttpHeaders Source: https://context7.com/tocha688/curl-cffi-node/llms.txt Use HttpHeaders to manage request and response headers. Keys are automatically title-cased, except for 'sec-*' headers. Supports case-insensitive lookups, deletion, and serialization. ```typescript import { HttpHeaders } from "curl-cffi"; // Construct from a plain object const headers = new HttpHeaders({ "content-type": "application/json", "x-request-id": "abc-123", "sec-fetch-mode": "cors", }); headers.set("Authorization", "Bearer token"); console.log(headers.first("content-type")); // "application/json" console.log(headers.first("X-Request-Id")); // "abc-123" (case-insensitive lookup) console.log(headers.first("sec-fetch-mode")); // "cors" (kept lowercase) console.log(headers.has("Authorization")); // true headers.delete("x-request-id"); console.log(headers.has("X-Request-Id")); // false // Serialize for use as curl header array console.log(headers.toArray()); // ["Content-Type: application/json", "Authorization: Bearer token", "sec-fetch-mode: cors"] // Serialize to a single string console.log(headers.toString()); // Clone const copy = headers.clone(); copy.set("X-Extra", "value"); console.log(headers.has("X-Extra")); // false — original unchanged ``` -------------------------------- ### Low-level One-shot Fetch Function Source: https://context7.com/tocha688/curl-cffi-node/llms.txt The stateless `fetch` function creates a new `Curl` handle for each request. Use this for simple, isolated requests without connection reuse. It supports custom headers, impersonation, and synchronous execution. ```typescript import { fetch } from "curl-cffi"; // Async fetch with custom headers and impersonation const res = await fetch("https://httpbin.org/headers", { method: "GET", headers: { "Accept-Language": "en-US,en;q=0.9", "X-Custom-Header": "my-value", }, impersonate: "firefox135", timeout: 15000, }); console.log(res.status); // 200 console.log(res.text); // raw UTF-8 response body string console.log(res.data); // auto-parsed JSON if response is JSON // Synchronous fetch (blocks the event loop) const syncRes = await fetch("https://httpbin.org/get", { sync: true }); console.log(syncRes.status); // 200 ``` -------------------------------- ### CurlClient: Legacy Client with Request/Response Events Source: https://context7.com/tocha688/curl-cffi-node/llms.txt Use CurlClient for backwards compatibility, employing event-based interceptors via onRequest() and onResponse() callbacks. It accepts CurlOptions with additional MaxConnects and MaxConcurrentStreams properties and can delegate to CurlMultiImpl for connection reuse. ```typescript import { CurlClient, CurlMultiImpl, Logger } from "curl-cffi"; Logger.level = 4; // Enable debug logging const client = new CurlClient({ impl: new CurlMultiImpl(), // use multi for connection reuse impersonate: "chrome136", timeout: 20000, MaxConnects: 10, MaxConcurrentStreams: 100, }); // Request interceptor — mutates options before sending client.onRequest(async (opts) => { opts.headers = { ...(opts.headers || {}), "X-App-Token": "secret" }; return opts; }); // Response interceptor — called after each successful response client.onResponse(async (res) => { if (res.status >= 400) console.warn("HTTP error:", res.status); return res; }); // Fire concurrent requests const [r1, r2] = await Promise.all([ client.get("https://httpbin.org/get"), client.post("https://httpbin.org/post", { payload: "data" }), ]); console.log(r1.status, r2.status); client.close(); ``` -------------------------------- ### Pooled Async HTTP Client (CurlRequest) Source: https://context7.com/tocha688/curl-cffi-node/llms.txt The `CurlRequest` class manages a pool of `Curl` handles for efficient connection reuse, reducing TLS handshake overhead. Configure it with `baseUrl`, default parameters, data, retry logic, and SSL verification. Remember to close the client when done to release resources. ```typescript import { CurlRequest } from "curl-cffi"; const client = new CurlRequest( { baseUrl: "https://httpbin.org", timeout: 10000, impersonate: "chrome136", params: { apiKey: "abc123" }, // merged into every request defaultData: { source: "node" }, // merged into every POST/PUT body retryCount: 2, // retry up to 2 times on failure verify: true, // SSL certificate verification allowRedirects: true, maxRedirects: 5, }, { maxSize: 20, idleTTL: 30_000 } // CurlPool options ); // Relative path resolves against baseUrl const r1 = await client.get("/get?a=1"); console.log(r1.data.url); // "https://httpbin.org/get?a=1&apiKey=abc123" // POST — data is deep-merged with defaultData const r2 = await client.post("/post", { name: "test" }); console.log(r2.data.json); // { source: "node", name: "test" } // PUT with override options const r3 = await client.put("/put", { value: 42 }, { timeout: 5000 }); // DELETE with params const r4 = await client.delete("/delete", undefined, { params: { id: "99" } }); // HEAD request — response has headers but no body const r5 = await client.head("/get"); console.log(r5.status); // Access pool baseURL console.log(client.baseURL); // "https://httpbin.org" // Always close when done to release pool resources client.close(); ``` -------------------------------- ### Request Options Type Definition Source: https://github.com/tocha688/curl-cffi-node/blob/main/README.md Defines the structure for RequestOptions, detailing available parameters for configuring HTTP requests, including impersonation, headers, proxy, and more. ```typescript type RequestOptions = { method?: RequestMethod, url?: string, params?: Record, // Request data data?: Record | string | null, // Cookie jar jar?: CookieJar, // Request headers headers?: Record, auth?: RequestAuth, timeout?: number, allowRedirects?: boolean, maxRedirects?: number, // Proxy http://username:password@host:port proxy?: string, referer?: string, acceptEncoding?: string, // Enable curl fingerprint impersonate?: CURL_IMPERSONATE, ja3?: string, akamai?: string, defaultHeaders?: boolean, defaultEncoding?: string, httpVersion?: HttpVersion | number, interface?: string, cert?: string | RequestCert, verify?: boolean, maxRecvSpeed?: number, curlOptions?: Record, ipType?: IpType, // Enable multi, which will reuse requests, not reused by default impl?: CurlMultiImpl, // Automatic retry count, default 0 retryCount?: number, keepAlive?: boolean, // Enable curl logging dev?: boolean, // Simulate browser CORS request cors?: boolean, curl?: Curl, }; ``` -------------------------------- ### Simulate Browser Fingerprints with CURL_IMPERSONATE Source: https://context7.com/tocha688/curl-cffi-node/llms.txt Use the CURL_IMPERSONATE enum to pass browser fingerprint targets to the 'impersonate' option in RequestOptions. This configures TLS client hello, HTTP/2 settings, and default headers to match the specified browser. ```typescript import { req } from "curl-cffi"; import type { CURL_IMPERSONATE } from "curl-cffi"; const targets: CURL_IMPERSONATE[] = [ // Chrome (desktop & Android) "chrome99", "chrome100", "chrome101", "chrome104", "chrome107", "chrome110", "chrome116", "chrome119", "chrome120", "chrome123", "chrome124", "chrome131", "chrome133a", "chrome136", "chrome99_android", "chrome131_android", // Firefox / Tor "firefox133", "firefox135", "tor145", // Safari (desktop & iOS) "safari153", "safari155", "safari170", "safari172_ios", "safari180", "safari180_ios", "safari184", "safari184_ios", "safari260", "safari260_ios", // Edge "edge99", "edge101", ]; // Simulate a specific browser's TLS fingerprint const res = await req.get("https://tls.peet.ws/api/all", { impersonate: "chrome136", }); // The response body contains the server-detected TLS fingerprint console.log(res.data.tls?.ja3); // Should match Chrome 136's JA3 hash console.log(res.data.http2?.akamai); // Should match Chrome 136's H2 fingerprint // Use iOS Safari for mobile simulation const mobile = await req.get("https://httpbin.org/user-agent", { impersonate: "safari184_ios", }); console.log(mobile.data["user-agent"]); // Safari iOS user-agent string ``` -------------------------------- ### CurlClient - Legacy Client with onRequest/onResponse Events Source: https://context7.com/tocha688/curl-cffi-node/llms.txt The original client class, maintained for backward compatibility. It uses event-based interceptors via `onRequest()` and `onResponse()` callbacks. ```APIDOC ## CurlClient ### Description The original client class (kept for backwards compatibility). Uses event-based interceptors via `onRequest()` / `onResponse()` callbacks instead of the axios-style `interceptors` manager. Accepts `CurlOptions` with extra `MaxConnects` and `MaxConcurrentStreams` properties. Internally delegates to `CurlMultiImpl` when provided. ### Usage ```typescript import { CurlClient, CurlMultiImpl, Logger } from "curl-cffi"; Logger.level = 4; // Enable debug logging const client = new CurlClient({ impl: new CurlMultiImpl(), // use multi for connection reuse impersonate: "chrome136", timeout: 20000, MaxConnects: 10, MaxConcurrentStreams: 100, }); // Request interceptor — mutates options before sending client.onRequest(async (opts) => { opts.headers = { ...(opts.headers || {}), "X-App-Token": "secret" }; return opts; }); // Response interceptor — called after each successful response client.onResponse(async (res) => { if (res.status >= 400) console.warn("HTTP error:", res.status); return res; }); // Fire concurrent requests const [r1, r2] = await Promise.all([ client.get("https://httpbin.org/get"), client.post("https://httpbin.org/post", { payload: "data" }), ]); console.log(r1.status, r2.status); client.close(); ``` ``` -------------------------------- ### CurlRequestMulti - High-Concurrency Multi-Handle Client Source: https://context7.com/tocha688/curl-cffi-node/llms.txt Utilizes libcurl's `curl_multi` interface for true concurrent I/O on many simultaneous requests without spawning threads. Includes a `batch()` method for submitting multiple requests at once. ```APIDOC ## CurlRequestMulti ### Description Uses libcurl's `curl_multi` interface (timer-based via `CurlMultiTimer`) for true concurrent I/O on many simultaneous requests without spawning threads. Includes a `batch()` convenience method that submits an array of requests and returns `Promise`. ### Usage ```typescript import { CurlRequestMulti, CurlMultiImpl } from "curl-cffi"; const multi = new CurlRequestMulti( { timeout: 10000, impersonate: "chrome131" }, { maxSize: 50 }, new CurlMultiImpl() // optional: bring your own multi handle ); // Batch request — all submitted concurrently to curl_multi const results = await multi.batch([ { url: "https://httpbin.org/get?n=1", method: "GET" }, { url: "https://httpbin.org/get?n=2", method: "GET" }, { url: "https://httpbin.org/post", method: "POST", data: { key: "val" } }, ]); results.forEach((res, i) => { console.log(`Request ${i + 1}: status=${res.status}`); }); // Single request via multi handle const single = await multi.request({ url: "https://httpbin.org/uuid", method: "GET" }); console.log(single.data.uuid); multi.close(); ``` ``` -------------------------------- ### Configure Logging Levels with Logger Source: https://context7.com/tocha688/curl-cffi-node/llms.txt Utilize the static Logger for configurable log output. Set Logger.level to control verbosity from silent (0) to debug (4). Can also be used for custom logging within your application. ```typescript import { Logger, LogLevel } from "curl-cffi"; // Enable full debug output (shows curl_multi timer callbacks, handle lifecycle, etc.) Logger.level = LogLevel.debug; // or: Logger.level = 4 // Disable all output Logger.level = LogLevel.none; // or: Logger.level = 0 // Use as a regular logger in your own code Logger.info("Starting scraper..."); Logger.debug("Request options:", { url: "...", impersonate: "chrome136" }); Logger.warn("Rate limit approaching"); Logger.error("Request failed after retries"); ``` -------------------------------- ### CurlRequestMulti: High-Concurrency Multi-Handle Client Source: https://context7.com/tocha688/curl-cffi-node/llms.txt Utilize CurlRequestMulti for true concurrent I/O on many simultaneous requests without threads, leveraging libcurl's curl_multi interface. The batch() method simplifies submitting an array of requests and receiving all responses. ```typescript import { CurlRequestMulti, CurlMultiImpl } from "curl-cffi"; const multi = new CurlRequestMulti( { timeout: 10000, impersonate: "chrome131" }, { maxSize: 50 }, new CurlMultiImpl() // optional: bring your own multi handle ); // Batch request — all submitted concurrently to curl_multi const results = await multi.batch([ { url: "https://httpbin.org/get?n=1", method: "GET" }, { url: "https://httpbin.org/get?n=2", method: "GET" }, { url: "https://httpbin.org/post", method: "POST", data: { key: "val" } }, ]); results.forEach((res, i) => { console.log(`Request ${i + 1}: status=${res.status}`); }); // Single request via multi handle const single = await multi.request({ url: "https://httpbin.org/uuid", method: "GET" }); console.log(single.data.uuid); multi.close(); ``` -------------------------------- ### `CurlRequest` — Pooled Async HTTP Client Source: https://context7.com/tocha688/curl-cffi-node/llms.txt A client class for efficient asynchronous HTTP requests using a connection pool (`CurlPool`) to reuse `Curl` handles. It supports features like `baseUrl`, default parameters and data, interceptors, CORS preflight, and automatic retries. ```APIDOC ## `CurlRequest` — Pooled Async HTTP Client ### Description The primary client class for making async HTTP requests. Maintains a `CurlPool` that reuses `Curl` handles across requests to avoid repeated TLS handshake setup costs. Supports `baseUrl`, default `params`, `defaultData`, full interceptor pipeline, CORS preflight, and automatic retry. ### Constructor - `new CurlRequest(clientOptions, poolOptions)` ### Parameters #### `clientOptions` - **baseUrl** (string) - Optional - Base URL for all requests made with this client. - **timeout** (number) - Optional - Default request timeout in milliseconds. - **impersonate** (string) - Optional - Default browser fingerprint to impersonate. - **params** (object) - Optional - Default query parameters merged into every request. - **defaultData** (object | string | Buffer) - Optional - Default data merged into POST/PUT request bodies. - **retryCount** (number) - Optional - Number of times to retry a failed request. - **verify** (boolean) - Optional - Whether to verify SSL certificates. Defaults to true. - **allowRedirects** (boolean) - Optional - Whether to follow HTTP redirects. Defaults to true. - **maxRedirects** (number) - Optional - Maximum number of redirects to follow. #### `poolOptions` - **maxSize** (number) - Optional - Maximum number of `Curl` handles in the pool. - **idleTTL** (number) - Optional - Time in milliseconds after which an idle handle is removed from the pool. ### Methods - `get(url, data, options)` - `post(url, data, options)` - `put(url, data, options)` - `delete(url, data, options)` - `patch(url, data, options)` - `head(url, data, options)` - `options(url, data, options)` - `close()` - Closes the client and releases pool resources. ### Request Example ```typescript import { CurlRequest } from "curl-cffi"; const client = new CurlRequest( { baseUrl: "https://httpbin.org", timeout: 10000, impersonate: "chrome136", params: { apiKey: "abc123" }, // merged into every request defaultData: { source: "node" }, // merged into every POST/PUT body retryCount: 2, // retry up to 2 times on failure verify: true, // SSL certificate verification allowRedirects: true, maxRedirects: 5, }, { maxSize: 20, idleTTL: 30_000 } // CurlPool options ); // Relative path resolves against baseUrl const r1 = await client.get("/get?a=1"); console.log(r1.data.url); // "https://httpbin.org/get?a=1&apiKey=abc123" // POST — data is deep-merged with defaultData const r2 = await client.post("/post", { name: "test" }); console.log(r2.data.json); // { source: "node", name: "test" } // PUT with override options const r3 = await client.put("/put", { value: 42 }, { timeout: 5000 }); // DELETE with params const r4 = await client.delete("/delete", undefined, { params: { id: "99" } }); // HEAD request — response has headers but no body const r5 = await client.head("/get"); console.log(r5.status); // Access pool baseURL console.log(client.baseURL); // "https://httpbin.org" // Always close when done to release pool resources client.close(); ``` ### Response - **status** (number) - The HTTP status code of the response. - **data** (any) - The response body, automatically parsed if the content type is JSON. ``` -------------------------------- ### Shared CurlMultiImpl Instance Source: https://context7.com/tocha688/curl-cffi-node/llms.txt Share a single `CurlMultiImpl` instance across multiple `CurlClient` or `CurlRequest` instances to consolidate their event loops and connection pools. Ensure `sharedMulti.close()` is called when done to clean up resources. ```typescript import { CurlClient, CurlRequest, CurlMultiImpl } from "curl-cffi"; // Create a shared multi-handle const sharedMulti = new CurlMultiImpl(); // Share it across two different client instances const clientA = new CurlClient({ impl: sharedMulti, impersonate: "chrome136" }); const clientB = new CurlRequest({ baseUrl: "https://httpbin.org" }); // Inject the shared impl into clientB via the legacy API clientA.setImpl(sharedMulti); const [r1, r2] = await Promise.all([ clientA.get("https://httpbin.org/get?from=A"), clientA.get("https://httpbin.org/get?from=B"), ]); console.log(r1.status, r2.status); // Close the shared multi-handle once done sharedMulti.close(); clientA.close(); ``` -------------------------------- ### Axios-Style Interceptors for Requests and Responses Source: https://context7.com/tocha688/curl-cffi-node/llms.txt Use request and response interceptors to modify outgoing requests or handle incoming responses. Interceptors can be configured with priority, conditional execution (`runIf`), and error handling. Use `eject(id)` to remove a specific interceptor. ```typescript import { CurlRequest } from "curl-cffi"; const client = new CurlRequest({ baseUrl: "https://httpbin.org", timeout: 10000 }); // Add auth header on every request (priority 10 = high) const authId = client.interceptors.request.use( (opts) => { opts.headers = { ...(opts.headers || {}), Authorization: "Bearer my-token" }; return opts; }, undefined, { priority: 10 } ); // Conditional: only add debug param on /get paths client.interceptors.request.use( (opts) => { opts.params = { ...(opts.params || {}), debug: "1" }; return opts; }, undefined, { runIf: (opts) => !!opts.url?.includes("/get") } ); // Request error recovery: if interceptor throws, redirect to /get client.interceptors.request.use( (opts) => { if (!opts.url) throw new Error("no url"); return opts; }, (err, opts) => ({ ...opts!, url: "/get" }) ); // Response interceptor: log all responses client.interceptors.response.use(async (res) => { console.log(`[${res.status}] ${res.url}`); return res; }); // Response error interceptor: return a fallback on network failure client.interceptors.response.use(undefined, async (error) => { console.error("Network error, returning fallback:", error.message); return { status: 503, data: null, url: "fallback" } as any; }); const r = await client.get("/get?x=1"); console.log(r.data.args); // { x: "1", debug: "1" } console.log(r.data.headers?.Authorization); // "Bearer my-token" // Remove the auth interceptor client.interceptors.request.eject(authId); client.close(); ``` -------------------------------- ### CurlSession - Cookie-Persistent Session Client Source: https://context7.com/tocha688/curl-cffi-node/llms.txt Manages HTTP sessions with automatic cookie handling using an integrated CookieJar. Cookies are stored and sent on subsequent requests to the same domain, mimicking browser behavior. ```APIDOC ## CurlSession ### Description Extends `CurlRequest` with an automatic `CookieJar` (backed by `tough-cookie`). Cookies received via `Set-Cookie` response headers are stored and automatically sent on subsequent requests to the same domain, mimicking real browser session behavior. ### Usage ```typescript import { CurlSession } from "curl-cffi"; import { CookieJar } from "tough-cookie"; // Session with auto cookie management const session = new CurlSession({ impersonate: "chrome136", timeout: 15000, }); // First request — server may set session cookies const login = await session.post("https://httpbin.org/cookies/set/sessionid/abc123"); console.log(login.status); // Second request — cookies are sent automatically const profile = await session.get("https://httpbin.org/cookies"); console.log(profile.data.cookies); // { sessionid: "abc123" } // Inspect or serialize the cookie jar const jar = session.jar; console.log(jar?.getCookiesSync("https://httpbin.org")); // Provide a pre-populated CookieJar const existingJar = new CookieJar(); existingJar.setCookieSync("auth_token=xyz789", "https://api.example.com"); const authenticatedSession = new CurlSession({ jar: existingJar, baseUrl: "https://api.example.com", impersonate: "safari184", }); const r = await authenticatedSession.get("/protected-resource"); console.log(r.data); authenticatedSession.close(); ``` ``` -------------------------------- ### CurlPool for Connection Management Source: https://context7.com/tocha688/curl-cffi-node/llms.txt Utilize CurlPool to manage a pool of reusable Curl handles, optimizing TLS connection reuse. Configure pool size (`maxSize`) and idle timeout (`idleTTL`). Set `keepAlive: false` for a specific request to disable connection reuse for that request. ```typescript import { CurlRequest } from "curl-cffi"; // Configure pool: max 10 handles, idle handles expire after 30 seconds const client = new CurlRequest( { baseUrl: "https://api.example.com", impersonate: "chrome136" }, { maxSize: 10, idleTTL: 30_000 } ); // Pool silently reuses handles across these requests const tasks = Array.from({ length: 20 }, (_, i) => client.get(`/endpoint?i=${i}`) ); const responses = await Promise.all(tasks); console.log(responses.map(r => r.status)); // [200, 200, ...] // Disable connection keep-alive for a specific request (closes handle after use) const r = await client.get("/endpoint", { keepAlive: false }); client.close(); // closes all handles in the pool ```