node-tls-clientLatest version on npm

Requests

Methods, request bodies, redirects, timeouts, and every per-request option.

Each HTTP method has a session method: get, post, put, patch, delete, head and options. They all take a URL and an optional options object, and resolve with a Response.

await session.post("https://httpbin.org/post", {
  headers: { "content-type": "application/json" },
  body: JSON.stringify({ hello: "world" }),
  followRedirects: true,
});

Sending a body

body accepts a string or a Buffer/Uint8Array. Set the content-type header yourself; the library doesn't guess it.

JSON

const created = await session.post("https://httpbin.org/post", {
  headers: { "content-type": "application/json" },
  body: JSON.stringify({ name: "Ada" }), // objects must be stringified
});
console.log((await created.json()).json); // { name: 'Ada' }

Passing an object as body throws a TlsClientError: stringify it first.

Form data

const form = new URLSearchParams({ q: "tls fingerprint", page: "2" });
const searched = await session.post("https://httpbin.org/post", {
  headers: { "content-type": "application/x-www-form-urlencoded" },
  body: form.toString(),
});
console.log((await searched.json()).form); // { page: '2', q: 'tls fingerprint' }

Binary data

// A Buffer or Uint8Array is sent as raw bytes (here: this file itself).
const bytes = readFileSync(new URL(import.meta.url));
const uploaded = await session.put("https://httpbin.org/put", {
  headers: { "content-type": "application/octet-stream" },
  body: bytes,
});
console.log(uploaded.status, (await uploaded.json()).data.length > 0); // 200 true

String bodies with a binary content-type

When the content-type looks binary (image/*, audio/*, video/*, application/octet-stream, application/pdf, application/zip, …) or any content-encoding header is set, a string body is treated as base64 and decoded before sending: "aGVsbG8=" arrives as hello. Pass a Buffer for binary data, and only use a string with those headers if it's base64.

Redirects

Redirects are not followed by default. You get the 3xx response and its Location header, which lets you inspect cookies or headers set along the way. Pass followRedirects: true to follow them:

const hop = await session.get("https://httpbin.org/redirect/2");
console.log(hop.status, hop.headers.Location); // 302 [ '/relative-redirect/1' ]

const landed = await session.get("https://httpbin.org/redirect/2", {
  followRedirects: true,
});
console.log(landed.status, landed.url); // 200 https://httpbin.org/get

After following redirects, res.url is the final URL.

Other methods

await session.delete("https://httpbin.org/delete");
await session.patch("https://httpbin.org/patch", { body: "x=1" });
const head = await session.head("https://httpbin.org/get");
console.log(head.status, head.body); // 200 '' (HEAD has no body)

Timeouts

The timeout is a session option, in milliseconds, and applies to each request:

const session = new Session({ timeout: 10_000 });

A request that runs out of time resolves with status: 0 and a Client.Timeout exceeded message in body; it doesn't throw. Without a timeout, requests give up after 30 seconds.

There's no per-request timeout. For one request with a different timeout, use fetch() with options: { timeout }, or a second session.

timeoutSeconds exists for compatibility. If both are set, timeout wins and a warning is logged once.

Host override

hostOverride sets the Host header separately from the URL. It's typically used when connecting to an IP address directly:

await session.get("https://203.0.113.7/", { hostOverride: "example.com" });

To change the TLS server name (SNI) as well, see serverNameOverwrite in TLS verification.

Options

Every option a single request takes. Methods that can send a body (post, put, patch) take RequestOptions; the others (get, head, options, delete) take BaseRequestOptions, the same minus body. The per-method names (GetRequestOptions, PostRequestOptions, …) are aliases of these two, exported for typing.

OptionTypeDefaultWhat it does
bodystring | Buffer | Uint8Array—Request body. Objects are rejected: JSON.stringify them. Not on get/head/options/delete. See Sending a body.
headersHeaderInputsession headersMerged over the session's headers per key, case-insensitively; null removes a session header for this request. See Headers.
headerOrderstring[]session's orderHeader names in the order to send them. Replaces the session's headerOrder for this request.
connectHeadersRecord<string, string[]>session'sHeaders for the proxy CONNECT request. Replaces the session's for this request.
followRedirectsbooleanfalseFollow 3xx redirects. Off by default: you get the redirect response and its Location header. See Redirects.
proxystringsession proxyA different proxy for this request. The next request without one goes back to the session's. See Proxies.
isRotatingProxybooleansession'sRe-apply the proxy before this request instead of reusing a pooled connection.
cookiesRecord<string, string | number>—Cookies sent with this request on top of the jar's, and stored in the jar, so later requests to the host send them too. See Cookies.
byteResponsebooleanfalseReturn a binary body as a data:<mime>;base64,… URL. See Responses.
hostOverridestringURL hostHost header to send, e.g. when the URL is an IP address. See Host override.

The timeout and the fingerprint are session-only. Every session-wide option is listed in SessionOptions.

On this page