C# – How to read response headers with HttpClient

When you send a request with HttpClient, it returns an HttpResponseMessage. You can read the response headers through the HttpResponseMessage.Headers property:

using System.Linq;

var response = await httpClient.GetAsync("https://localhost:12345/stocks/MSFT");

foreach (var header in response.Headers)
{
	Console.WriteLine($"{header.Key}={header.Value.First()}");
}
Code language: C# (cs)

This outputs the response headers:

Date=Wed, 08 Dec 2021 18:48:54 GMT
Server=Kestrel
Cache-Control=max-age=60
Transfer-Encoding=chunkedCode language: plaintext (plaintext)

Raw response headers are really just key/value(s) pairs. When the response comes in, the headers are loaded into the Headers property (which is of type HttpResponseHeaders). This parses the headers and provides an interface for accessing them as KeyValuePair<string, IEnumerable<string>> objects (and strongly typed properties for common headers). This is very similar to getting values from a dictionary.

The example above showed how to loop through the headers. In this article, I’ll show how to read specific headers – custom headers, common headers (ex: Cache-Control), and content headers (ex: Content-Type).

Reading specific headers

To read a specific header, you can use Headers.TryGetValues():

using System.Linq;

var response = await httpClient.GetAsync("https://localhost:12345/stocks/MSFT");

if (response.Headers.TryGetValues("X-CDN-Cache", out IEnumerable<string> cdnCacheStatusList)) 
{
	var cdnCacheStatus = cdnCacheStatusList.First();

	//do something with the header value
}
else
{
	//the header is missing
}
Code language: C# (cs)

You can also use Headers.Contains() + Headers.GetValues():

var response = await httpClient.GetAsync("https://localhost:12345/stocks/MSFT");

if (response.Headers.Contains("X-CDN-Cache"))
{
	var cdnCacheStatus = response.Headers.GetValues("X-CDN-Cache").First();

	//do something with the header value
}
Code language: C# (cs)

Note: GetValues() will throw an exception if the header doesn’t exist, so I recommend always using that with Contains().

Headers can have multiple values, which is why it always returns IEnumerable<string>. This is why you have to use First() to get the first value (even if it’s the only value).

You can use these approaches to read any header (custom or common).

Reading common response headers

There are many common HTTP response headers (ex: Cache-Control, Server, Retry-After). Some of the common response headers are parsed into strongly typed properties (ex: Headers.CacheControl). If you need to read a common header, check if there’s property for it in Headers and use it.

For example, let’s say you want to read the Cache-Control header. You can use the Headers.CacheControl property to read this.

var response = await httpClient.GetAsync("https://localhost:12345/stocks/MSFT");

var maxAge = response.Headers.CacheControl?.MaxAge;

//use the values
Code language: C# (cs)

If the header is missing, the property will be null. Make sure to handle nulls appropriately to avoid a runtime NullReferenceException.

If there isn’t a convenient property in Headers for the header you’re trying to read, then use TryGetValues() / GetValues() (as shown in the section above).

Reading content headers

You can access the content headers through the HttpResponseMessage.Content.Headers property. For example, let’s say you want to check the Content-Type to determine how to deserialize the content:

var response = await httpClient.GetAsync("https://localhost:12345/stocks/MSFT");

if (response.Content.Headers.ContentType?.MediaType == "application/json")
{
	//deserialize content as JSON
}
Code language: C# (cs)

Content.Headers is of type HttpContentHeaders. Just like the response headers class, it has many strongly typed properties for common headers (such as Content-Type).

In the scenario where you need to read custom content headers, you can use Content.Headers.TryGetValues(). This should be rare. However, if you need to do this, you can follow the same approach as shown in the Reading specific headers section. It’s the same approach for content headers and response headers because both classes subclass HttpHeaders.