Skip to the content.

How to convert curl to C#

There are two ways to convert curl to C#: run the curl command directly with Curl.ExecuteAsync (no conversion at all), or generate starter code with Curl.ToHttpClient(cmd) and its siblings for Python, JavaScript and PowerShell.

dotnet add package CurlDotNet

Option 1: do not convert, just run it

The most faithful conversion is none. Curl.ExecuteAsync accepts the command exactly as it appears in the API documentation:

using CurlDotNet;

var result = await Curl.ExecuteAsync(
    "curl -H 'Authorization: Bearer abc123' https://httpbin.org/bearer");

Console.WriteLine($"{result.StatusCode}: {result.Body}");

If you prefer typed code, the fluent builder expresses the same request and can print the curl command back out:

using CurlDotNet.Core;

var request = CurlRequestBuilder
    .Get("https://httpbin.org/bearer")
    .WithBearerToken("abc123");

Console.WriteLine(request.ToCurlCommand());
var result = await request.ExecuteAsync();

Option 2: generate HttpClient code

Curl.ToHttpClient returns C# source as a string:

using CurlDotNet;

string code = Curl.ToHttpClient(
    "curl -H 'Authorization: Bearer t' https://api.example.com/me");
Console.WriteLine(code);

Output:

// Generated by CurlDotNet from: curl -H 'Authorization: Bearer t' https://api.example.com/me
var handler = new HttpClientHandler
{
    AllowAutoRedirect = false, // curl without -L returns the 3xx response itself
};
using var client = new HttpClient(handler);
client.DefaultRequestHeaders.TryAddWithoutValidation("Authorization", "Bearer t");
var response = await client.GetAsync("https://api.example.com/me");
var body = await response.Content.ReadAsStringAsync();

The handler is always emitted with AllowAutoRedirect set explicitly, because HttpClient follows redirects by default and curl does not: false without -L, true (with MaxAutomaticRedirections) with it. Other flags that need handler settings add to it. For curl -u user:pass -k -L -m 10 -x http://proxy:8080 https://api.example.com/me the output is:

var handler = new HttpClientHandler
{
    Credentials = new NetworkCredential("user", "pass"),
    Proxy = new WebProxy("http://proxy:8080"),
    ServerCertificateCustomValidationCallback = HttpClientHandler.DangerousAcceptAnyServerCertificateValidator, // curl -k
    AllowAutoRedirect = true, // curl -L
    MaxAutomaticRedirections = 50, // --max-redirs
};
using var client = new HttpClient(handler);
client.Timeout = TimeSpan.FromSeconds(10);
var response = await client.GetAsync("https://api.example.com/me");
var body = await response.Content.ReadAsStringAsync();

Other languages from the same curl string

using CurlDotNet;

var cmd = "curl -X POST https://api.example.com/users -H 'Content-Type: application/json' -d '{\"name\":\"Ada\"}'";

Console.WriteLine(Curl.ToPythonRequests(cmd));  // Python requests
Console.WriteLine(Curl.ToFetch(cmd));           // JavaScript fetch()
Console.WriteLine(Curl.ToPowershellCode(cmd));  // Invoke-RestMethod

For that command, ToPythonRequests emits requests.post(..., headers=headers, json={"name":"Ada"}) and ToPowershellCode emits a single Invoke-RestMethod -Uri ... -Method POST -Headers @{...} -Body ... -ContentType "application/json" line. See curl to PowerShell code for details.

Treat generated code as a starting point

ToHttpClient and ToPythonRequests translate the URL, method, headers and body, plus -u, -x, -k, -L, -m and -F (multipart). The C# output uses the real HttpClient methods (GetAsync, PostAsync, PutAsync, PatchAsync, …), puts Content-Type on the StringContent, and escapes JSON bodies in a verbatim string. ToFetch and ToPowershellCode cover the URL, method, headers and body only.

Still review generated code before you commit it:

Running the curl string with Curl.ExecuteAsync avoids all of this, because no code is generated.