urlx is a memory-safe, from-scratch reimplementation of curl and libcurl. No OpenSSL. No unsafe outside the FFI boundary. 1,300 of curl's own tests pass against urlx.
# It's curl. Just in Rust.
urlx https://example.com
urlx -d '{"key":"val"}' -H 'Content-Type: application/json' https://api.example.com
urlx -Lo file.tar.gz https://example.com/file.tar.gz
urlx -u user:pass --digest https://api.example.com/admin
urlx -Z https://a.com https://b.com https://c.com # parallel transferscurl is one of the most important pieces of software ever written. It's also 180,000 lines of C with a long history of memory safety CVEs. urlx asks: what if we just rewrote it?
- Memory-safe — zero
unsafein the core library and CLI - No OpenSSL — TLS via rustls, with optional OpenSSL for TLS-SRP
- Drop-in CLI — same flags, same output, same exit codes — 261 long flags, 46 short
- Drop-in C library —
liburlx-ffiexposes the libcurl C ABI for existing C/C++ programs - Idiomatic Rust API — async/sync
Easy/Multihandles,thiserrorerrors, feature-flagged protocols - Tested against curl itself — curl's own test suite is the spec
urlx is validated against curl's own test suite (tests 1–1400):
| Metric | Count |
|---|---|
| Pass | 1,300 |
| Skip (debug builds, missing platform features) | 92 |
| Permanently excluded (curl source analysis, libcurl C API) | 25 |
| Pass rate of evaluated tests | 100% |
| Status | |
|---|---|
| HTTP/1.0, 1.1, 2, 3 (QUIC) | Full (HTTP/3 untested) |
| TLS 1.2 / 1.3 | rustls, cert pinning, client certs, STARTTLS |
| Auth | Basic, Digest, Bearer, NTLMv2, SCRAM-SHA-256, AWS SigV4, SASL |
| FTP / FTPS | Upload, resume, directory ops, active & passive, EPSV |
| SSH / SFTP / SCP | Password + pubkey auth, quote commands |
| SMTP, IMAP, POP3 | STARTTLS, SASL, MIME |
| WebSocket | RFC 6455, close codes, fragmentation |
| MQTT | Subscribe, publish |
| Gopher, DICT, TFTP, RTSP | Full |
| Cookies | Netscape format, domain-indexed, PSL, SameSite |
| HSTS | Preload list |
| Proxy | HTTP CONNECT, SOCKS4/4a/5, HTTPS tunnel, proxy auth |
| DNS | Happy Eyeballs, DoH, DoT, custom servers, caching |
| Decompression | gzip, deflate, brotli, zstd |
| CLI flags | 261 long + 46 short (curl has ~250 long) |
| FFI | 156 CURLOPT, 49 CURLINFO, 57 exported C functions |
cargo install urlx-cli # from crates.io
brew install jonwiggins/tap/urlx # HomebrewOr build from source:
git clone --recurse-submodules https://github.com/jonwiggins/urlx
cd urlx && cargo build --releaselet mut easy = liburlx::Easy::new();
easy.url("https://httpbin.org/get")?;
let response = easy.perform()?;
println!("{}", response.status()); // 200
println!("{}", response.body_str()?); // {"origin": "..."}[dependencies]
liburlx = "0.2"#include "urlx.h"
CURL *curl = curl_easy_init();
curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
CURLcode res = curl_easy_perform(curl);
curl_easy_cleanup(curl);Link against liburlx_ffi instead of libcurl — no code changes needed.
┌─────────────┐
│ urlx CLI │ Drop-in curl replacement
└──────┬──────┘
│
┌──────────────┐ ┌──────┴──────┐
│ liburlx-ffi │────│ liburlx │ Core Rust library
│ (C ABI) │ │ (Rust API) │
└──────────────┘ └──────┬──────┘
│
┌────────────┼────────────┐
│ │ │
┌─────┴─────┐ ┌───┴───┐ ┌─────┴─────┐
│ Protocols │ │ TLS │ │ DNS │
│ HTTP, FTP, │ │rustls │ │ Cache, │
│ WS, SMTP...│ │ │ │ HE, DoH │
└────────────┘ └───────┘ └───────────┘
Three crates, one workspace:
| Crate | What it does |
|---|---|
liburlx |
Core transfer library — pure Rust, async/sync API, 20+ feature flags |
liburlx-ffi |
C ABI layer — link against it instead of libcurl |
urlx-cli |
The urlx binary — drop-in curl replacement |
See CONTRIBUTING.md. The short version:
cargo fmt && cargo clippy --all-targets && cargo test --workspaceEvery commit must pass the full guardrail suite. Conventional commits are enforced by CI.
urlx would not exist without curl by Daniel Stenberg. curl's behavior is our specification, and its test suite is our acceptance criteria.
Built with tokio, rustls, h2, quinn, and russh.
MIT