leyline-http
Leyline is an async Rust HTTP client that impersonates browsers on the wire. The TLS ClientHello, HTTP/2 SETTINGS and priorities, HTTP/3 transport parameters, and request header order all come from captures of shipped browsers, so a server that reads JA3, JA4, or HTTP/2 fingerprints sees Chrome, Firefox, or Safari, not a Rust library. It does for Rust what curl-impersonate does for curl.
use ;
async
For the profiles captured from shipped browsers, the live test suite checks that tls.peet.ws sees the same JA4 and HTTP/2 fingerprint from Leyline as from the browser capture.
Plain client
Session::new() is a plain session:
use Duration;
use ;
# async
No browser headers. A 4xx or 5xx is not an error unless you call
error_for_status(). See
API clients.
What it matches
A user agent is one header. A fingerprinting server also reads the ClientHello, the HTTP/2 frames, and the header order. Leyline matches every layer a capture shows:
| Layer | What Leyline sends |
|---|---|
| TLS | Cipher suites, extensions and their order, GREASE, key shares, and ALPN, from BoringSSL at the revision Chrome 155 ships. |
| HTTP/2 | SETTINGS, window update, pseudo-header order, and stream priority. |
| HTTP/3 | QUIC ClientHello, transport parameters, connection ID lengths, HTTP/3 SETTINGS, and the size of the first datagram. |
| Headers | The browser's header set and order for each kind of request: navigation, form, script, image, XHR, frame, and reload. |
| Fetch metadata | sec-fetch-site, Origin, and Referer follow the Fetch rules across redirect chains. |
| Cookies | SameSite follows each browser: Chrome judges the final target, Firefox the whole redirect chain. |
Of the 31 bundled profiles, 25 are captures of the shipped browser. Each
profile names the build it came from in captured_against, and the
profile reference
lists the source of every one.
Profiles
| Browser | Versions | Notes |
|---|---|---|
| Chrome | 145 to 155 | Android is captured for Chrome 145 only. |
| Brave | 146, 154, 155 | |
| Firefox | 148 to 158 | Firefox 155 to 157 offer QUIC v2. |
| Safari | 18, 26, 27 | macOS. |
| Safari on iOS | 17, 18, 27 | |
| OkHttp | 4.12 | Android. |
| CFNetwork | iOS 18, iOS 27, macOS 26 | Native app traffic, not Safari. |
Edge and Opera are brand overlays on the Chrome profiles for desktop
platforms. The Opera overlay covers Chrome 145 to 153. To send a profile that
is not bundled, load it at runtime with SessionBuilder::profile.
Install
Add Leyline and Tokio to Cargo.toml:
[]
= "0.1"
= { = "1", = ["macros", "rt-multi-thread"] }
The package is leyline-http. The library is leyline.
Requirements
- Rust 1.96 or later, and Tokio.
- One of these targets:
aarch64-apple-darwin,x86_64-unknown-linux-gnu,aarch64-unknown-linux-gnu,x86_64-unknown-linux-musl,aarch64-unknown-linux-musl, orx86_64-pc-windows-msvc. Intel macOS is not supported. - A C and C++ compiler and
git, to build BoringSSL from source: Xcode Command Line Tools on macOS, GCC or Clang on Linux, the MSVC build tools on Windows. On musl, a musl C and C++ toolchain. No CMake, NASM, Go, or libclang is needed.
The first build compiles BoringSSL, so it takes longer than a pure Rust dependency. Later builds reuse it.
Choose a browser
Session::browser(Browser::default()) sends the newest bundled Chrome with a
Windows identity. A patch release can move that default to a newer capture.
To keep one fingerprint, pin the browser and the platform:
use ;
#
Reuse one session to share connections and cookies.
Also included
- Crawling:
HostLimits,ProxyPool, andResponse::block(). - Accounts:
Tabfor pages and forms,Deviceto save an account to a file. - Atomic downloads and
Linkpagination. - Proxies: HTTP and HTTPS, and SOCKS5 with the
socksfeature. The pool keeps connections per proxy, and HTTP/3 runs through SOCKS5UDP ASSOCIATE. - Cookies: a jar with RFC 6265bis limits and
Securerules that you can save and restore with serde. - WebSocket, streaming bodies, multipart forms, and gzip, deflate, Brotli, and zstd decoding.
- TLS trust: custom roots, certificate pins, client certificates, and a TLS
version floor through
TlsTrustConfig. - Typed errors:
Error::category()names the failure, andis_retryable()says whether to try again. Retries are off until you set aRetryPolicy. Debugoutput masks passwords, tokens, cookies, and query values.- The bundled BoringSSL prefixes its symbols with
LEYLINE_, so it links beside OpenSSL and Cloudflare'sboring.
Limits
- A profile covers the TLS, HTTP/2, HTTP/3, and header properties its capture shows. It does not reproduce every byte a browser sends, and it runs no JavaScript.
- Firefox on Android sends the desktop Firefox ClientHello.
- The kernel picks the TCP option order and window scale. Leyline sets TTL,
TCP_NODELAY, and, where the OS allows, MSS, don't-fragment, and a window clamp. - HTTP/3 sends no 0-RTT data, and it can't run through an HTTP or HTTPS proxy. Safari on iOS 17, OkHttp, and the CFNetwork profiles have no HTTP/3 data.
Response::audit()reports what the configured profile sends. It is not a packet capture.- Detection by a remote site is not a security defect. See SECURITY.md.
Documentation
| Page | Contents |
|---|---|
| Quick start | From an empty project to a parsed response. |
| User guide | Sessions, requests, streaming, proxies, cookies, crawling, accounts, HTTP/3, and TLS trust. |
| API reference | Every public item, and each task mapped to its one call. |
| Profile reference | Bundled profiles and their capture status. |
| Benchmarks | Paired runs against wreq, reqwest, and tls-client, losses included. |
| Changelog | Release notes and the version policy. |
Security
To report a vulnerability, follow SECURITY.md.
Contributing
CONTRIBUTING.md describes the build and the checks.
License
Leyline is licensed under the MIT license. It depends on forks of BoringSSL (MIT, Apache-2.0, and BSD-3-Clause) and quiche (BSD-2-Clause), published as separate crates. NOTICE lists the forks and their licenses.
Copyright 2026 Manaforge Technologies, LLC.