How to add User-Agent header to HttpClient in .NET
An intrinsic part of the modern web application is the ability to use external APIs and webpages. In .NET this is done using the HttpClient class. The HttpClient class does not add the field User-Agent
out of the box. According to the HTTP standard, it is recommended that this is added to HTTP Requests. This is especially important when doing automated requests like a bot or a web crawler/scraper. In this article, I will show the format for the User-Agent
header and how to add it individually to each request or by default.
The purpose
The purpose of the User-Agent
header is to tell the API/website that you access what you are using to access the site, why you are accessing their site, who you are, and how they can get in contact with you. This can be useful if the owner of the site doesn't want you to access the specific site or if they have suggestions for things that you could do differently when requesting their resources. Some public API's also limit your bandwidth and requests/minute if you do not supply a valid User-Agent
header.
The User-Agent format
The general format for a User-Agent
value is as follows:
(<Product>/<Product version> (<Comments>))*
This means that it contains any number of product-version-comment pairs specifiying the products used to make the request one after each other with increasing specificity. The comments are optional and should be encased in parenthesis. In browsers, this is used to specify things like browser and render engine. When we make a request using HttpClient, we can specify what framework we use to make the request (this is .NET), and we should indicate that this is an automated request. An example of one for a webscraper could be as the following:
.NET/5.0 ScraperBot/1.0 (+http://www.example.com/ScraperBot.html)
We have specified that we use .NET 5.0, that we have made a bot called ScraperBot
which we used for this request and as a comment a link to proceeded by a +
-sign to a page where one can read more about the bot. That we use .NET 5.0 is optional to inform. It is common that "bot"
is a part of the name to indicate that this is an automated request. The site that is linked to should be very simple and contain the name of the bot, the purpose, how they can contact the owner/creator, and when the read-more site has last been updated.
Adding User-Agent header to single HttpRequest
If you wish to add the User-Agent
header to a single HttpRequestMessage
, this can be done like this:
var httpClient = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Get, "https://API.com/api");
var productValue = new ProductInfoHeaderValue("ScraperBot", "1.0");
var commentValue = new ProductInfoHeaderValue("(+http://www.API.com/ScraperBot.html)");
request.Headers.UserAgent.Add(productValue);
request.Headers.UserAgent.Add(commentValue);
var resp = await httpClient.SendAsync(request);
We create a new request. Then we add two fields for the User-Agent
header. One which defines the product and one that defines the comment. The format for the string of the comment is only validated on runtime, so remember to add the parenthesis around the comment.
Adding it as default to HttpClient.
Sometimes you need the same header for many requests during the instance of a single HttpClient
. For this, we can add the User-Agent
header as a default header to the HttpClient
.
var httpClient = new HttpClient();
var productValue = new ProductInfoHeaderValue("ScraperBot", "1.0");
var commentValue = new ProductInfoHeaderValue("(+http://www.example.com/ScraperBot.html)");
httpClient.DefaultRequestHeaders.UserAgent.Add(productValue);
httpClient.DefaultRequestHeaders.UserAgent.Add(commentValue);
var request = new HttpRequestMessage(HttpMethod.Get, "https://API.com/api");
var resp = await httpClient.SendAsync(request);
Adding default headers to HttpClientFactory
A common way to create HttpClient
s in WebAPI and MVC projects for .NET is using a HttpClientFactory
. This can be added to the Service Collection in Startup.cs
and be Dependency Injected in each controller.
First, we add the HttpClientFactory
in Startup.cs
.
public void ConfigureServices(IServiceCollection services)
{
// Other services
services.AddHttpClient("Bot", config =>
{
var productValue = new ProductInfoHeaderValue("ScraperBot", "1.0");
var commentValue = new ProductInfoHeaderValue("(+http://www.example.com/ScraperBot.html)");
config.DefaultRequestHeaders.UserAgent.Add(productValue);
config.DefaultRequestHeaders.UserAgent.Add(commentValue);
});
}
We have added the HttpClientFactory
with a specific configuration for the name "Bot"
. This can be used later to create a HttpClient
with these settings.
Now, we can inject the HttpClientFactory
in a controller.
public class ExampleController : ControllerBase
{
private readonly IHttpClientFactory httpClientFactory;
public ExampleController(IHttpClientFactory httpClientFactory)
{
this.httpClientFactory = httpClientFactory;
}
public async Task<ActionResult> Example()
{
var httpClient = httpClientFactory.CreateClient("Bot");
var request = new HttpRequestMessage(HttpMethod.Get, "https://example.com/api");
var resp = await httpClient.SendAsync(request);
}
}
In the action that we want to use the HttpClient
, we call the CreateClient
method with the name "Bot"
as argument to get our pre-configured HttpClient
.
Conclusion
I have explained what the purpose is for the User-Agent
header. I have shown, the general format of the User-Agent
header. And in the end, I have shown how to add this header to HttpRequests
in .NET. I have shown how to do this in 3 different ways: on the HttpRequestMessage
, on the HttpClient
, and via the HttpClientFactory
dependency injector. If you have any questions regarding this article or feedback then please reach out.