A high-performance HTTP client workspace for crypto exchange HFT applications. Forked from wreq / reqwest, optimized for low-latency network I/O, browser emulation, and automated scraping.
hpx/
├── bin/
│ └── hpx-cli/ # CLI binary — HTTP client, scraper, download manager, CDP server
├── crates/
│ ├── hpx/ # Core HTTP client library (TLS, HTTP/1+2, pooling, middleware)
│ ├── hpx-emulation/ # Browser fingerprint profiles (JA3/JA4, HTTP/2 settings)
│ ├── hpx-browser/ # Headless browser engine (DOM, CSS, layout, JS, challenge detection)
│ ├── hpx-dl/ # Segmented download engine (resume, queue, persistence)
│ ├── hpx-streams/ # Streaming response codecs (JSON/CSV/Protobuf/Arrow)
│ └── yawc/ # WebSocket client/server (RFC 6455, compression)
└── Justfile # Task runner (fmt, lint, test, ci)
hpx — Core HTTP Client
The foundation crate. Everything else builds on top of this.
Provides: Client, ClientBuilder, RequestBuilder, Response, Body, WebSocket upgrade, cookie store, redirect policy, Tower middleware stack, TLS backends (BoringSSL / Rustls).
Use when: You need to make HTTP requests — GET, POST, JSON APIs, file uploads, WebSocket connections, or reverse proxy traffic.
// Minimal
let body = hpx::get("https://api.example.com").send().await?.text().await?;
// Full control
let client = hpx::Client::builder()
.emulation(BrowserProfile::Chrome)
.proxy("socks5://127.0.0.1:1080")
.cookie_provider(Jar::default())
.build()?;Key feature flags: json, ws, cookies, gzip/brotli/zstd, socks, hickory-dns, hft (preset), stealth (preset).
hpx-emulation — Browser Fingerprint Profiles
Companion crate for hpx. Provides ready-made browser emulation profiles that configure TLS ciphersuites, HTTP/2 settings, and default headers to match real browsers.
Provides: Emulation, EmulationOption, BrowserProfile (Chrome, Firefox, Safari, Edge, OkHttp), EmulationOS, fingerprint diffing.
Use when: You need to impersonate a specific browser for TLS fingerprint checks (JA3/JA4), or when scraping sites that inspect HTTP/2 SETTINGS frames.
use hpx_emulation::Emulation;
let resp = hpx::get("https://tls.peet.ws/api/all")
.emulation(Emulation::Firefox136)
.send()
.await?;Depends on: hpx (provides the EmulationFactory trait that hpx::RequestBuilder::emulation() accepts).
hpx-browser — Headless Browser Engine
A lightweight headless browser built on hpx. Parses HTML/CSS, builds a DOM, runs JavaScript (via V8/Deno), detects anti-bot challenges, and renders pages to text/markdown/screenshots.
Provides: HTML parser, CSS parser + cascade, DOM tree, layout engine, JS runtime (Deno_core), challenge detection (Cloudflare, AWS-WAF, Kasada, PerimeterX, DataDome, hCaptcha, reCAPTCHA), CDP protocol support, parallel scraping, stealth mode, canvas rendering.
Use when: You need to render JavaScript-heavy pages, bypass anti-bot protections, scrape SPAs, or run a headless browser programmatically.
Key modules:
| Module | Purpose |
|---|---|
challenge |
Anti-bot challenge classifier (CF, AWS-WAF, Kasada, etc.) |
html_parser / css_parser |
DOM + CSSOM construction |
dom / layout |
DOM tree + box model layout |
js_runtime |
V8-based JavaScript execution (feature v8) |
parallel |
Multi-URL concurrent scraping |
stealth |
Anti-fingerprinting patches |
protocol |
CDP (Chrome DevTools Protocol) server |
Depends on: hpx (network), deno_core (JS), html5ever (HTML), image/skia-safe (canvas, optional).
hpx-dl — Download Engine
Segmented HTTP download engine with resume, priority queue, speed limiting, and SQLite persistence.
Provides: DownloadEngine, EngineBuilder, SegmentDownloader, PriorityQueue, SqliteStorage, checksum verification (SHA-256/384/512, MD5), metalink parsing, event broadcasting.
Use when: You need to download large files with pause/resume, parallel segments, integrity verification, or managed download queues.
use hpx_dl::{DownloadEngine, EngineConfig};
let engine = DownloadEngine::new(EngineConfig::default());
let id = engine.add("https://example.com/large-file.bin").await?;
engine.start(id).await?;Key features: http (enable HTTP client integration), sqlite (persistent storage), test (in-memory storage for tests).
Depends on: hpx (HTTP client for segments), sqlx (persistence), ahash (concurrent data structures).
hpx-streams — Streaming Response Codecs
Extension trait for hpx::Response that adds streaming decode for structured response formats.
Provides: JsonStreamResponse, CsvStreamResponse, ProtobufStreamResponse, ArrowIpcStreamResponse — each adds a .xxx_stream() method to hpx::Response.
Use when: You're consuming large paginated APIs, database dumps, or event streams that return JSON arrays, CSV, Protobuf, or Arrow IPC.
use hpx_streams::JsonStreamResponse as _;
let mut stream = client
.get("http://localhost:8080/large-json-array")
.send()
.await?
.json_array_stream::<MyItem>(1024);Depends on: hpx (the Response type), serde_json/csv/prost/arrow-ipc (per feature).
hpx-yawc (yawc) — WebSocket
RFC 6455 WebSocket implementation with permessage-deflate compression. Can be used standalone or as the WebSocket backend for hpx.
Provides: WebSocket client/server, frame codec, masking, compression (zlib/deflate), Axum integration, SIMD UTF-8 validation.
Use when: You need a standalone WebSocket client or server, or when you want the ws feature in hpx (this is the default backend).
use futures::{SinkExt, StreamExt};
use hpx_yawc::WebSocket;
let mut ws = WebSocket::connect("wss://echo.websocket.org".parse()?).await?;
ws.send(hpx_yawc::Frame::text("hello")).await?;Depends on: tokio, rustls (TLS), optional axum integration.
hpx-fastwebsockets — WebSocket (Alternative)
Alternative WebSocket backend for hpx. Activated via ws-fastwebsockets feature flag. Takes priority over yawc when both are enabled.
The hpx-cli binary (bin/hpx-cli/) is a multi-tool HTTP client that ties all the crates together.
# Simple GET
hpx https://api.example.com/data
# POST with JSON body
hpx -X POST https://api.example.com/data -j '{"key":"value"}'
# With headers and auth
hpx -H 'Authorization: Bearer TOKEN' https://api.example.com/protected
# Form data
hpx -X POST https://httpbin.org/post -f 'name=test' -f 'email=test@example.com'
# Save response to file
hpx https://example.com/file.zip -o file.zip
# Follow redirects + timing
hpx -L -T https://httpbin.org/redirect/3
# WebSocket
hpx wss://echo.websocket.org
# Proxy
hpx --proxy socks5://127.0.0.1:1080 https://api.example.com# Fetch and render a page (JS execution, challenge bypass)
hpx fetch https://example.com --dump html
# Dump rendered text
hpx fetch https://example.com --dump text
# Dump all links
hpx fetch https://example.com --dump links
# Wait for a CSS selector
hpx fetch https://example.com --selector '#content' --wait 10
# Evaluate JS on the page
hpx fetch https://example.com -e 'document.title'
# Scrape multiple URLs in parallel
hpx scrape https://a.com https://b.com --concurrency 20
# Start a CDP (Chrome DevTools Protocol) server
hpx serve --port 9222# Add a download
hpx dl add https://example.com/large.bin -o ./large.bin
# Add with speed limit, checksum, mirrors
hpx dl add https://example.com/file.bin \
--speed-limit 1MB/s \
--checksum sha256:abc123... \
--mirror https://mirror1.com/file.bin \
--max-connections 8
# Pause / resume / remove
hpx dl pause <id>
hpx dl resume <id>
hpx dl remove <id>
# List all downloads
hpx dl list
# Check status
hpx dl status <id># Run proxy integration smoke tests
hpx proxy-test --proxy http://127.0.0.1:7890hpx-cli (binary)
├── hpx (HTTP client)
├── hpx-emulation (browser profiles)
├── hpx-browser (headless browser, challenge detection)
├── hpx-dl (download engine)
└── hpx-streams (streaming codecs)
hpx (core)
├── hpx-emulation (optional, via emulation feature)
└── hpx-yawc (optional, via ws feature)
hpx-dl
└── hpx (HTTP client for segments)
hpx-streams
└── hpx (extends Response with streaming methods)
hpx-browser
└── hpx (network layer)
Standalone usage: Each crate can be used independently. hpx-yawc works without hpx for raw WebSocket connections. hpx-dl can be used with its own EngineBuilder without the CLI.
Default: boring, http1, http2, stream, tracing.
| Feature | Default | Description |
|---|---|---|
| TLS | ||
boring |
Yes | BoringSSL TLS backend |
rustls-tls |
No | Rustls TLS backend (pure Rust) |
webpki-roots |
No | WebPKI root certificates |
| HTTP | ||
http1 |
Yes | HTTP/1.1 support |
http2 |
Yes | HTTP/2 support |
| Content | ||
json |
No | JSON request/response support |
simd-json |
No | SIMD-accelerated JSON (enables json) |
form |
No | x-www-form-urlencoded support |
query |
No | URL query string serialization |
multipart |
No | Multipart form data |
stream |
No | Streaming request/response bodies |
charset |
No | Character encoding support |
| Compression | ||
gzip |
No | Gzip decompression |
brotli |
No | Brotli decompression |
zstd |
No | Zstandard decompression |
deflate |
No | Deflate decompression |
| WebSocket | ||
ws |
No | WebSocket support (alias for ws-yawc) |
ws-yawc |
No | WebSocket via hpx-yawc backend |
ws-fastwebsockets |
No | WebSocket via fastwebsockets backend |
| Networking | ||
cookies |
No | Cookie store support |
socks |
No | SOCKS proxy support |
hickory-dns |
No | Async DNS resolver (Hickory) |
system-proxy |
No | System proxy configuration |
| Observability | ||
tracing |
No | Tracing/logging support |
| Presets | ||
hft |
No | Low-latency: BoringSSL, HTTP/1+2, streaming, Hickory DNS, SIMD JSON, Zstd, fast WS |
stealth |
No | Browser-like: BoringSSL, HTTP/1+2, decompression, cookies, charset, Hickory DNS, fast WS |
# Minimal HTTP client
hpx = "2"
# JSON API client
hpx = { version = "2", features = ["json", "cookies", "gzip"] }
# WebSocket client
hpx = { version = "2", features = ["ws"] }
# High-performance trading
hpx = { version = "2", default-features = false, features = ["hft"] }
# Browser-like scraping
hpx = { version = "2", default-features = false, features = ["stealth"] }
# Pure Rust (no C dependencies)
hpx = { version = "2", default-features = false, features = ["rustls-tls", "http1", "http2"] }Default: emulation.
| Feature | Default | Description |
|---|---|---|
emulation |
Yes | Browser emulation profiles (Chrome, Firefox, Safari, Opera, OkHttp) |
emulation-compression |
No | Compression settings for emulation profiles |
emulation-rand |
No | Random emulation profile selection |
emulation-serde |
No | Serde serialization for emulation types |
Default: rustls-ring.
| Feature | Default | Description |
|---|---|---|
rustls-ring |
Yes | TLS via rustls with ring crypto |
rustls-aws-lc-rs |
No | TLS via rustls with AWS LC crypto |
axum |
No | Axum WebSocket extractor |
simd |
No | SIMD-accelerated UTF-8 validation |
smol |
No | smol async runtime support |
zlib |
No | Native zlib compression backend |
BoringSSL is the default TLS backend, providing robust support for modern TLS features and extensive browser emulation capabilities. Recommended for most use cases, especially when browser fingerprinting is required.
[dependencies]
hpx = "2"A pure Rust TLS implementation. Useful for environments where C dependencies are difficult to manage or when you prefer the safety guarantees of a pure Rust stack.
Note: Switching to Rustls may affect the availability or behavior of certain browser emulation features that rely on specific BoringSSL capabilities.
[dependencies]
hpx = { version = "2", default-features = false, features = ["rustls-tls", "http1", "http2"] }#[tokio::main]
async fn main() -> hpx::Result<()> {
let body = hpx::get("https://www.rust-lang.org")
.send()
.await?
.text()
.await?;
println!("body = {body:?}");
Ok(())
}Requires the json feature.
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize, Debug)]
struct User {
name: String,
email: String,
}
#[tokio::main]
async fn main() -> hpx::Result<()> {
let user = User {
name: "John Doe".to_string(),
email: "john@example.com".to_string(),
};
let response = hpx::Client::new()
.post("https://jsonplaceholder.typicode.com/users")
.json(&user)
.send()
.await?;
println!("Status: {}", response.status());
Ok(())
}Requires the stream feature. For reverse proxies and API gateways, hpx can forward framework-native request bodies without buffering the full payload.
use axum::{
body::Body as AxumBody,
extract::{Request as AxumRequest, State},
http::{Response as AxumResponse, StatusCode},
};
use hpx::{Body, Client, Request};
async fn proxy(
State(client): State<Client>,
mut req: AxumRequest<AxumBody>,
) -> Result<AxumResponse<Body>, StatusCode> {
let path_and_query = req
.uri()
.path_and_query()
.map(|value| value.as_str())
.unwrap_or("/");
let upstream_uri = format!("https://upstream.internal{path_and_query}")
.parse()
.map_err(|_| StatusCode::BAD_REQUEST)?;
*req.uri_mut() = upstream_uri;
let upstream_req = Request::from_http(req);
let upstream_res = client
.execute(upstream_req)
.await
.map_err(|_| StatusCode::BAD_GATEWAY)?;
Ok(http::Response::<Body>::from(upstream_res))
}Requires the hpx-emulation crate with default features.
use hpx_emulation::Emulation;
#[tokio::main]
async fn main() -> hpx::Result<()> {
let resp = hpx::get("https://tls.peet.ws/api/all")
.emulation(Emulation::Firefox136)
.send()
.await?;
println!("{}", resp.text().await?);
Ok(())
}Requires the ws feature.
use futures_util::{SinkExt, StreamExt, TryStreamExt};
use hpx::{header, ws::message::Message};
#[tokio::main]
async fn main() -> hpx::Result<()> {
let websocket = hpx::websocket("wss://echo.websocket.org")
.header(header::USER_AGENT, env!("CARGO_PKG_NAME"))
.send()
.await?;
let (mut tx, mut rx) = websocket.into_websocket().await?.split();
tokio::spawn(async move {
if let Err(err) = tx.send(Message::text("Hello, World!")).await {
eprintln!("failed to send message: {err}");
}
});
while let Some(message) = rx.try_next().await? {
if let Message::Text(text) = message {
println!("received: {text}");
}
}
Ok(())
}Requires the cookies feature.
use hpx::cookie::Jar;
#[tokio::main]
async fn main() -> hpx::Result<()> {
let jar = Jar::default();
let client = hpx::Client::builder()
.cookie_provider(jar.clone())
.build()?;
let _resp = client
.get("https://httpbin.org/cookies/set/session/123")
.send()
.await?;
println!("Cookies: {:?}", jar.cookies("https://httpbin.org"));
Ok(())
}simd-json: Replacesserde_jsonwith SIMD-accelerated JSON parsinghickory-dns: High-performance async DNS resolver, avoids blocking system callszstd: Fastest compression/decompression ratio for most workloads- Lock-free internals: Uses
sccconcurrent containers andarc-swapfor hot-path data
Apache-2.0