Table of contents

How do I add authentication headers to HttpClient (C#) requests?

Adding authentication headers to HttpClient requests in C# is essential for securing your API calls. This guide covers the most common authentication methods with practical examples.

Bearer Token Authentication

Bearer tokens are commonly used with OAuth 2.0, JWT tokens, and many modern APIs.

Method 1: Using AuthenticationHeaderValue (Recommended)

using System;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;

public class ApiClient
{
    private readonly HttpClient _httpClient;

    public ApiClient()
    {
        _httpClient = new HttpClient();

        // Set bearer token
        string bearerToken = "your_access_token_here";
        _httpClient.DefaultRequestHeaders.Authorization = 
            new AuthenticationHeaderValue("Bearer", bearerToken);
    }

    public async Task<string> GetDataAsync()
    {
        try
        {
            HttpResponseMessage response = await _httpClient.GetAsync("https://api.example.com/data");
            response.EnsureSuccessStatusCode();
            return await response.Content.ReadAsStringAsync();
        }
        catch (HttpRequestException ex)
        {
            Console.WriteLine($"Request failed: {ex.Message}");
            throw;
        }
    }

    public void Dispose()
    {
        _httpClient?.Dispose();
    }
}

Method 2: Per-Request Authorization

using (var client = new HttpClient())
{
    var request = new HttpRequestMessage(HttpMethod.Get, "https://api.example.com/data");
    request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", "your_token");

    var response = await client.SendAsync(request);

    if (response.IsSuccessStatusCode)
    {
        string content = await response.Content.ReadAsStringAsync();
        Console.WriteLine(content);
    }
}

Basic Authentication

Basic authentication encodes username and password in Base64 format.

using System;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;

public class BasicAuthClient
{
    private readonly HttpClient _httpClient;

    public BasicAuthClient(string username, string password)
    {
        _httpClient = new HttpClient();

        // Create Basic auth header
        string credentials = Convert.ToBase64String(
            Encoding.ASCII.GetBytes($"{username}:{password}"));

        _httpClient.DefaultRequestHeaders.Authorization = 
            new AuthenticationHeaderValue("Basic", credentials);
    }

    public async Task<string> GetProtectedDataAsync()
    {
        var response = await _httpClient.GetAsync("https://api.example.com/protected");
        response.EnsureSuccessStatusCode();
        return await response.Content.ReadAsStringAsync();
    }
}

// Usage
var client = new BasicAuthClient("myusername", "mypassword");
string data = await client.GetProtectedDataAsync();

API Key Authentication

Many APIs use custom headers for API keys.

using System.Net.Http;
using System.Threading.Tasks;

public class ApiKeyClient
{
    private readonly HttpClient _httpClient;

    public ApiKeyClient(string apiKey)
    {
        _httpClient = new HttpClient();

        // Common API key header patterns
        _httpClient.DefaultRequestHeaders.Add("X-API-Key", apiKey);
        // or
        // _httpClient.DefaultRequestHeaders.Add("Authorization", $"ApiKey {apiKey}");
        // or
        // _httpClient.DefaultRequestHeaders.Add("X-Auth-Token", apiKey);
    }

    public async Task<string> FetchDataAsync()
    {
        var response = await _httpClient.GetAsync("https://api.example.com/endpoint");
        response.EnsureSuccessStatusCode();
        return await response.Content.ReadAsStringAsync();
    }
}

JWT Token with Refresh Logic

For more complex scenarios with token refresh:

using System;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;

public class JwtApiClient
{
    private readonly HttpClient _httpClient;
    private string _accessToken;
    private DateTime _tokenExpiry;

    public JwtApiClient()
    {
        _httpClient = new HttpClient();
    }

    private async Task EnsureValidTokenAsync()
    {
        if (string.IsNullOrEmpty(_accessToken) || DateTime.UtcNow >= _tokenExpiry)
        {
            await RefreshTokenAsync();
        }

        _httpClient.DefaultRequestHeaders.Authorization = 
            new AuthenticationHeaderValue("Bearer", _accessToken);
    }

    private async Task RefreshTokenAsync()
    {
        // Implement your token refresh logic here
        var tokenResponse = await GetNewTokenAsync();
        _accessToken = tokenResponse.AccessToken;
        _tokenExpiry = DateTime.UtcNow.AddSeconds(tokenResponse.ExpiresIn - 60); // 60s buffer
    }

    public async Task<string> MakeAuthenticatedRequestAsync(string endpoint)
    {
        await EnsureValidTokenAsync();

        var response = await _httpClient.GetAsync(endpoint);

        // Handle 401 and retry once
        if (response.StatusCode == System.Net.HttpStatusCode.Unauthorized)
        {
            await RefreshTokenAsync();
            await EnsureValidTokenAsync();
            response = await _httpClient.GetAsync(endpoint);
        }

        response.EnsureSuccessStatusCode();
        return await response.Content.ReadAsStringAsync();
    }

    // Placeholder for your token acquisition logic
    private async Task<TokenResponse> GetNewTokenAsync()
    {
        // Implement actual token acquisition
        throw new NotImplementedException();
    }
}

public class TokenResponse
{
    public string AccessToken { get; set; }
    public int ExpiresIn { get; set; }
}

Best Practices

1. HttpClient Lifecycle Management

// Use HttpClientFactory in ASP.NET Core
services.AddHttpClient<ApiClient>();

// Or use a singleton pattern for console apps
public sealed class HttpClientSingleton
{
    private static readonly Lazy<HttpClient> _instance = 
        new Lazy<HttpClient>(() => new HttpClient());

    public static HttpClient Instance => _instance.Value;
}

2. Secure Token Storage

// Never hardcode tokens in source code
string token = Environment.GetEnvironmentVariable("API_TOKEN");
// or use Azure Key Vault, AWS Secrets Manager, etc.

3. Error Handling

public async Task<ApiResponse<T>> SafeApiCallAsync<T>(string endpoint)
{
    try
    {
        var response = await _httpClient.GetAsync(endpoint);

        if (response.IsSuccessStatusCode)
        {
            var content = await response.Content.ReadAsStringAsync();
            var data = JsonSerializer.Deserialize<T>(content);
            return new ApiResponse<T> { Success = true, Data = data };
        }

        return new ApiResponse<T> 
        { 
            Success = false, 
            Error = $"HTTP {response.StatusCode}: {response.ReasonPhrase}" 
        };
    }
    catch (HttpRequestException ex)
    {
        return new ApiResponse<T> { Success = false, Error = ex.Message };
    }
    catch (TaskCanceledException ex)
    {
        return new ApiResponse<T> { Success = false, Error = "Request timeout" };
    }
}

4. Timeout Configuration

_httpClient.Timeout = TimeSpan.FromSeconds(30);

Summary

The key points for adding authentication headers to HttpClient:

  • Bearer tokens: Use AuthenticationHeaderValue("Bearer", token)
  • Basic auth: Base64 encode username:password
  • API keys: Add to custom headers like X-API-Key
  • Reuse HttpClient: Create once, use multiple times
  • Handle errors: Implement proper exception handling
  • Secure storage: Never hardcode credentials

Choose the authentication method that matches your API's requirements and always handle authentication failures gracefully.

Try WebScraping.AI for Your Web Scraping Needs

Looking for a powerful web scraping solution? WebScraping.AI provides an LLM-powered API that combines Chromium JavaScript rendering with rotating proxies for reliable data extraction.

Key Features:

  • AI-powered extraction: Ask questions about web pages or extract structured data fields
  • JavaScript rendering: Full Chromium browser support for dynamic content
  • Rotating proxies: Datacenter and residential proxies from multiple countries
  • Easy integration: Simple REST API with SDKs for Python, Ruby, PHP, and more
  • Reliable & scalable: Built for developers who need consistent results

Getting Started:

Get page content with AI analysis:

curl "https://api.webscraping.ai/ai/question?url=https://example.com&question=What is the main topic?&api_key=YOUR_API_KEY"

Extract structured data:

curl "https://api.webscraping.ai/ai/fields?url=https://example.com&fields[title]=Page title&fields[price]=Product price&api_key=YOUR_API_KEY"

Try in request builder

Related Questions

Get Started Now

WebScraping.AI provides rotating proxies, Chromium rendering and built-in HTML parser for web scraping
Icon