HTTP headers
asynchronous request
WebClient
programming
web development

Get HTTP headers in asynchronous WebClient request

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

With WebClient, request headers are set before the async call starts, and response headers become available after the request completes. That makes the main pattern straightforward: configure Headers, await the asynchronous operation, then read ResponseHeaders. The bigger caveat is that WebClient is legacy API surface, so this is mainly a maintenance topic rather than the preferred design for new .NET code.

Set Request Headers Before Starting the Call

WebClient exposes a Headers collection for outgoing headers.

csharp
1using System;
2using System.Net;
3using System.Threading.Tasks;
4
5public static async Task RunAsync()
6{
7    using var client = new WebClient();
8    client.Headers[HttpRequestHeader.Accept] = "application/json";
9    client.Headers[HttpRequestHeader.UserAgent] = "LegacyClient/1.0";
10
11    string body = await client.DownloadStringTaskAsync("https://example.com");
12    Console.WriteLine(body.Length);
13}

Those headers are part of the outgoing request. They must be set before calling DownloadStringTaskAsync, OpenReadTaskAsync, or another async method.

Read Response Headers After the Await

Once the asynchronous request completes, ResponseHeaders is populated with the server's returned headers.

csharp
1using System;
2using System.Net;
3using System.Threading.Tasks;
4
5public static async Task RunAsync()
6{
7    using var client = new WebClient();
8    string body = await client.DownloadStringTaskAsync("https://example.com");
9
10    WebHeaderCollection headers = client.ResponseHeaders;
11    Console.WriteLine(headers[HttpResponseHeader.ContentType]);
12    Console.WriteLine(headers["Server"]);
13}

The important timing rule is simple: do not expect ResponseHeaders to contain the final response until the request has actually finished.

Handle Errors Without Losing Header Context

If the request fails with a WebException, you may still be able to inspect the response headers from the exception response.

csharp
1using System;
2using System.IO;
3using System.Net;
4using System.Threading.Tasks;
5
6public static async Task RunAsync()
7{
8    using var client = new WebClient();
9
10    try
11    {
12        await client.DownloadStringTaskAsync("https://example.com/missing");
13    }
14    catch (WebException ex) when (ex.Response is HttpWebResponse response)
15    {
16        Console.WriteLine((int)response.StatusCode);
17        Console.WriteLine(response.Headers[HttpResponseHeader.ContentType]);
18
19        using var reader = new StreamReader(response.GetResponseStream());
20        Console.WriteLine(await reader.ReadToEndAsync());
21    }
22}

This matters because real HTTP work often requires both the error status and the headers that came back with it.

Understand the Limits of WebClient

WebClient is convenient for simple tasks, but it has limits:

  • limited control compared with HttpClient
  • awkward timeout customization
  • no first-class cancellation tokens in the modern style
  • legacy event and task patterns mixed together

If your only requirement is to read response headers in an existing codebase, WebClient can still do the job. If you are designing new networking code, HttpClient is usually the better tool.

A Modern Equivalent With HttpClient

For comparison, this is how the same idea looks with HttpClient.

csharp
1using System;
2using System.Net.Http;
3using System.Threading.Tasks;
4
5public static async Task RunAsync()
6{
7    using var client = new HttpClient();
8    client.DefaultRequestHeaders.Add("User-Agent", "ModernClient/1.0");
9
10    using var response = await client.GetAsync("https://example.com");
11    Console.WriteLine(response.Headers.Server);
12    Console.WriteLine(response.Content.Headers.ContentType);
13}

This is not required to answer the original WebClient question, but it explains why most new code has moved away from WebClient.

Common Pitfalls

The most common mistake is reading ResponseHeaders before the async operation has completed.

Another mistake is confusing request headers with response headers. client.Headers configures what you send, while client.ResponseHeaders exposes what you received.

A third issue is forgetting that failed requests may still return useful response metadata through the exception response.

Finally, do not keep extending WebClient for modern HTTP needs if HttpClient would solve the problem more cleanly.

Summary

  • Set outgoing headers on WebClient.Headers before starting the async request.
  • Read incoming headers from WebClient.ResponseHeaders after the request completes.
  • On errors, inspect WebException.Response to recover status and headers.
  • 'WebClient can handle simple header access, but it is legacy API surface.'
  • 'HttpClient is usually the better choice for new code.'
  • The key timing rule is that response headers are only reliable after the async operation has finished.

Course illustration
Course illustration

All Rights Reserved.