π THE KILLER FEATURE: Copy and paste any curl command - it just works! CurlDotNet brings the power of curl to .NET. Simply paste any curl command string and execute it directly. No translation needed, no shell execution, pure .NET. β¨ Key Features: β’ Paste ANY curl command - works with or without "curl" prefix β’ All 300+ curl options supported β’ Stream-based for memory efficiency β’ Perfect for CI/CD pipelines β’ Every curl error code has its own exception type β’ Middleware and DI support π¦ Supported Platforms: β’ .NET 10.0 (future-ready, opt-in support!) β’ .NET 9.0 (latest & greatest!) β’ .NET 8.0 (current LTS) β’ .NET Framework 4.8 (Windows, Mac, Linux via Mono) β’ .NET Framework 4.7.2+ (Windows) β’ .NET Standard 2.0 (maximum compatibility) β’ Xamarin, Unity, Blazor, MAUI π Proudly sponsored by IronSoftware (ironsoftware.com), creators of IronPDF, IronOCR, IronXL, and IronBarcode.
$ dotnet add package CurlDotNetThe Industry Standard curl Experience for C# and .NET
π Complete Beginner's Guide to curl in C# β
CurlDotNet brings the power and simplicity of curl to the .NET ecosystem. Execute curl commands directly in C#, make HTTP requests with curl's battle-tested reliability, and leverage decades of curl development - all with pure .NET code.
using CurlDotNet;
// Execute curl commands directly in C#
var result = await Curl.ExecuteAsync("curl -X GET https://api.github.com/users/octocat -H 'Accept: application/json'");
// Or use the fluent API for type safety
var response = await Curl.GetAsync("https://api.github.com/users/octocat")
.WithHeader("Accept", "application/vnd.github.v3+json")
.ExecuteAsync();
// Simple one-liners for common operations
var json = await Curl.GetJsonAsync<GitHubUser>("https://api.github.com/users/octocat");
# .NET CLI
dotnet add package CurlDotNet
# Package Manager Console
Install-Package CurlDotNet
# PackageReference
<PackageReference Include="CurlDotNet" Version="*" />
// GET request
var data = await Curl.GetAsync("https://api.example.com/users");
// POST JSON
var user = await Curl.PostJsonAsync("https://api.example.com/users",
new { name = "Alice", email = "alice@example.com" });
// PUT with authentication
await Curl.PutAsync("https://api.example.com/users/123")
.WithBearerToken(token)
.WithJson(updatedData)
.ExecuteAsync();
// DELETE
await Curl.DeleteAsync("https://api.example.com/users/123");
// PATCH
await Curl.PatchAsync("https://api.example.com/users/123")
.WithJson(new { status = "active" })
.ExecuteAsync();
// Bearer Token
await Curl.GetAsync("https://api.example.com")
.WithBearerToken(token)
.ExecuteAsync();
// Basic Auth
await Curl.GetAsync("https://api.example.com")
.WithBasicAuth("username", "password")
.ExecuteAsync();
// API Key
await Curl.GetAsync("https://api.example.com")
.WithHeader("X-API-Key", apiKey)
.ExecuteAsync();
// OAuth 2.0
await Curl.GetAsync("https://api.example.com")
.WithOAuth2(clientId, clientSecret, tokenEndpoint)
.ExecuteAsync();
// Sign requests with AWS SigV4 - works with AWS, GCP, and custom providers
var result = await Curl.ExecuteAsync(
@"curl --aws-sigv4 ""aws:amz:us-east-1:s3"" -u ""AKID:SECRET"" https://s3.us-east-1.amazonaws.com/my-bucket");
// Google Cloud Platform
var result = await Curl.ExecuteAsync(
@"curl --aws-sigv4 ""gcp:goog:us-central1:storage"" -u ""KEY:SECRET""
https://storage.googleapis.com/my-bucket/my-object");
// Custom provider (any SigV4-compatible service)
var result = await Curl.ExecuteAsync(
@"curl --aws-sigv4 ""middleearth:gondor:shire:hobbiton"" -u ""frodo:ring""
https://api.middleearth.example.com/quest");
// Download with progress
await Curl.DownloadFileAsync("https://example.com/file.zip", "local.zip",
progress: (percent) => Console.WriteLine($"{percent}% complete"));
// Upload file
await Curl.UploadFileAsync("https://api.example.com/upload", "document.pdf");
// Multipart form upload
await Curl.PostAsync("https://api.example.com/upload")
.WithFile("document", "report.pdf")
.WithFormField("description", "Annual report")
.ExecuteAsync();
// Use curl's --json flag - automatically sets Content-Type and Accept headers
var result = await Curl.ExecuteAsync(
"curl --json '{\"query\":\"search term\"}' https://api.example.com/search");
// Read JSON body from a file (just like curl) - @file reads file contents at execution time
var result = await Curl.ExecuteAsync(
@"curl --json @""c:\data\query.json"" https://api.example.com/search");
// Combine with other curl flags - proxies, auth, output, etc.
var result = await Curl.ExecuteAsync(@"curl -X POST
-H ""Authorization: Bearer token""
--json @query.json
-L -k -o result.json
https://graph.microsoft.com/beta/security/runHuntingQuery");
// -d @file reads file contents and sends as request body (like curl)
var result = await Curl.ExecuteAsync(@"curl -d @data.json https://api.example.com");
// --data-binary @file also reads file contents
var result = await Curl.ExecuteAsync(@"curl --data-binary @payload.bin https://api.example.com");
// --data-raw @file sends the literal string "@file" (no file reading - matches curl behavior)
var result = await Curl.ExecuteAsync(@"curl --data-raw @not-a-file https://api.example.com");
// Office docs, PDFs, ZIPs, etc. are automatically detected as binary
var result = await Curl.ExecuteAsync("curl -o report.xlsx https://example.com/report.xlsx");
// Force binary mode for servers with incorrect Content-Type headers
var report = await CurlRequestBuilder.Get("https://example.com/report.xlsx")
.AsBinary()
.WithOutput("report.xlsx")
.ExecuteAsync();
// Register custom MIME types as binary
var data = await CurlRequestBuilder.Get("https://example.com/data")
.WithBinaryContentType("application/x-custom-format")
.ExecuteAsync();
data.SaveToFile("output.bin");
CurlDotNet provides comprehensive proxy support for various scenarios:
// HTTP Proxy
await Curl.GetAsync("https://api.example.com")
.WithProxy("http://proxy.company.com:8080")
.ExecuteAsync();
// HTTPS Proxy with authentication
await Curl.GetAsync("https://api.example.com")
.WithProxy("https://proxy.company.com:443")
.WithProxyAuth("username", "password")
.ExecuteAsync();
// SOCKS5 Proxy (Tor, residential proxies)
await Curl.GetAsync("https://api.example.com")
.WithSocks5Proxy("socks5://localhost:9050")
.ExecuteAsync();
// Rotating/Backconnect Proxy
await Curl.GetAsync("https://api.example.com")
.WithProxy("http://gate.proxy.com:8000")
.WithProxyAuth("user-session-random123", "password")
.ExecuteAsync();
// Proxy with custom headers (for residential/datacenter proxies)
await Curl.GetAsync("https://api.example.com")
.WithProxy("http://proxy.provider.com:8080")
.WithProxyHeader("X-Session-ID", "sticky-session-123")
.ExecuteAsync();
// No proxy for specific domains
await Curl.GetAsync("https://internal.company.com")
.WithNoProxy("*.company.com,192.168.*")
.ExecuteAsync();
Why Use Proxies?
Proxy Types Supported:
// Retry with exponential backoff
await Curl.GetAsync("https://api.example.com")
.WithRetry(maxAttempts: 3)
.WithExponentialBackoff()
.ExecuteAsync();
// Rate limiting
await Curl.GetAsync("https://api.example.com")
.WithRateLimit(requestsPerMinute: 60)
.ExecuteAsync();
// Timeout handling
await Curl.GetAsync("https://api.example.com")
.WithTimeout(TimeSpan.FromSeconds(30))
.WithConnectTimeout(TimeSpan.FromSeconds(10))
.ExecuteAsync();
// Follow redirects
await Curl.GetAsync("https://bit.ly/shortened")
.FollowRedirects(maxRedirects: 5)
.ExecuteAsync();
// Cookie management
var cookieJar = new CookieContainer();
await Curl.GetAsync("https://example.com")
.WithCookieContainer(cookieJar)
.ExecuteAsync();
| Platform | Version | Support |
|---|---|---|
| .NET | 10, 9, 8, 7, 6, 5 | β Full Support |
| .NET Core | 3.1, 3.0, 2.1 | β Full Support |
| .NET Framework | 4.7.2+ | β via .NET Standard 2.0 |
| .NET Standard | 2.0+ | β Maximum Compatibility |
| Windows | 10, 11, Server 2016+ | β Native |
| Linux | Ubuntu, Debian, RHEL, Alpine | β Native |
| macOS | 10.14+, Apple Silicon | β Native |
| iOS | 12+ | β via .NET Standard/MAUI |
| Android | API 21+ | β via .NET Standard/MAUI |
| IoT | Raspberry Pi, Arduino | β via .NET IoT |
| Docker | All .NET images | β Optimized |
| Azure | Functions, App Service, IoT Hub | β Cloud Ready |
| AWS | Lambda, ECS, IoT Core | β Cloud Ready |
CurlDotNet treats Ubuntu/Linux syntax as the canonical source of truth when parsing curl strings, and then normalizes Windows CMD, PowerShell, and macOS variations. Highlights:
\ continuations).%VAR% or $env:VAR environment variablesβwe expand them transparently.When in doubt, author the command in an Ubuntu shell (or WSL), then copy it into your C# sourceβCurlDotNet will behave exactly like curl.
dotnet test (net8.0): 255 tests passed β parser, CurlResult, builder, middleware, and integration coverage.dotnet script scripts/generate-docs.csx so NuGet + GitHub Pages share the same <example> snippets../scripts/test-framework-compatibility.sh validates .NET Standard 2.0 & .NET 8 builds.Perfect for consuming REST APIs with minimal code:
var api = new Curl("https://api.example.com")
.WithBearerToken(Environment.GetEnvironmentVariable("API_TOKEN"));
var users = await api.GetJsonAsync<List<User>>("/users");
var newUser = await api.PostJsonAsync<User>("/users", new { name = "Bob" });
Handle complex scraping scenarios with ease:
var html = await Curl.GetAsync("https://example.com")
.WithUserAgent("Mozilla/5.0...")
.WithProxy("http://proxy.com:8080")
.GetBodyAsync();
Resilient service-to-service calls:
var response = await Curl.GetAsync("http://service-b/api/data")
.WithRetry(3)
.WithCircuitBreaker()
.WithTimeout(TimeSpan.FromSeconds(5))
.ExecuteAsync();
Execute curl commands from scripts:
var result = await Curl.ExecuteAsync(Environment.GetEnvironmentVariable("CURL_COMMAND"));
// Before: HttpClient
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", $"Bearer {token}");
var response = await client.GetAsync("https://api.example.com");
var content = await response.Content.ReadAsStringAsync();
// After: CurlDotNet
var content = await Curl.GetAsync("https://api.example.com")
.WithBearerToken(token)
.GetBodyAsync();
// Before: RestSharp
var client = new RestClient("https://api.example.com");
var request = new RestRequest("/users", Method.Get);
request.AddHeader("Authorization", $"Bearer {token}");
var response = await client.ExecuteAsync(request);
// After: CurlDotNet
var response = await Curl.GetAsync("https://api.example.com/users")
.WithBearerToken(token)
.ExecuteAsync();
We welcome contributions! See CONTRIBUTING.md for guidelines.
CurlDotNet is MIT licensed. See LICENSE for details.
"Finally, I can just paste curl commands from API docs!" - Senior Developer
"The proxy support is fantastic for our web scraping needs." - Data Engineer
"Migrating from HttpClient saved us hundreds of lines of code." - Tech Lead
"The retry logic and rate limiting just work." - DevOps Engineer
dotnet add package CurlDotNetusing CurlDotNet;await Curl.GetAsync("https://api.example.com");That's it! You're now using the power of curl in C# and .NET.
Read about how CurlDotNet is bringing curl superpowers to every corner of the .NET 10 & C# stack: π° Featured Article: CurlDotNet - Bringing curl Superpowers to Every Corner of the .NET 10 & C# Stack
CurlDotNet is part of the UserLand.NET initiative - bringing Unix/Linux tools to .NET through pure C# implementations.
Keywords: curl C#, curl .NET, C# HTTP client, .NET curl, REST API C#, HTTP requests .NET, web scraping C#, proxy C#, curl for Windows, curl alternative, HttpClient alternative
Author: Jacob Mellor | Sponsored by IronSoftware.com
Built with β€οΈ for the .NET community by CurlDotNet Contributors