C# – How to get the status code when using HttpClient

When you use HttpClient to make requests, you can directly get the status code from the HttpResponseMessage object, like this:

var response = await httpClient.GetAsync(moviesUrl);

if (response.StatusCode == System.Net.HttpStatusCode.TooManyRequests)
{
	//try again later
}
Code language: C# (cs)

The main reason for checking the status code is to determine if the request was successful and then reacting to error status codes (usually by throwing an exception). The HttpResponseMessage class has two helpers that abstract away these common tasks:

  • IsSuccessStatusCode: Returns true if the status code is between 200-299 (indicating the request was successful).
  • EnsureSuccessStatusCode(): Throws HttpRequestException if the request was not successful.

In this article, I’ll show examples of using these.

Using IsSuccessStatusCode

IsSuccessStatusCode is a property that returns true if the status code is in the successful range (200-299). Here’s an example of how to use it:

var response = await httpClient.GetAsync(moviesUrl);

if (response.IsSuccessStatusCode)
{
	//happy path
}
else
{
	//error path
	//example: retry, check error content, log error, throw exception

	Console.WriteLine($"Request failed. Error status code: {(int)response.StatusCode}");
}
Code language: C# (cs)

When an error status code is returned, IsSuccessStatusCode returns false and this code outputs the following:

Request failed. Error status code: 429Code language: plaintext (plaintext)

Using EnsureSuccessStatusCode() and HttpRequestException

When you send a request with HttpClient and get an error status code (anything outside of the 200-299 range), the EnsureSuccessStatusCode() method throws an exception. It throws an HttpRequestException, which is the same thing HttpClient throws when the request fails for other reasons (such as connection failures). This simplifies error handling, because you only need to catch one type of exception. Note: HttpClient throws a different type of exception for timeouts (TaskCanceledException).

Furthermore, in .NET 5 they added HttpRequestException.StatusCode. This allows you to directly check the error status code in the error handling code.

Here’s an example of using EnsureSuccessStatusCode() and checking HttpRequestException.StatusCode:

try
{
	var response = await httpClient.GetAsync(moviesUrl);
	response.EnsureSuccessStatusCode();

	//happy path
}
catch (HttpRequestException httpEx)
{
	if (httpEx.StatusCode.HasValue)
	{
		//request failed with an error status code
		Console.WriteLine($"Request failed. Error status code: {(int)httpEx.StatusCode}");
	}
	else
	{
		//request failed due to an exception (connection failure, etc...)
		Console.WriteLine(httpEx.Message);

	}
}
Code language: C# (cs)

When an error status code is returned, this outputs the following:

Request failed. Error status code: 429Code language: plaintext (plaintext)

Get the status code from HttpRequestException before .NET 5

Microsoft added the much-needed StatusCode property to HttpRequestException in .NET 5. If you’re using a version before this and can’t upgrade, then you have two options, which I’ll show below.

Option 1 – Use IsSuccessStatusCode and throw a custom exception containing the status code

Use IsSuccessStatusCode instead of EnsureSuccessStatusCode(). This gives you control over the exception that is thrown, therefore allowing you to create your own custom class with a status code property.

First, add a custom exception class with an HttpStatusCode property:

public class HttpErrorStatusCodeException : HttpRequestException
{
	public HttpErrorStatusCodeException(HttpStatusCode errorStatusCode)
	{
		ErrorStatusCode = errorStatusCode;
	}
	public HttpStatusCode ErrorStatusCode { get; set; }
}
Code language: C# (cs)

Note: Subclass HttpRequestException if you want to be able to use a single catch in the error handling code (as shown below).

Now check IsSuccessStatusCode and throw the custom exception with the status code:

var response = await httpClient.GetAsync(moviesUrl);

if (!response.IsSuccessStatusCode)
{
	throw new HttpErrorStatusCodeException(response.StatusCode);
}
Code language: C# (cs)

The error handling code can then get the status code from this custom exception:

try
{
	var movieData = await GetMovieData();
}
catch(HttpRequestException httpEx)
{
	if (httpEx is HttpErrorStatusCodeException httpErrorStatusEx)
	{
		Console.WriteLine($"Request failed with status code: {httpErrorStatusEx.ErrorStatusCode}");
	}
	else
	{
		//request failed due to an exception (connection failure, etc...)
		Console.WriteLine(httpEx.Message);
	}
}
Code language: C# (cs)

Here’s an example of what this outputs:

Request failed with status code: NotFoundCode language: plaintext (plaintext)

Option 2 – Parse the status code out of the exception message

When EnsureSuccessStatusCode() throws an exception, the exception message looks like this:

Response status code does not indicate success: 404 (Not Found).Code language: plaintext (plaintext)

Notice that there’s a pattern to the error message, which means the status code can be parsed out.

This is a last resort type of option. If you must use EnsureSuccessStatusCode(), can’t upgrade to >= .NET 5, and need the error status code, then this is a viable option.

Here’s an example of parsing out the status code of the exception message:

using System.Net;

try
{
	var response = await httpClient.GetAsync(moviesUrl);
	response.EnsureSuccessStatusCode();
}
catch(HttpRequestException httpEx)
{
	//warning: not localized and has no error handling
	var errorStatusCodeStart = "Response status code does not indicate success: ";

	if (httpEx.Message.StartsWith(ErrorStatusCodeStart))
	{
		var statusCodeString = httpEx.Message.Substring(ErrorStatusCodeStart.Length, 3);
		var statusCode = (HttpStatusCode)Enum.Parse(typeof(HttpStatusCode), statusCodeString);

		Console.WriteLine($"Error status code: {(int)statusCode} {statusCode}");
	}
}
Code language: C# (cs)

Disclaimer: This is a proof of concept that shows you a possible way to parse out the status code when you have no other options. This code has no error handling and doesn’t handle localized exception messages.

Here’s an example of what this outputs:

Error status code: 404 NotFoundCode language: plaintext (plaintext)