Repository navigation
Releases: North-web-dev/impersonate-http
Release list
v0.6.0 — verified Akamai HTTP/2 fingerprint parity
HTTP/2 (Akamai) fingerprint: verified, byte-level
The frame-level HTTP/2 client (introduced in v0.2.0) drives the connection over uTLS with http2.Framer + hpack, emitting the browser's SETTINGS, connection WINDOW_UPDATE and pseudo-header order instead of Go's net/http2 defaults. This release makes that parity verifiable and honest.
Added
- Byte-level unit tests (
http2_wire_test.go) — assert the exact preface + SETTINGS +WINDOW_UPDATEbytes the client writes (an independent hand-rolled byte reference plus a fully literal Chrome expectation), and that HEADERS carries each profile's four pseudo-headers in order followed by the regular headers inHeaderOrder. No network needed. cmd/measureis now reflector-configurable —-urlflag /REFLECTOR_URLenv; tolerates reflectors that expose the Akamai string at the top level. Addedchrome_android.
Verified (real measurements)
Measured against two independent reflectors — tls.peet.ws and fp.shshbshsnang.shop — which agree per profile:
| Profile | Emitted Akamai h2 | Match |
|---|---|---|
| chrome / edge / chrome_android | 1:65536;2:0;4:6291456;6:262144|15663105|0|m,a,s,p |
✅ byte-exact (canonical Chromium) |
| firefox | 1:65536;4:131072;5:16384|12517377|0|m,p,a,s |
✅ byte-exact |
| safari | 3:100;4:4194304|10420225|0|m,s,p,a |
✅ values & pseudo-order; see caveat |
| ios | 3:100;4:2097152|10420225|0|m,s,p,a |
✅ values & pseudo-order; see caveat |
Honest caveat: Safari/iOS SETTINGS values and pseudo-order are correct for WebKit, but public fingerprint DBs disagree on SETTINGS ordering and the exact WINDOW_UPDATE increment, and these were not cross-checked against a real device. See the README parity table.
CI green (build / vet / gofmt / test on Go 1.25).
v0.5.0 — measured parity table + docs overhaul
Documentation and release polish. No breaking API changes; no behavioural change to the library.
Highlights
- Real measured parity table in the README: JA4, JA3, and HTTP/2 (Akamai) fingerprints for every profile (chrome, edge, firefox, safari, ios), captured with
go run ./cmd/measureagainst tls.peet.ws on 2026-10-25 (uTLS v1.8.2). Reproducible — no hand-written values. - Corrected the Chrome fingerprint claim. Chrome shuffles its TLS extension order on every connection (Chromium >= 110), so its JA3 is non-deterministic by design. The old README listed a single fixed Chrome JA3, which was misleading; JA4 (which sorts extensions) is now presented as the identifier to match on.
- Honest Edge caveat: uTLS
HelloEdge_Autodoes not reproduce Chromiums per-connection extension shuffle, so the Edge ClientHello is close but not shuffle-identical to real Edge 131. UseChrome` if you need the shuffle. - 30-second quickstart with a complete, runnable example.
- What it does / does not do section (no HTTP/3, regular-header order is best-effort, no JS/DOM) and a factual comparison to curl_cffi (Python + CGo/libcurl) and utls (TLS layer only).
- Godoc: documented the exported
Profiletype and all its fields.
Verified
go build ./..., go vet ./..., and go test ./... -race all pass (Go 1.25.3). CI green.
Full changelog: v0.4.0...v0.5.0
v0.4.0
Proxy support, a language-agnostic HTTP fetch API, and a new mobile profile.
Highlights
- Proxy support — route any client through a
socks5://orhttp(s)://proxy (with credentials) viaWithProxy, or plug in your own dialer withWithDialer.WithTimeoutsets the client timeout. - HTTP fetch API (
cmd/serve) — wrap the library in a service:POST /fetcha URL + profile, get the response fetched with that browser's exact TLS/HTTP2 fingerprint.br/zstd/gzipbodies are decoded for you. Endpoints:/fetch,/profiles,/usage,/healthz. - Per-key rate limits & quotas — run the API with
-key(single key) or-keys keys.jsonfor per-key requests/sec and daily quotas. Auth viaAuthorization: BearerorX-API-Key; open when no key is set. chrome_androidprofile — mobile Chrome (Android UA,sec-ch-ua-mobile: ?1). Six profiles total:chrome,chrome_android,firefox,safari,edge,ios.- Docker — multi-stage build to a distroless image.
Install
go get github.com/North-web-dev/impersonate-http@v0.4.0
Non-breaking: New, NewTransport, and NewByName now take optional Options; existing calls are unchanged.
v0.3.0 — WebSocket support
Browser-fingerprinted WebSocket (wss://).
Expose Profile.DialTLSContext / Profile.Dial — a uTLS dialer that does the browser-exact TLS handshake and hands back the conn, so any WebSocket client (coder/websocket, gorilla/websocket) gets JA3/JA4-identical wss connections.
websocket.Dial(ctx, "wss://host", &websocket.DialOptions{
HTTPClient: &http.Client{Transport: impersonate.NewTransport(impersonate.Chrome)},
})Also: a cmd/measure fingerprint self-check, and the profiles are now cross-referenced with the new fingerprint-db. HTTP/3 (QUIC) on the roadmap.
v0.2.0 — browser-exact HTTP/2 fingerprint
v0.2 nails the HTTP/2 (Akamai) fingerprint too — not just TLS.
A custom HTTP/2 client (on http2.Framer + hpack) emits the browser's exact SETTINGS order+values, WINDOW_UPDATE increment, and pseudo-header order.
Verified against tools.scrapfly.io — Chrome:
1:65536;2:0;4:6291456;6:262144|15663105|0|m,a,s,p
byte-identical to real Chrome (JA3/JA4 + Akamai h2 both match).
Now defeats both TLS and HTTP/2 fingerprinting — the combination Cloudflare/Akamai/DataDome actually score.
v0.1.0 — browser-exact TLS fingerprint
A drop-in Go *http.Client whose TLS ClientHello is byte-identical to a real browser (Chrome/Firefox/Safari/Edge/iOS) — survive JA3/JA4 fingerprinting without a headless browser, CGo, or curl.
client := impersonate.New(impersonate.Chrome)
resp, _ := client.Get("https://example.com")Verified against tls.peet.ws — each profile's JA4 matches the real browser (Chrome t13d1516h2_8daaf6152771).
Scope: TLS (JA3/JA4) + default headers are browser-exact. HTTP/2 frame-level (Akamai) fingerprint is Go's stack for now — browser-exact h2 is the v0.2 roadmap, documented honestly.
Only deps: uTLS + x/net. MIT.