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.
Why?
curl 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
Test Suite Compatibility
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% |
What's Supported
| 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 |
Install
Or build from source:
&&
Use as a Rust Library
let mut easy = new;
easy.url?;
let response = easy.perform?;
println!; // 200
println!; // {"origin": "..."}
[]
= "0.2"
Use as a C Library (libcurl ABI)
CURL *curl = ;
;
;
CURLcode res = ;
;
Link against liburlx_ffi instead of libcurl — no code changes needed.
Architecture
┌─────────────┐
│ 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 |
Contributing
See CONTRIBUTING.md. The short version:
&& &&
Every commit must pass the full guardrail suite. Conventional commits are enforced by CI.
Acknowledgements
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.
License
MIT