Skip to main content

Common Options

Every HTTP client exposes the same handful of knobs: timeouts, redirects, retries, default headers, cookies. This page covers those for httpcloak. The full option surface lives in Reference: Options.

Timeout

WithSessionTimeout sets the default timeout for every request on the session. Per-request overrides go through the Timeout field on Request in Go, or the timeout kwarg in the bindings.

The session timeout covers the whole request: DNS, connect, TLS handshake, request send, response read. It does not cover reading the body once Get or Do has returned. The body read is on you.

sess := httpcloak.NewSession("chrome-latest",
httpcloak.WithSessionTimeout(10*time.Second),
)

In Go, the timeout is also bounded by the context.Context passed to Get or Do, and whichever deadline fires first wins. The context handles caller cancellation, the session timeout is the backstop.

Redirects

Redirects are followed by default, up to 10 hops. You can disable them entirely or just change the cap.

// Don't follow at all
noRedir := httpcloak.NewSession("chrome-latest", httpcloak.WithoutRedirects())

// Follow but cap at 5
capped := httpcloak.NewSession("chrome-latest", httpcloak.WithRedirects(true, 5))

When redirects are followed, the response object exposes the full chain through response.History (Go), r.history (Python and Node), or Response.History (.NET). Each entry carries the status, URL, and headers of the intermediate hop. The final URL lands on FinalURL, final_url, finalUrl, or FinalUrl depending on the binding.

With redirects off, a 301 or 302 comes back as the response, body and all, with no auto-follow.

Retries

Retries are off by default. WithRetry(n) turns them on with sensible defaults. WithRetryConfig tunes the backoff window and the trigger status codes. The default retry-on-status set is [429, 500, 502, 503, 504].

One thing to watch: retries on POST, PUT, and PATCH need a re-readable body. A bytes.Buffer or []byte-backed reader works. A one-shot stream does not, since the retry has nothing left to send.

// 3 retries with default 500ms-10s exponential backoff on default statuses
sess := httpcloak.NewSession("chrome-latest", httpcloak.WithRetry(3))

// Custom: 5 retries, 1s-30s backoff, only 429 and 503
tuned := httpcloak.NewSession("chrome-latest",
httpcloak.WithRetryConfig(5, 1*time.Second, 30*time.Second, []int{429, 503}),
)

Custom headers

Presets ship with a default header set in the order Chrome sends. Most of the time these stay untouched, since matching Chrome is the point. What you'll usually need is to add an Authorization, Cookie, Referer, or some app-specific header on top.

Per-request additions get merged into the preset's order at the correct slot. httpcloak knows where Chrome puts authorization relative to accept, and so on for every standard header.

resp, err := sess.Do(ctx, &httpcloak.Request{
Method: "GET",
URL: "https://httpbin.org/headers",
Headers: map[string][]string{
"Authorization": {"Bearer abc123"},
"X-Request-Id": {"42"},
},
})

To override the preset's header order entirely, use SetHeaderOrder on the session. See Reference: Options for that one.

Cookies

The session has a built-in cookie jar. It captures Set-Cookie from every response and replays the right cookies on subsequent requests, scoped to domain and path the way browsers do.

The jar is on by default with no opt-in needed. To inspect or seed it, see Cookies and State.

If cookies are already managed elsewhere (a shared store across many sessions, or proxying for another tool that owns the jar), turn the internal jar off:

sess := httpcloak.NewSession("chrome-latest", httpcloak.WithoutCookieJar())

With the jar off, Set-Cookie values are not stored and nothing gets auto-injected on later requests. The Cookie header is yours to manage per-request. See Disabling the Cookie Jar for the full pattern.

Local source address

A session can be pinned to a specific source IP, which is the move when an IPv6 prefix is routed to the host (cheap rotating egress) or when multiple IPv4 addresses live on the same box. Linux freebind kicks in automatically, so addresses that aren't configured on the interface still bind without CAP_NET_ADMIN.

sess := httpcloak.NewSession("chrome-latest",
httpcloak.WithLocalAddress("2001:db8::1234"),
)

IPv4 works the same way. For rotation patterns and freebind details, see Source Address Binding.

What's not on this page

  • Proxies (HTTP CONNECT, SOCKS5, MASQUE, split TCP/UDP): see Proxies.
  • Fingerprint customization (custom JA3, Akamai shorthand, JSON presets): see Fingerprinting.
  • Advanced TLS knobs (ECH, key logging, session resumption): see Advanced TLS.
  • Streaming uploads/downloads, multipart, redirect history details: see Requests and Responses.
Full option list

This page covers the everyday set. For the rest (WithForceHTTP3, WithKeyLogFile, WithECHFrom, WithCustomFingerprint, WithSessionCache, and the rest of the surface), see Reference: Options.