CurlDotNet 9.7.0
dotnet add package CurlDotNet --version 9.7.0
NuGet\Install-Package CurlDotNet -Version 9.7.0
<PackageReference Include="CurlDotNet" Version="9.7.0" />
<PackageVersion Include="CurlDotNet" Version="9.7.0" />
<PackageReference Include="CurlDotNet" />
paket add CurlDotNet --version 9.7.0
#r "nuget: CurlDotNet, 9.7.0"
#:package CurlDotNet@9.7.0
#addin nuget:?package=CurlDotNet&version=9.7.0
#tool nuget:?package=CurlDotNet&version=9.7.0
CurlDotNet - curl for C# and .NET
<div align="center"> <img src="https://github.com/jacob-mellor/curl-dot-net/blob/master/src/CurlDotNet/icon128.png?raw=true" alt="CurlDotNet Icon" width="128" height="128"/> </div>
🆕 New to curl? Start Here!
📖 Complete Beginner's Guide to curl in C# →
The Industry Standard curl Experience for C# and .NET Developers
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.
🚀 Quick Start with curl for C# and .NET
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");
📊 Code Coverage
- Line Coverage: 65.9%
- Branch Coverage: 72%
- Method Coverage: 59.9%
- Tests: 657 total, 619 passing, 38 failing
- Last Updated: 2025-11-18
📦 Installation
# .NET CLI
dotnet add package CurlDotNet
# Package Manager Console
Install-Package CurlDotNet
# PackageReference
<PackageReference Include="CurlDotNet" Version="*" />
✨ Why CurlDotNet?
curl Compatibility in .NET
- 100% curl behavior - Your C# code works exactly like curl commands
- Parse any curl command - Copy from documentation and paste into your code
- Industry standard - Used by millions of developers worldwide
Superior to HttpClient
- More features - Proxies, authentication chains, retries, rate limiting
- Better debugging - curl-style verbose output
- Simpler API - One-line operations that would take 20+ lines with HttpClient
Pure .NET Implementation
- No native dependencies - 100% managed C# code
- Universal compatibility - Runs anywhere .NET runs: Windows, Linux, macOS, iOS, Android, IoT devices, Docker, cloud
- Safe and secure - No P/Invoke, no unmanaged memory
🎯 Key Features
HTTP/REST Operations
// 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();
Authentication Methods
// Bearer Token
await Curl.GetAsync("https://api.example.com")
.WithBearerToken("your-token")
.ExecuteAsync();
// Basic Auth
await Curl.GetAsync("https://api.example.com")
.WithBasicAuth("username", "password")
.ExecuteAsync();
// API Key
await Curl.GetAsync("https://api.example.com")
.WithApiKey("X-API-Key", "your-api-key")
.ExecuteAsync();
// OAuth 2.0
await Curl.GetAsync("https://api.example.com")
.WithOAuth2("access-token", "Bearer")
.ExecuteAsync();
// Custom headers
await Curl.GetAsync("https://api.example.com")
.WithHeader("X-Custom-Auth", "token123")
.ExecuteAsync();
AWS Signature V4 Authentication (--aws-sigv4)
// 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");
// API Gateway with request body
var result = await Curl.ExecuteAsync(
@"curl --aws-sigv4 ""aws:amz:eu-central-1:execute-api"" -u ""AKID:SECRET""
--json '{""action"":""invoke""}' https://abc123.execute-api.eu-central-1.amazonaws.com/prod/fn");
// 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");
// Temporary credentials with session token
var result = await Curl.ExecuteAsync(
@"curl --aws-sigv4 ""aws:amz:us-east-1:s3"" -u ""AKID:SECRET""
-H ""x-amz-security-token: SESSION_TOKEN"" https://s3.amazonaws.com/bucket");
File Operations
// Download file with progress
await Curl.DownloadFileAsync(
"https://example.com/large-file.zip",
"local-file.zip",
progress: (percent) => Console.WriteLine($"Progress: {percent:F1}%")
);
// Upload file
await Curl.PostAsync("https://api.example.com/upload")
.WithFile("file", "/path/to/file.pdf")
.ExecuteAsync();
// Multipart form data
await Curl.PostAsync("https://api.example.com/upload")
.WithMultipartForm(form => form
.AddString("name", "John")
.AddFile("document", "/path/to/doc.pdf")
.AddFile("image", "/path/to/image.jpg"))
.ExecuteAsync();
JSON API Requests (--json flag)
// 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");
@file References for Request Data
// -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");
Binary File Downloads
// Download binary files (Office docs, PDFs, ZIPs, etc.) - automatically detected
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");
Proxy Support
// HTTP proxy
await Curl.GetAsync("https://api.example.com")
.WithProxy("http://proxy.example.com:8080")
.WithProxyAuth("username", "password")
.ExecuteAsync();
// SOCKS5 proxy (Tor)
await Curl.GetAsync("https://check.torproject.org")
.WithSocks5Proxy("socks5://127.0.0.1:9050")
.ExecuteAsync();
// Residential proxy
await Curl.GetAsync("https://api.example.com")
.WithProxy("http://gate.smartproxy.com:10000")
.WithProxyAuth("user-country-us", "password")
.ExecuteAsync();
// Rotating proxy
await Curl.GetAsync("https://api.example.com")
.WithProxy("http://proxy.provider.com:8000")
.WithProxyAuth($"user-session-{Guid.NewGuid()}", "password")
.ExecuteAsync();
// Backconnect proxy
await Curl.GetAsync("https://api.example.com")
.WithBackconnectProxy("proxy.provider.com", 20001)
.ExecuteAsync();
Advanced Features
// 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();
📊 Performance & Reliability
- ✅ 244 Unit Tests - 100% pass rate
- ✅ Self-Contained Testing - No external dependencies
- ✅ Cross-Platform CI/CD - Windows, Linux, macOS
- ✅ Production Ready - Used in enterprise applications
🏗️ Platform Support
| 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.8 | ✅ Native (Windows, Mac, Linux via Mono) |
| .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 Linux images | ✅ Full Support |
| Azure | App Service, Functions, Container Instances | ✅ Cloud Native |
| AWS | Lambda, ECS, Fargate | ✅ Cloud Native |
📖 Documentation
- 🆕 Beginner's Guide - New to curl? Start here
- 📚 API Reference - Complete API documentation
- 👨🍳 Cookbook - Ready-to-use recipes
- 📝 Tutorials - Step-by-step guides
- 🔄 Migration Guides - Migration from HttpClient/RestSharp
💡 Use Cases
REST API Integration
// GitHub API example
var repos = await Curl.GetJsonAsync<List<Repository>>(
"https://api.github.com/users/octocat/repos"
);
Web Scraping
// Scrape with proper headers
var html = await Curl.GetAsync("https://example.com")
.WithUserAgent("Mozilla/5.0 (Windows NT 10.0; Win64; x64)")
.WithHeader("Accept-Language", "en-US")
.ExecuteAsync();
Microservices Communication
// Service-to-service with retry
var response = await Curl.PostAsync("http://service-b/api/process")
.WithJson(requestData)
.WithRetry(3)
.WithTimeout(TimeSpan.FromSeconds(5))
.ExecuteAsync();
CI/CD Automation
// Deploy webhook
await Curl.PostAsync("https://deploy.example.com/webhook")
.WithJson(new {
version = "1.2.3",
environment = "production"
})
.WithBearerToken(deployToken)
.ExecuteAsync();
🔧 Advanced Usage
Custom Middleware
// Add custom middleware for logging, caching, etc.
var result = await Curl.GetAsync("https://api.example.com")
.UseMiddleware(async (context, next) => {
Console.WriteLine($"Request: {context.Request.Url}");
var response = await next();
Console.WriteLine($"Response: {response.StatusCode}");
return response;
})
.ExecuteAsync();
Code Generation
// Convert curl to other languages
var pythonCode = Curl.ToPythonRequests("curl -X GET https://api.example.com");
var jsCode = Curl.ToJavaScriptFetch("curl -X POST https://api.example.com -d '{}'");
var httpClientCode = Curl.ToHttpClient("curl https://api.example.com");
Debugging
// Enable verbose output like curl -v
var result = await Curl.GetAsync("https://api.example.com")
.Verbose(true)
.ExecuteAsync();
// Access detailed timing information
Console.WriteLine($"DNS Lookup: {result.Timings.DnsLookup}ms");
Console.WriteLine($"Connect: {result.Timings.Connect}ms");
Console.WriteLine($"TLS Handshake: {result.Timings.TlsHandshake}ms");
Console.WriteLine($"First Byte: {result.Timings.FirstByte}ms");
Console.WriteLine($"Total: {result.Timings.Total}ms");
Detailed Trace Logging (--trace / --trace-ascii / --trace-time)
When you need to know exactly where a request succeeds or gets blocked — especially behind a corporate proxy — write a full diagnostic trace to a log file. The trace captures connection and proxy selection, TLS certificate verification, the exact request/response headers and bodies, transfer timings, and the precise error if the request fails.
// Paste-a-curl-command style: write a full hex+ASCII trace to a file
await Curl.ExecuteAsync("curl --trace curl-trace.log https://api.example.com");
// Compact, ASCII-only trace with timestamps on every line
await Curl.ExecuteAsync("curl --trace-ascii curl-trace.txt --trace-time https://api.example.com");
// Send the trace to standard output instead of a file
await Curl.ExecuteAsync("curl --trace - https://api.example.com");
// Fluent builder equivalent
var result = await CurlRequestBuilder
.Get("https://api.example.com")
.WithTrace("curl-trace.log", includeTimestamps: true)
.ExecuteAsync();
A trace file looks like this:
== Info: CurlDotNet trace started 2026-06-03 14:03:27
== Info: Command: curl --trace curl-trace.log https://api.example.com
== Info: Trying api.example.com:443...
== Info: Using explicit proxy http://proxy.corp.local:8080 (with credentials)
== Info: Connected to api.example.com (api.example.com) port 443
== Info: TLS: certificate verification enabled
=> Send header, 142 bytes (0x8e)
0000: 47 45 54 20 2f 20 48 54 54 50 2f 31 2e 31 0d 0a GET / HTTP/1.1..
...
<= Recv header, 173 bytes (0xad)
0000: 48 54 54 50 2f 31 2e 31 20 32 30 30 20 4f 4b 0d HTTP/1.1 200 OK.
...
== Info: Transfer complete: HTTP 200, 1256 bytes received.
If the request is blocked, the exact failure is recorded so you can see which stage rejected it:
== Error: Connection failed: The proxy tunnel request to proxy 'http://proxy.corp.local:8080' failed with status code '407'.
== Error: caused by: HttpRequestException: Proxy authentication required
Code Generation
CurlDotNet can transpile curl commands into code for other languages. This is perfect for building developer tools or converting documentation examples.
// Convert curl to PowerShell
var powershellCode = Curl.ToPowershellCode("curl -X POST https://api.example.com -d 'data'");
// Convert curl to Python Requests
var pythonCode = Curl.ToPythonCode("curl -X POST https://api.example.com -d 'data'");
// Convert curl to JavaScript Fetch
var jsCode = Curl.ToFetchCode("curl -X POST https://api.example.com -d 'data'");
// Convert curl to C# HttpClient
var csharpCode = Curl.ToHttpClientCode("curl -X POST https://api.example.com -d 'data'");
❓ Troubleshooting
SSL/TLS Issues
If you encounter SSL errors (e.g., self-signed certificates), you can disable verification for development:
// Global setting (affects all requests)
Curl.DefaultInsecure = true;
// Per-request setting
await Curl.Execute("curl -k https://self-signed.local");
Timeouts
If requests are timing out, increase the timeout settings:
// Set global timeout to 60 seconds
Curl.DefaultMaxTimeSeconds = 60;
// Or per request
await Curl.Execute("curl --max-time 60 https://slow-api.example.com");
Proxy Authentication
If your proxy requires authentication:
await Curl.Execute("curl -x http://user:pass@proxy.example.com:8080 https://api.example.com");
Where are my requests being blocked? (proxy / firewall debugging)
If requests work locally but fail behind a proxy or firewall, add --trace to capture a
detailed log of every stage of the transfer. The log shows which proxy was selected,
whether the TLS handshake completed, the request/response headers, and the precise error
if the connection is rejected:
await Curl.ExecuteAsync("curl --trace-ascii proxy-debug.log -x http://proxy.corp.local:8080 https://api.example.com");
// Then open proxy-debug.log and look for the first "== Error:" line.
Note: As of v9.6.0,
-x/--proxy,--proxy-user,--socks5and-k/--insecureare honored for HTTP/HTTPS requests (previously they were only applied to FTP).
🤝 Contributing
We welcome contributions! Please see our Contributing Guide for details.
Development Setup
# Clone the repository
git clone https://github.com/jacob-mellor/curl-dot-net.git
# Build the project
dotnet build
# Run tests
dotnet test
# Run with coverage
dotnet test /p:CollectCoverage=true
📊 Examples
Comprehensive examples are available in the examples directory:
- Basic Examples - Simple GET, POST, error handling
- Authentication - Bearer tokens, OAuth, API keys
- File Operations - Upload, download, progress tracking
- Advanced Scenarios - Proxies, retries, rate limiting
- Real World - GitHub API, web scraping, complete applications
📄 License
CurlDotNet is MIT licensed. See LICENSE for details.
🌟 Why Developers Choose CurlDotNet
"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
🚦 Getting Started
- Install the package:
dotnet add package CurlDotNet - Add using:
using CurlDotNet; - Make your first request:
await Curl.GetAsync("https://api.example.com");
That's it! You're now using the power of curl in C# and .NET.
🆘 Support
- GitHub Issues - Report bugs or request features
- Discussions - Ask questions and share ideas
- Stack Overflow - Community Q&A
📎 Additional Resources
- Repository – https://github.com/jacob-mellor/curl-dot-net
- NuGet – https://www.nuget.org/packages/CurlDotNet
- CI/CD Integration Guide – https://github.com/jacob-mellor/curl-dot-net/blob/master/docs/articles/ci-cd-integration.md
- Logging & Observability Guide – https://github.com/jacob-mellor/curl-dot-net/blob/master/docs/guides/logging-observability.md
- Shell Compatibility Guide – https://jacob-mellor.github.io/curl-dot-net/reference/index.md
📖 Our Story
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
🌐 Part of UserLand.NET
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
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 is compatible. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
| .NET Core | netcoreapp2.0 was computed. netcoreapp2.1 was computed. netcoreapp2.2 was computed. netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
| .NET Standard | netstandard2.0 is compatible. netstandard2.1 was computed. |
| .NET Framework | net461 was computed. net462 was computed. net463 was computed. net47 was computed. net471 was computed. net472 is compatible. net48 is compatible. net481 was computed. |
| MonoAndroid | monoandroid was computed. |
| MonoMac | monomac was computed. |
| MonoTouch | monotouch was computed. |
| Tizen | tizen40 was computed. tizen60 was computed. |
| Xamarin.iOS | xamarinios was computed. |
| Xamarin.Mac | xamarinmac was computed. |
| Xamarin.TVOS | xamarintvos was computed. |
| Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETFramework 4.7.2
- Newtonsoft.Json (>= 13.0.3)
- Ninject (>= 3.3.6)
- Ninject.Extensions.Factory (>= 3.3.3)
- System.CommandLine (>= 2.0.0-beta4.22272.1)
- System.Net.Http (>= 4.3.4)
- System.Text.Json (>= 8.0.5)
-
.NETFramework 4.8
- Newtonsoft.Json (>= 13.0.3)
- Ninject (>= 3.3.6)
- Ninject.Extensions.Factory (>= 3.3.3)
- System.CommandLine (>= 2.0.0-beta4.22272.1)
- System.Net.Http (>= 4.3.4)
- System.Text.Json (>= 8.0.5)
-
.NETStandard 2.0
- Microsoft.CSharp (>= 4.7.0)
- Newtonsoft.Json (>= 13.0.3)
- Ninject (>= 3.3.6)
- Ninject.Extensions.Factory (>= 3.3.3)
- System.CommandLine (>= 2.0.0-beta4.22272.1)
- System.Text.Json (>= 8.0.5)
-
net8.0
- Newtonsoft.Json (>= 13.0.3)
- Ninject (>= 3.3.6)
- Ninject.Extensions.Factory (>= 3.3.3)
- System.CommandLine (>= 2.0.0-beta4.22272.1)
- System.Text.Json (>= 8.0.5)
-
net9.0
- Newtonsoft.Json (>= 13.0.3)
- Ninject (>= 3.3.6)
- Ninject.Extensions.Factory (>= 3.3.3)
- System.CommandLine (>= 2.0.0-beta4.22272.1)
- System.Text.Json (>= 8.0.5)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 9.7.0 | 0 | 9/9/2026 |
| 9.6.0 | 861 | 6/3/2026 |
| 9.5.2 | 971 | 2/19/2026 |
| 9.5.1 | 120 | 2/13/2026 |
| 9.5.0 | 96 | 2/12/2026 |
| 9.4.1 | 99 | 2/12/2026 |
| 9.4.0 | 102 | 2/10/2026 |
| 9.3.3 | 105 | 2/8/2026 |
| 9.2.1 | 912 | 12/1/2025 |
| 9.2.0 | 512 | 12/1/2025 |
| 9.1.0 | 492 | 12/1/2025 |
| 9.0.0 | 505 | 12/1/2025 |
| 3.0.0 | 490 | 12/1/2025 |
| 1.3.5 | 496 | 12/1/2025 |
| 1.2.27 | 465 | 11/18/2025 |
| 1.2.25 | 399 | 11/18/2025 |
| 1.2.23 | 365 | 11/17/2025 |
| 1.2.15 | 314 | 11/17/2025 |
| 1.1.1 | 243 | 11/16/2025 |
| 1.1.0 | 249 | 11/16/2025 |
Version 9.7.0 - Binary content sniffing + digest auth + curl-accurate cookies
FIX: Binary files served under a wrong text Content-Type (e.g. .xlsx sent as text/plain) are no
longer corrupted. Payloads are sniffed for binary signatures (ZIP/Office, PDF, EXE, images,
archives, OLE2) and NUL bytes, matching curl's write-bytes-verbatim behavior. Reported by
Massimo Braga - thank you!
FIX: FTP binary downloads are no longer corrupted (bytes are read raw, text decoding only for listings)
FIX: (#41) -b/--cookie values and manual Cookie headers now always reach the wire, and session
cookies no longer leak between unrelated requests. Like curl, no automatic cookie engine.
Thanks linv2 for the precise diagnosis!
NEW: (#40) --digest, --ntlm, --negotiate, --anyauth and --basic are now supported. -u with a
challenge scheme performs the proper 401 challenge-response flow instead of leaking
credentials as preemptive Basic. Thanks linv2!
NEW: CurlOptions.AuthScheme property + parser support for the five auth-scheme flags
Frameworks: netstandard2.0, net472, net48, net8.0, net9.0, net10.0
Sponsored by IronSoftware
Documentation: https://jacob-mellor.github.io/curl-dot-net/