When making HTTP requests with Reqwest in Rust, customizing the User-Agent string is often necessary for web scraping, API access, or client identification. The User-Agent header tells servers what type of client is making the request.
Method 1: Using the header() Method (Per Request)
The simplest approach is to set the User-Agent header for individual requests:
use reqwest::header::USER_AGENT;
#[tokio::main]
async fn main() -> Result<(), reqwest::Error> {
let client = reqwest::Client::new();
let response = client
.get("https://httpbin.org/get")
.header(USER_AGENT, "MyWebScraper/1.0")
.send()
.await?;
println!("Status: {}", response.status());
println!("Response: {}", response.text().await?);
Ok(())
}
Method 2: Using HeaderMap for Multiple Headers
When you need to set multiple headers including User-Agent:
use reqwest::header::{HeaderMap, USER_AGENT, ACCEPT};
#[tokio::main]
async fn main() -> Result<(), reqwest::Error> {
let client = reqwest::Client::new();
let mut headers = HeaderMap::new();
headers.insert(USER_AGENT, "MyWebScraper/1.0".parse()?);
headers.insert(ACCEPT, "application/json".parse()?);
let response = client
.get("https://api.example.com/data")
.headers(headers)
.send()
.await?;
println!("Response: {}", response.text().await?);
Ok(())
}
Method 3: Setting Default User-Agent for Client
For applications making multiple requests, set a default User-Agent when creating the client:
use reqwest::header::{HeaderMap, USER_AGENT};
#[tokio::main]
async fn main() -> Result<(), reqwest::Error> {
let mut default_headers = HeaderMap::new();
default_headers.insert(
USER_AGENT,
"MyApp/2.0 (https://example.com)".parse()?
);
let client = reqwest::Client::builder()
.default_headers(default_headers)
.build()?;
// All requests will use the default User-Agent
let response1 = client.get("https://httpbin.org/get").send().await?;
let response2 = client.get("https://api.example.com/users").send().await?;
Ok(())
}
Method 4: Browser-like User-Agent
To mimic a real browser for web scraping:
use reqwest::header::USER_AGENT;
#[tokio::main]
async fn main() -> Result<(), reqwest::Error> {
let browser_user_agent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36";
let client = reqwest::Client::new();
let response = client
.get("https://example.com")
.header(USER_AGENT, browser_user_agent)
.send()
.await?;
println!("Response: {}", response.text().await?);
Ok(())
}
Error Handling with Custom User-Agent
Proper error handling when setting headers:
use reqwest::header::{HeaderValue, USER_AGENT, InvalidHeaderValue};
fn create_user_agent(app_name: &str, version: &str) -> Result<HeaderValue, InvalidHeaderValue> {
let user_agent = format!("{}/{}", app_name, version);
HeaderValue::from_str(&user_agent)
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let client = reqwest::Client::new();
let user_agent = create_user_agent("MyApp", "1.0")?;
let response = client
.get("https://httpbin.org/get")
.header(USER_AGENT, user_agent)
.send()
.await?;
println!("Status: {}", response.status());
Ok(())
}
Best Practices
- Be descriptive: Include your application name and version
- Add contact info: Consider adding a URL or email for identification
- Respect robots.txt: Check site policies before scraping
- Don't impersonate: Avoid misleading User-Agent strings
- Rate limiting: Implement delays between requests when scraping
Common User-Agent Patterns
// Application identification
"MyApp/1.0 (contact@example.com)"
// Bot identification
"MyBot/2.1 (+https://example.com/bot-info)"
// Browser simulation (use responsibly)
"Mozilla/5.0 (compatible; MyBot/1.0)"
Remember that many websites use User-Agent strings for content negotiation, bot detection, and access control. Always respect the website's terms of service and robots.txt file when web scraping.