> For the complete documentation index, see [llms.txt](https://docs.disasm.dev/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.disasm.dev/getting-started/tls-fingerprinting.md).

# TLS & Fingerprinting

A correct payload is only half of a solve. Before DataDome or Incapsula looks at your cookie, it fingerprints the connection itself - the TLS handshake (JA3/JA4), the HTTP/2 settings and frame order, and the order of your HTTP headers. If those don't look like the browser you are claiming to be, you are blocked regardless of how good the payload is.

Our solvers emulate **Chrome on Windows**. Your client has to do the same.

## What gets fingerprinted

* **TLS (JA3/JA4)** - the cipher suites, extensions and curves your client offers during the handshake. A default Go, Python `requests` or Node client has an obvious, non-browser signature.
* **HTTP/2** - the SETTINGS frame values, header-table size, window updates and pseudo-header order. Real Chrome has a specific, stable HTTP/2 fingerprint.
* **Header order** - browsers send headers in a consistent order. Reordering them, or letting a library sort them alphabetically, is a common tell.

A standard HTTP library cannot control any of this, which is why a purpose-built client is required.

## Recommended client: httpcloak

We recommend [**httpcloak**](https://github.com/sardanioss/httpcloak) ([docs](https://httpcloak.dev)). It reproduces browser-identical JA3/JA4, HTTP/2 and HTTP/3 fingerprints, preserves header order, and ships presets for current Chrome, Firefox and Safari versions. The core is written in Go, with bindings for Python, Node.js and C#.

Because our API emulates Chrome on Windows, use a matching Windows preset such as `chrome-146-windows` (or `chrome-latest`), and keep it current as Chrome releases.

{% tabs %}
{% tab title="Go" %}

```bash
go get github.com/sardanioss/httpcloak
```

```go
import (
    "context"
    "fmt"

    "github.com/sardanioss/httpcloak/client"
)

c := client.NewClient("chrome-146-windows")
defer c.Close()

resp, _ := c.Get(context.Background(), "https://example.com", nil)
fmt.Println(resp.StatusCode, resp.Protocol)
```

{% endtab %}

{% tab title="Python" %}

```bash
pip install httpcloak
```

```python
import httpcloak

r = httpcloak.get("https://example.com", preset="chrome-146-windows")
print(r.status_code, r.protocol)
```

{% endtab %}

{% tab title="Node.js" %}

```bash
npm install httpcloak
```

```javascript
import httpcloak from "httpcloak";

const session = new httpcloak.Session({ preset: "chrome-146-windows" });
const r = await session.get("https://example.com");
console.log(r.statusCode, r.protocol);
session.close();
```

{% endtab %}
{% endtabs %}

## Match the headers we return

Several endpoints hand back the client-hint values to send on your requests - DataDome returns a `headers` map (`sec-ch-ua`, `sec-ch-ua-full-version-list`, and so on), Incapsula returns `userAgent` and `sec_ch_ua`. Send those exact values and keep them stable for the lifetime of the session, alongside a matching User-Agent. The TLS fingerprint, the User-Agent and the client hints must all describe the same browser.

## Header order and recording

* Record a real Chrome session against the target with **Charles Proxy** and replicate the header order exactly.
* Avoid tools that don't preserve HTTP/2 header order, such as Proxyman or Fiddler. Per [RFC 7540](https://httpwg.org/specs/rfc7540.html) the order carries meaning, and a reordered set is detectable.
* Header order matters for the whole session, not just the solve - a clean solve followed by mis-ordered headers will still be flagged.

{% hint style="warning" %}
A few steps must be sent over **HTTP/1.1** rather than HTTP/2 (for example the DataDome interstitial POST). The individual guides call this out where it applies.
{% endhint %}


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.disasm.dev/getting-started/tls-fingerprinting.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
