Saturday, October 17, 2026

CycleTLS for spoofing TLS and HTTP/2 fingerprints across Go and JavaScript

CycleTLS for spoofing TLS and HTTP/2 fingerprints across Go and JavaScript

CycleTLS is a dual-runtime HTTP client library that lets authorized security professionals precisely control JA3, JA4 and HTTP/2 fingerprints in Go and JavaScript, primarily for fingerprinting research and defensive testing.

ToolDanny-Dasilva/CycleTLS — Go/TypeScript HTTP client with configurable JA3, JA4R and HTTP/2 fingerprints
CategoryNetwork client library / TLS fingerprint manipulation
Primary UseEmulating precise browser ClientHello and HTTP/2 characteristics for fingerprint research, bot-detection evaluation, and authorized scraping of systems you own or are permitted to test
Safe UseIntended for authorized penetration tests, private labs, and defensive research teams validating whether their JA3/JA4/Akamai-style fingerprint blocklists actually distinguish real browsers from scripted clients
Telemetry NoteEvery request still produces a real ClientHello and SETTINGS frames observable by defenders; fingerprint anomaly detection, JA4/JA3 mismatch against claimed User-Agent, and proxy egress logs remain viable detection angles

CycleTLS occupies a distinctive niche in the tooling landscape: it is not a scanner, a proxy, or an exploitation framework, but a drop-in HTTP client library whose entire raison d'être is deterministic control over how your traffic looks at the TLS and HTTP/2 layers. Written in Go with a parallel TypeScript/JavaScript distribution on npm as cycletls, it exposes the kind of low-level socket configuration that net/http and Node's standard stacks deliberately hide from you. The repository sits at roughly 1,500 stars under a GPL-3.0 license, with active CI badges, GoDoc documentation, and a Discord community, all signals of a maintained project rather than an abandoned proof of concept.

The core capability is fingerprint impersonation at three layers simultaneously. First, the classic JA3 token: a comma-separated string encoding TLS version, cipher suites, extensions, elliptic curves, and signature algorithms, which CycleTLS translates into an actual ClientHello rather than merely hashing one. Second, JA4R, the raw form of the newer JA4 standard, which the README is careful to distinguish from the JA4 hash itself — passing a JA4 hash does nothing because it is a report-only digest; only the raw ja4r string, listing ciphers, extensions, and signature algorithms explicitly, changes your handshake. Third, HTTP/2 fingerprinting in the Akamai format, controlling SETTINGS values, window sizes, and pseudo-header priority ordering so that the connection behaves like a specific browser even after the TLS handshake completes.

Architecturally, the README reveals a design tuned for throughput. The feature list highlights a built-in goroutine pool for handling asynchronous requests, custom header ordering via fhttp (a fork of net/http that preserves header sequence, itself a fingerprinting signal), connection reuse enabled through EnableConnectionReuse, and a WithRawBytes() initialization option that trades the friendlier chan Response API for raw byte performance in high-volume scenarios. Proxy support covers Socks4, Socks5, and Socks5h, and the transport layer has grown well beyond plain HTTPS: the project now advertises HTTP/3 and QUIC support, a WebSocket client, and Server-Sent Events (SSE), which makes it plausible infrastructure for long-lived connections that need consistent fingerprint cover.

The dual-runtime story deserves attention because it shapes how you would actually deploy the library. On the Go side, cycletls behaves like a conventional dependency: instantiate with cycletls.Init(), call client.Do() with an Options struct carrying Ja3, Ja4r, or HTTP2Fingerprint fields, and defer client.Close(). The JavaScript side mirrors this with an async factory — await initCycleTLS() returns a callable that accepts a URL, an options object, and a method, and requires an explicit await cycleTLS.exit() to terminate cleanly. Notably, the Go API also exposes cycletls.NewTransport(ja3, ua), letting you wrap an existing fhttp.Client transport instead of adopting the library's request lifecycle wholesale — a thoughtful escape hatch for integrating into larger codebases.

Installation follows the standard package-manager pattern in both ecosystems, and nothing here is weaponized — it is library setup, not an attack recipe. For Node, npm install cycletls pulls the package (the README pins the dependency at node ^v18.0); for Go, go get github.com/Danny-Dasilva/CycleTLS/cycletls with golang ^v1.21x. A minimal invocation in either language is a single GET against a fingerprint-echo service with a chosen ja3 string and User-Agent, which is exactly the verification loop the README's own examples demonstrate against endpoints like tls.peet.ws/api/all.

What the examples teach, read carefully, is the methodology of fingerprint consistency rather than any attack technique. The README's combined example stacks a Chrome JA4R raw fingerprint with a Firefox HTTP/2 fingerprint and a mismatched User-Agent — a combination no real browser would produce — and its browser fingerprint table documents why: Firefox sends smaller window sizes with m,p,a,s priority ordering while Chrome sends larger windows with m,a,s,p. This is the educational heart of the tool. Defenders who understand that JA3/JA4 must correlate coherently with the Akamai HTTP/2 fingerprint and the claimed User-Agent gain a robust detection heuristic that single-layer fingerprint spoofing cannot easily defeat.

The streaming support rounds out the API in a way that suggests real production usage rather than a research toy. CycleTLS implements axios-compatible streaming via responseType: 'stream', with data, end, and error events on the response body, plus buffered modes using responseType: 'json' or 'text' and corresponding .json()/.text() accessors. For defenders analyzing the tool, this matters: any authorized assessment tooling that needs to ingest SSE feeds or chunked endpoints without breaking fingerprint cover can now do so natively, meaning egress from this library is not limited to discrete request/response pairs that would stand out in flow analysis.

In an authorized workflow, the primary legitimate applications are straightforward to enumerate. Red teams operating under a signed scope can validate that their collection tooling doesn't leak a Go-default fingerprint that would trip client-side analytics. Blue teams and anti-bot engineers can use CycleTLS as a test harness: build a matrix of JA3, JA4R, and HTTP/2 combinations, replay them against your own staging infrastructure, and measure whether your WAF rules and fingerprint blocklists actually catch imperfect impersonations such as a valid JA3 paired with an impossible header order or a stale cipher list. It is also the standard toolkit for scraping literature where the target is your own platform or one you have written permission to access, since naive requests-style clients are trivially fingerprintable otherwise.

The telemetry perspective is the mirror image. Because CycleTLS constructs genuine handshakes rather than replaying captured ones, every request it emits is fully observable at the network edge: defenders see the complete ClientHello, the SETTINGS frame sequence, the SETTINGS window update pattern, and header ordering — all of which can be logged and diffed. The strongest detection signals are internal inconsistencies: a JA4 claiming Chrome with a priority tree claiming Firefox, a User-Agent version too old for the advertised ALPN or extension set, or cipher ordering that no shipping browser produces. Tools like CycleTLS make those inconsistencies easy to generate deliberately, which is precisely why they are valuable for tuning the detections that catch less careful operators.

Limitations worth flagging before adoption: the GPL-3.0 license has redistribution implications for commercial tooling that embeds the library, and the README's warning about JA4 hashes being inert is easy to miss — practitioners who pass a hash expecting a fingerprint change will silently send the default Go profile, a mistake that itself is a clean detection signature. Dependency requirements (node ^v18.0, golang ^v1.21x) are current but worth pinning in CI. The project's acceptance of community PRs, its Discord channel, and its npm publication cadence all suggest a maintainer responsive to API-change requests, which reduces the maintenance risk of building authorized assessment infrastructure on top of it. As with any fingerprint-manipulation library, the professional framing is unchanged: its value is in understanding and testing the observation layer, not in evading controls on systems you have no permission to touch.

Official project repository for Danny-Dasilva/CycleTLS.
Download Tool

Educational analysis for authorized security professionals. Use only in controlled, authorized environments.

Share articleFacebookXLinkedIn

Continue exploring

Browse all articles →

0 comentários:

Post a Comment

Note: Only a member of this blog may post a comment.