cURL to Rust

Convert a cURL command into a Rust reqwest request.

cURL Command
Rust (reqwest) Output
Rust (reqwest) code appears here

Related Tools

Documentation

What is curl-to-Rust?

This tool converts a curl command into an async Rust program built on reqwest, the de facto standard HTTP client crate for Rust (built on hyper), running under the tokio async runtime.

How it works

Curl's flags are parsed into method, url, headers, a raw body string, form fields, Basic Auth, and the insecure flag. The Rust emitter builds a reqwest::Client, then chains a request builder: .header(key, value) for each curl -H, .basic_auth(user, Some(pass)) for -u, and .body(...) for -d/--data — passed through as a raw Rust string literal (using a raw string r#"..."# when the body itself contains double quotes, so nothing needs escaping). The HTTP method is built via reqwest::Method::from_bytes(...) rather than reqwest's named constructors (Client::get, Client::post, etc.), because that accepts any method string — including less common verbs like PATCH or a custom method — not just the handful reqwest exposes helpers for.

Features

  • Async output using #[tokio::main] and reqwest
  • Any HTTP method supported via Method::from_bytes, not just the common ones
  • Body passed through as a raw string, using r#"..."# automatically when it contains quotes
  • -F/--form uploads via multipart::Form.text(key, value) for fields, .file(key, path).await? for files (reqwest reads the file from disk directly, no manual I/O needed)
  • -k/--insecure mapped to ClientBuilder::danger_accept_invalid_certs(true)

Example

Input: curl -X POST https://api.example.com/v1/users -H "Content-Type: application/json" -H "X-Api-Key: abc123" -d '{"name":"Ada Lovelace","role":"admin"}'

Output:

use reqwest::Client;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new();

    let req = client.request(reqwest::Method::from_bytes(b"POST")?, "https://api.example.com/v1/users")
        .header("Content-Type", "application/json")
        .header("X-Api-Key", "abc123")
        .body(r#"{"name":"Ada Lovelace","role":"admin"}"#);

    let response = req.send().await?;

    println!("{}", response.status());
    println!("{}", response.text().await?);
    Ok(())
}

Common errors

The output needs the reqwest and tokio crates in Cargo.tomltokio specifically needs its "full" feature (or at minimum "rt-multi-thread" and "macros") enabled, since #[tokio::main] won't compile without it. Forgetting reqwest's "multipart" feature flag will fail to compile any command that used -F.

Best practices

Reuse one Client across many requests instead of constructing a new one each time — it holds a connection pool internally and is cheap to clone. Always propagate errors with ? (as the generated code does) rather than .unwrap(), and avoid danger_accept_invalid_certs(true) outside local development.

Frequently Asked Questions

Why reqwest specifically?

reqwest is the de facto standard async HTTP client for Rust, built on hyper — the generated code targets it directly rather than a lower-level alternative, since it's what most Rust HTTP code in the wild already uses.

Does this need tokio?

Yes — reqwest's async API needs an async runtime, and the generated main function is annotated #[tokio::main], which requires the tokio crate with the "full" (or at least "rt-multi-thread" + "macros") feature enabled in Cargo.toml.

How is an arbitrary HTTP method (like PATCH) handled?

Via reqwest::Method::from_bytes(...), which accepts any method string — not just the handful reqwest exposes as named constructors (get, post, put, delete) — so unusual verbs from the original curl command still work.

Does it support multipart file uploads?

Yes, via reqwest::multipart::Form — text fields use .text(key, value) and file fields use .file(key, path).await?, which reads the file from disk directly (unlike the Node/Go generators, reqwest's API makes this a one-line call).