Table of contents

How do I configure timeouts for HttpClient (C#) requests?

Configuring timeouts for HttpClient requests in C# is essential to prevent applications from hanging when servers don't respond or are slow. This guide covers multiple approaches to handle different timeout scenarios.

Basic HttpClient Timeout Configuration

The simplest way to configure timeouts is using the HttpClient.Timeout property:

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

class Program
{
    static async Task Main()
    {
        using var httpClient = new HttpClient()
        {
            Timeout = TimeSpan.FromSeconds(30) // Set 30-second timeout
        };

        try
        {
            var response = await httpClient.GetAsync("https://api.example.com/data");

            if (response.IsSuccessStatusCode)
            {
                var content = await response.Content.ReadAsStringAsync();
                Console.WriteLine($"Response: {content}");
            }
            else
            {
                Console.WriteLine($"HTTP Error: {response.StatusCode}");
            }
        }
        catch (TaskCanceledException ex) when (ex.InnerException is TimeoutException)
        {
            Console.WriteLine("Request timed out.");
        }
        catch (TaskCanceledException ex)
        {
            Console.WriteLine("Request was canceled.");
        }
        catch (HttpRequestException ex)
        {
            Console.WriteLine($"HTTP request failed: {ex.Message}");
        }
    }
}

Per-Request Timeout with CancellationToken

For more granular control, use CancellationToken with individual requests:

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

public class HttpService
{
    private readonly HttpClient _httpClient;

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

    public async Task<string> GetWithTimeoutAsync(string url, int timeoutSeconds)
    {
        using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(timeoutSeconds));

        try
        {
            var response = await _httpClient.GetAsync(url, cts.Token);
            response.EnsureSuccessStatusCode();
            return await response.Content.ReadAsStringAsync();
        }
        catch (OperationCanceledException) when (cts.Token.IsCancellationRequested)
        {
            throw new TimeoutException($"Request to {url} timed out after {timeoutSeconds} seconds");
        }
    }

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

Advanced Timeout Configuration with HttpClientHandler

For separate connection and read timeouts, configure HttpClientHandler:

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

public class AdvancedHttpClient
{
    public static HttpClient CreateWithCustomTimeouts()
    {
        var handler = new HttpClientHandler()
        {
            // Connection timeout is handled differently in .NET 5+
            ServerCertificateCustomValidationCallback = (sender, cert, chain, sslPolicyErrors) => true
        };

        var client = new HttpClient(handler)
        {
            Timeout = TimeSpan.FromMinutes(5) // Overall request timeout
        };

        // Set default headers
        client.DefaultRequestHeaders.Add("User-Agent", "MyApp/1.0");

        return client;
    }
}

// Usage example
class Program
{
    static async Task Main()
    {
        using var httpClient = AdvancedHttpClient.CreateWithCustomTimeouts();

        try
        {
            // This request will timeout after 5 minutes total
            var response = await httpClient.GetAsync("https://slow-api.example.com/data");
            var content = await response.Content.ReadAsStringAsync();
            Console.WriteLine(content);
        }
        catch (TaskCanceledException)
        {
            Console.WriteLine("Request exceeded timeout limit");
        }
    }
}

Multiple Requests with Different Timeouts

When you need different timeout values for various operations:

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

public class ApiClient
{
    private readonly HttpClient _httpClient;

    public ApiClient()
    {
        _httpClient = new HttpClient()
        {
            BaseAddress = new Uri("https://api.example.com/"),
            Timeout = Timeout.InfiniteTimeSpan // Disable global timeout
        };
    }

    public async Task<string> GetQuickDataAsync()
    {
        // Short timeout for quick operations
        using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(5));
        var response = await _httpClient.GetAsync("quick-data", cts.Token);
        return await response.Content.ReadAsStringAsync();
    }

    public async Task<string> GetLargeDataAsync()
    {
        // Longer timeout for large data transfers
        using var cts = new CancellationTokenSource(TimeSpan.FromMinutes(10));
        var response = await _httpClient.GetAsync("large-data", cts.Token);
        return await response.Content.ReadAsStringAsync();
    }

    public async Task<string> PostDataAsync(string jsonData)
    {
        using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(30));
        var content = new StringContent(jsonData, System.Text.Encoding.UTF8, "application/json");
        var response = await _httpClient.PostAsync("data", content, cts.Token);
        return await response.Content.ReadAsStringAsync();
    }
}

Important Timeout Considerations

Default Values

  • Default HttpClient.Timeout: 100 seconds
  • Infinite timeout: TimeSpan.FromMilliseconds(Timeout.Infinite) or Timeout.InfiniteTimeSpan

Scope of Timeouts

The HttpClient.Timeout property applies to the entire HTTP operation: - DNS resolution - TCP connection establishment - SSL handshake (if HTTPS) - Sending request headers and body - Receiving response headers and body

Exception Handling

try
{
    var response = await httpClient.GetAsync(url);
}
catch (TaskCanceledException ex) when (ex.InnerException is TimeoutException)
{
    // Timeout occurred
}
catch (TaskCanceledException ex) when (ex.CancellationToken.IsCancellationRequested)
{
    // Request was explicitly canceled
}
catch (TaskCanceledException)
{
    // Could be timeout or cancellation - check the context
}

Best Practices

  1. Reuse HttpClient instances - Create once and reuse throughout application lifecycle
  2. Use dependency injection - Register HttpClient as a singleton or use IHttpClientFactory
  3. Set appropriate timeouts - Balance between user experience and server capabilities
  4. Handle timeouts gracefully - Provide meaningful error messages to users
  5. Consider retry policies - Implement exponential backoff for transient failures

HttpClientFactory Example

// In Startup.cs or Program.cs
services.AddHttpClient("api", client =>
{
    client.BaseAddress = new Uri("https://api.example.com/");
    client.Timeout = TimeSpan.FromSeconds(30);
    client.DefaultRequestHeaders.Add("Accept", "application/json");
});

// In your service
public class MyService
{
    private readonly HttpClient _httpClient;

    public MyService(IHttpClientFactory httpClientFactory)
    {
        _httpClient = httpClientFactory.CreateClient("api");
    }
}

Proper timeout configuration ensures your application remains responsive and provides a better user experience when dealing with slow or unresponsive web services.

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