cURL to Rust Converter

Paste a cURL command and get equivalent Rust built on the reqwest blocking client — the de facto HTTP crate for Rust. The parser reads the method, repeated headers, request body, -u basic auth and cookies, then emits a complete fn main() -> Result<(), Box<dyn std::error::Error>> with a chained builder: .request(...), .header(...), .basic_auth(...), .body(...), .send(). The exact Cargo.toml dependency line is included as a comment. Runs entirely in your browser.

How to use the cURL to Rust Converter

Paste a cURL command into the cURL command box — a browser Copy as cURL string with backslash line continuations works. Press Convert to Rust (it also converts as you type) and the Rust code appears below. Click Example to load a JSON POST with a bearer token, then Copy the snippet into src/main.rs. The output starts with a // Cargo.toml: reqwest = { version = "0.12", features = ["blocking"] } comment so you know exactly what to add, then use reqwest::Method;, then a fn main() returning a boxed-error Result. It builds reqwest::blocking::Client::new(), calls .request(Method::POST, url), chains .header(k, v) per header, adds .basic_auth(user, Some(pass)) for -u, attaches .body(...) when there is a payload, and finishes with .send()? plus a resp.status() / resp.text()? read. The trailing ? operators make the boxed-error return type compile cleanly.

Converting cURL to Rust with reqwest

reqwest is the standard high-level HTTP client in the Rust ecosystem, built on hyper and Tokio. It ships two front ends: an async client (the default) and a blocking client behind the blocking feature flag. This converter targets the blocking client because it produces a short, self-contained fn main() that runs without an async runtime, executor macros, or .await sprinkled through the code — ideal for scripts, CLIs and quick API calls. That is also why the generated header comment enables features = ["blocking"]; forget it and the blocking module simply will not exist.

The builder is fluent: Client::new().request(method, url) returns a RequestBuilder you decorate with .header(), .basic_auth() and .body() before calling .send(). Rust’s error handling shapes the output: nearly every step returns a Result, so the function signature is Result<(), Box<dyn std::error::Error>> and each fallible call ends in ? to propagate errors upward. The method is passed as a reqwest::Method value. Basic auth uses .basic_auth(user, Some(pass)) — the password is an Option — rather than a hand-built header. Any Content-Length header is dropped because reqwest derives it from the body.

If you would prefer the async client, the body of the function maps over almost directly — swap the blocking client for reqwest::Client and add .await after .send() and .text(). For the same request in other ecosystems, see the cURL to Python converter or the multi-language cURL converter.

Common use cases

  • CLI tools — drop an API call into a Rust binary without wiring up an async runtime.
  • DevTools to Rust — turn a browser “Copy as cURL” into a working reqwest request.
  • Crate scaffolding — bootstrap a third-party integration, then add typed structs, retries or timeouts.
  • Documentation — present an endpoint as idiomatic Rust beside the shell example.
  • Learning reqwest — see how the builder chain and the ? error operator fit together.
  • Porting scripts — move a curl-based job into a compiled, type-checked Rust program.

Frequently asked questions

Blocking or async client?

The output uses the blocking client so it runs in a plain fn main() with no runtime. To go async, switch to reqwest::Client and add .await after .send() and .text().

What do I add to Cargo.toml?

The first line of the output is a comment with the exact dependency: reqwest = { version = "0.12", features = ["blocking"] }. The blocking feature is required.

Why does main return a Result?

Because most reqwest calls are fallible. The signature Result<(), Box<dyn std::error::Error>> lets each step use the ? operator to propagate errors instead of unwrapping.

How is -u basic auth represented?

As .basic_auth(user, Some(pass)) — the password is wrapped in Some(...) because the parameter is an Option.

Need another language?

Embed this tool on your site

Free to embed, no attribution required (but appreciated). Paste this where you want the tool to appear: