Skip to main content

First Request

httpcloak emits the same wire bytes as a real browser across the TLS ClientHello, HTTP/2 SETTINGS frame, header order, and priority frames. A site that fingerprints clients sees Chrome (or Firefox, or Safari), not Go's net/http or Python requests.

This page is the four-line check that the install works. Pick a language, run the snippet, and you should get a 200 from tls.peet.ws/api/all with a Chrome-shaped fingerprint in the body.

The snippet

package main

import (
"context"
"fmt"
"time"

"github.com/sardanioss/httpcloak"
)

func main() {
sess := httpcloak.NewSession("chrome-latest",
httpcloak.WithSessionTimeout(30*time.Second),
)
defer sess.Close()

ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()

resp, err := sess.Get(ctx, "https://tls.peet.ws/api/all")
if err != nil {
panic(err)
}
defer resp.Close()

fmt.Println("status:", resp.StatusCode)
fmt.Println("protocol:", resp.Protocol)

body, _ := resp.Text()
fmt.Println(body)
}

What you should see

The full response is a JSON blob covering TLS, HTTP/2, and header data. The parts that matter, trimmed down:

{
"http_version": "h2",
"tls": {
"ja3_hash": "55ecc08008f90a8b2a5c5289ab0f8b69",
"ja4": "t13d1516h2_8daaf6152771_d8a2da3f94cd"
},
"http2": {
"akamai_fingerprint": "1:65536;2:0;4:6291456;6:262144|15663105|0|m,a,s,p",
"akamai_fingerprint_hash": "52d84b11737d980aef856699f885ca86"
},
"user_agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36"
}

A few things worth flagging:

  • http_version is h2. Chrome negotiates HTTP/2 against any ALPN-capable server, and httpcloak follows the same pattern. HTTP/3 takes over when the server advertises it via Alt-Svc. To skip negotiation, pin a transport with WithForceHTTP2() or WithForceHTTP3().
  • ja4 stays stable across runs on the same preset. ja3_hash does not, because Chrome shuffles GREASE extension values on every ClientHello and the JA3 string folds those values in. JA4 strips GREASE before hashing. Match against JA4 and ignore JA3.
  • akamai_fingerprint_hash rolls H2 SETTINGS, WINDOW_UPDATE, PRIORITY, and pseudo-header order into one value. It should match what real Chrome 148 ships.
tls.peet.ws is your friend

Bookmark tls.peet.ws/api/all. Any time a preset gets tweaked, a custom JA3 goes in, or a target keeps flagging the request, hit this endpoint and diff the response against a real browser. DevTools doesn't expose request header order, so this endpoint is the closest thing to a source of truth.

Where to next