Rust WebSocket client with TLS fingerprint impersonation, powered by libcurl-impersonate.
Bypass TLS fingerprinting by impersonating real browser signatures (Chrome, Safari, Firefox, Edge, Tor).
| Crate | Description |
|---|---|
impcurl-sys |
Dynamic FFI bindings for libcurl-impersonate with auto-fetch |
impcurl |
Safe blocking wrapper — WebSocket handshake, send, recv |
impcurl-ws |
Async tokio Stream + Sink WebSocket connection |
[dependencies]
impcurl-ws = "1.1.1"
futures-util = "0.3"
tokio = { version = "1", features = ["macros", "rt-multi-thread"] }use futures_util::{SinkExt, StreamExt};
use impcurl_ws::{Message, WsConnection};
#[tokio::main]
async fn main() -> anyhow::Result<()> {
let mut ws = WsConnection::connect("wss://echo.websocket.org").await?;
ws.send(Message::Text("hello".to_owned())).await?;
if let Some(message) = ws.next().await.transpose()? {
match message {
Message::Text(text) => println!("{text}"),
Message::Binary(bytes) => println!("{} bytes", bytes.len()),
Message::Ping(_) | Message::Pong(_) | Message::Close(_) => {}
}
}
Ok(())
}use impcurl::ImpersonateTarget;
use impcurl_ws::{ControlFrameMode, WsConnection};
use std::time::Duration;
let ws = WsConnection::builder("wss://example.com/ws")
.header("Origin", "https://example.com")
.header("User-Agent", "Mozilla/5.0 ...")
.proxy("socks5h://127.0.0.1:1080")
.impersonate(ImpersonateTarget::Chrome136)
.connect_timeout(Duration::from_secs(10))
.control_frame_mode(ControlFrameMode::Manual)
.read_buffer_messages(32)
.write_buffer_messages(32)
.verbose(true)
.connect()
.await?;The libcurl-impersonate shared library is resolved in this order:
CURL_IMPERSONATE_LIBenv var- Near executable (
../lib/and side-by-side) IMPCURL_LIB_DIRenv var~/.impcurl/lib,~/.cuimp/binaries- Auto-fetch from versioned libcurl-impersonate assets on this repo's GitHub Releases (enabled by default)
impcurl-ws does not expose a lib_path(...) builder escape hatch anymore. Library resolution is treated as deployment configuration rather than a connection-level concern.
impcurl now auto-resolves a CA bundle and applies CURLOPT_CAINFO during websocket setup.
Resolution order:
CURL_CA_BUNDLESSL_CERT_FILE- Platform defaults (Linux:
/etc/ssl/certs/ca-certificates.crt,/etc/pki/tls/certs/ca-bundle.crt, ...)
This removes the need for app-level distro-specific CA symlink hacks in most Linux deployments.
| Env Var | Description |
|---|---|
IMPCURL_AUTO_FETCH=0 |
Disable auto-download |
IMPCURL_LIBCURL_VERSION |
libcurl-impersonate asset version (default current crate version) |
IMPCURL_LIBCURL_REPO |
GitHub repo for libcurl-impersonate assets (default tuchg/impcurl) |
IMPCURL_AUTO_FETCH_CACHE_DIR |
Override fetch cache directory |
IMPCURL_DISABLE_AUTO_CAINFO=1 |
Disable automatic CURLOPT_CAINFO injection |
impcurl-ws (async tokio client)
└── impcurl (safe blocking wrapper)
└── impcurl-sys (dynamic FFI + auto-fetch)
└── libcurl-impersonate (.so/.dylib/.dll)
On Unix, the async event loop uses CURLMOPT_SOCKETFUNCTION / CURLMOPT_TIMERFUNCTION with tokio::io::unix::AsyncFd for efficient socket-level readiness notification. Non-Unix falls back to curl_multi_poll.
MIT
This repository includes a workflow that publishes versioned libcurl-impersonate assets:
- GitHub Actions workflow:
.github/workflows/release-libcurl-impersonate-assets.yml - Local packaging helper:
scripts/package_libcurl_assets.sh
Asset naming:
impcurl-libcurl-impersonate-v<version>-x86_64-apple-darwin.tar.gzimpcurl-libcurl-impersonate-v<version>-aarch64-apple-darwin.tar.gzimpcurl-libcurl-impersonate-v<version>-x86_64-unknown-linux-gnu.tar.gzimpcurl-libcurl-impersonate-v<version>-aarch64-unknown-linux-gnu.tar.gzimpcurl-libcurl-impersonate-v<version>-x86_64-apple-darwin.sha256impcurl-libcurl-impersonate-v<version>-aarch64-apple-darwin.sha256impcurl-libcurl-impersonate-v<version>-x86_64-unknown-linux-gnu.sha256impcurl-libcurl-impersonate-v<version>-aarch64-unknown-linux-gnu.sha256
Note: Linux aarch64 publishing depends on an available ARM64 source image for
libcurl-impersonate. macOS assets are packaged by extracting standalone
.dylib files from curl-cffi wheels during the release workflow.