Skip to the content.

How to use curl basic auth in C#

To use curl basic auth in C#, pass -u username:password in the command you give Curl.ExecuteAsync, or call .WithBasicAuth(username, password) on CurlRequestBuilder. CurlDotNet base64-encodes the credentials into an Authorization: Basic header exactly as curl does.

dotnet add package CurlDotNet

The curl command

using CurlDotNet;

var result = await Curl.ExecuteAsync(
    "curl -u user:passwd https://httpbin.org/basic-auth/user/passwd");

Console.WriteLine(result.StatusCode);  // 200

--basic is accepted and is the default for -u. As in curl, -u splits at the first colon, so a password may itself contain colons, and credentials written into the URL (https://user:passwd@host/) are sent as Basic too. -n / --netrc-file reads them from a .netrc file; see config files and variables.

API keys as the user name

Some APIs, Stripe for example, take the API key as the user name with an empty password. The trailing colon works the same as in curl:

using CurlDotNet;

var result = await Curl.ExecuteAsync("curl -u sk_test_123: https://httpbin.org/headers");
Console.WriteLine(result.Body);  // "Authorization": "Basic c2tfdGVzdF8xMjM6"

The fluent builder

using CurlDotNet.Core;

var result = await CurlRequestBuilder
    .Get("https://httpbin.org/basic-auth/user/passwd")
    .WithBasicAuth("user", "passwd")
    .ExecuteAsync();

Console.WriteLine(result.IsSuccess);

Or, with LibCurl, set it once for all requests:

using CurlDotNet.Lib;

using var curl = new LibCurl();
curl.WithBasicAuth("user", "passwd");
var result = await curl.GetAsync("https://httpbin.org/basic-auth/user/passwd");
Console.WriteLine(result.StatusCode);

Digest, NTLM and Negotiate

Challenge-response schemes use the same -u value plus a scheme flag:

using CurlDotNet;

var result = await Curl.ExecuteAsync(
    "curl --digest -u user:passwd https://httpbin.org/digest-auth/auth/user/passwd");

Console.WriteLine(result.StatusCode);  // 200

--ntlm, --negotiate and --anyauth are also accepted. Digest, NTLM (v1 and v2) and --anyauth are negotiated by CurlDotNet itself in pure C#, the way curl does it: the first request goes out without credentials (a POST or PUT as a Content-Length: 0 probe), the server’s challenge picks the scheme (--anyauth prefers Digest, then NTLM, then Basic), and no Basic header is ever sent when a challenge scheme was asked for. They behave the same on every platform. Only --negotiate (Kerberos/SPNEGO) relies on the platform’s own support.

Authorization headers, --oauth2-bearer and URL credentials are not forwarded to a different host when -L follows a redirect, unless you add --location-trusted.

When the credentials are wrong

A 401 does not throw. Check result.StatusCode or call result.EnsureSuccess(), which throws CurlDotNet.Core.CurlHttpException for any non-2xx status. With -f, the 401 throws CurlHttpReturnedErrorException (exit code 22) instead. When Digest or NTLM negotiation itself cannot complete (for example the server offers no scheme you allowed), CurlAuthErrorException (exit code 94) is thrown.

Security notes