The Complete Guide to User-Agent: History, Structure, Detection, and Best Practices
A comprehensive deep-dive into HTTP User-Agent strings — covering their history, anatomy, browser detection techniques, bot identification, Client Hints (UA-CH), and best practices for modern web development.
Every time you open a browser and visit a website, the server often knows your browser type, operating system, and device category before it even responds — all thanks to a single string called the User-Agent. It acts as an invisible “ID card” that travels silently with every HTTP request you make.
Want to instantly see what your browser’s User-Agent looks like? Use our User-Agent Analyzer to parse every field in one click.
1. What Is a User-Agent?
A User-Agent (UA) is a standard HTTP request header field that clients (typically browsers) automatically attach when sending HTTP requests, identifying themselves to the server.
1.1 Where UA Lives in an HTTP Request
Every HTTP request contains headers, and User-Agent is one of the core standard fields:
GET /index.html HTTP/1.1
Host: example.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.9
1.2 Formal Definition
According to RFC 7231 (HTTP/1.1 Semantics and Content), the User-Agent field follows this format:
User-Agent = product *( RWS ( product / comment ) )
product = token ["/" product-version]
In plain words: one or more “product/version” identifiers, with optional comments in parentheses.
2. A Brief History of User-Agent Strings
The history of UA strings is a fascinating story of compatibility wars. Understanding it explains why modern UA strings look the way they do.
2.1 Origins: Mosaic and Netscape (1990s)
NCSA Mosaic, one of the earliest web browsers, used a simple UA string:
NCSA_Mosaic/2.0 (Windows 3.1)
In 1993, Netscape Navigator introduced the Mozilla identifier (short for “Mosaic Killer”):
Mozilla/1.0 (Win3.1)
Early websites were configured to check for Mozilla in the UA and only serve rich HTML content (like frames) when it was present.
2.2 The Price of Compatibility: IE Pretends (1995)
When Microsoft launched Internet Explorer, it wanted to receive the “full” content that servers gave to Netscape. So IE added a Mozilla compatibility tag to its UA:
Mozilla/2.0 (compatible; MSIE 3.0; Windows 95)
This practice of “pretending to be Mozilla” has persisted ever since.
2.3 The Rendering Engine Era (2000s)
As rendering engines like Gecko (Firefox), WebKit (Safari), and Blink (Chrome) emerged, UA strings grew longer. Each new browser added compatibility claims to avoid being treated as second-class:
- Firefox: Claimed compatibility with Mozilla and Gecko
- Safari: Claimed compatibility with Mozilla and AppleWebKit
- Chrome: Claimed compatibility with Mozilla, AppleWebKit, and even Safari (!)
This is why you see Mozilla, AppleWebKit, Chrome, and Safari all in a single Chrome UA string.
2.4 Evolution Summary
| Era | Representative Browsers | UA Characteristics |
|---|---|---|
| 1993–1995 | Mosaic, Netscape 1.x | Short, direct self-identification |
| 1995–2000 | IE 3–5 | Added Mozilla compatibility tag |
| 2001–2008 | Firefox, Safari | Added rendering engine identifiers |
| 2008–Present | Chrome, Edge | Stacked multiple compatibility claims |
3. Anatomy of a Modern User-Agent String
Let’s dissect a Chrome UA string on Windows step by step:
Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36
3.1 Field-by-Field Breakdown
| Field | Value | Meaning |
|---|---|---|
Mozilla/5.0 | Mozilla/5.0 | Legacy compatibility token present in virtually all modern browsers |
(Windows NT 10.0; Win64; x64) | OS comment | Windows 10, 64-bit OS, 64-bit processor |
AppleWebKit/537.36 | Rendering engine | WebKit/Blink engine version |
(KHTML, like Gecko) | Engine comment | KHTML-compatible, Gecko-like behavior |
Chrome/124.0.0.0 | Browser identifier | Chrome browser, version 124 |
Safari/537.36 | Safari compat tag | Legacy field; Chrome is based on WebKit, which is Safari-compatible |
3.2 Windows NT Version Reference
| NT Version | Windows OS |
|---|---|
| Windows NT 5.1 | Windows XP |
| Windows NT 6.0 | Windows Vista |
| Windows NT 6.1 | Windows 7 |
| Windows NT 6.2 | Windows 8 |
| Windows NT 6.3 | Windows 8.1 |
| Windows NT 10.0 | Windows 10 / 11 |
3.3 Mobile UA Differences
Android Chrome:
Mozilla/5.0 (Linux; Android 14; Pixel 8) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.6367.82 Mobile Safari/537.36
iOS Safari:
Mozilla/5.0 (iPhone; CPU iPhone OS 17_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.4.1 Mobile/15E148 Safari/604.1
Mobile UA strings add:
- Device model: e.g.,
Pixel 8,iPhone - OS version: e.g.,
Android 14,iPhone OS 17_4 Mobileflag: Used to distinguish mobile from desktop
4. Common User-Agent Quick Reference
4.1 Desktop Browsers
| Browser | Typical User-Agent |
|---|---|
| Chrome 124 (Windows) | Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36 |
| Firefox 125 (Windows) | Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:125.0) Gecko/20100101 Firefox/125.0 |
| Safari 17 (macOS) | Mozilla/5.0 (Macintosh; Intel Mac OS X 14_4) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.4 Safari/605.1.15 |
| Edge 124 (Windows) | Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36 Edg/124.0.0.0 |
| Opera 109 (Windows) | Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36 OPR/109.0.0.0 |
4.2 Mobile Browsers
| Browser | Typical User-Agent |
|---|---|
| Chrome (Android) | Mozilla/5.0 (Linux; Android 14; Pixel 8) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.6367.82 Mobile Safari/537.36 |
| Safari (iPhone) | Mozilla/5.0 (iPhone; CPU iPhone OS 17_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.4.1 Mobile/15E148 Safari/604.1 |
| Samsung Internet | Mozilla/5.0 (Linux; Android 14; SM-S928B) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/25.0 Chrome/121.0.0.0 Mobile Safari/537.36 |
4.3 Crawlers and Bots
| Crawler | User-Agent |
|---|---|
| Googlebot | Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html) |
| Bingbot | Mozilla/5.0 (compatible; bingbot/2.0; +http://www.bing.com/bingbot.htm) |
| Baiduspider | Mozilla/5.0 (compatible; Baiduspider/2.0; +http://www.baidu.com/search/spider.html) |
| Python requests | python-requests/2.31.0 |
| cURL | curl/8.6.0 |
5. Use Cases for User-Agent
5.1 Adaptive Content Delivery
Servers can use the UA to differentiate between desktop and mobile visitors and serve different page versions:
// Node.js example
function detectDevice(userAgent) {
const mobileKeywords = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i;
return mobileKeywords.test(userAgent) ? 'mobile' : 'desktop';
}
app.get('/', (req, res) => {
const device = detectDevice(req.headers['user-agent']);
if (device === 'mobile') {
res.redirect('/mobile');
} else {
res.sendFile('desktop/index.html');
}
});
5.2 Browser Compatibility Handling
Frontend code can detect browser type via UA and selectively load polyfills or apply fallbacks:
const ua = navigator.userAgent;
const isFirefox = ua.includes('Firefox');
const isChrome = ua.includes('Chrome') && !ua.includes('Edg');
const isEdge = ua.includes('Edg/');
const isSafari = ua.includes('Safari') && !ua.includes('Chrome');
// Apply Safari-specific workarounds
if (isSafari) {
document.documentElement.classList.add('safari-mode');
}
⚠️ Note: Chrome’s UA includes the
Safaristring, so always exclude Chrome when detecting Safari.
5.3 Bot Detection and Anti-Scraping
Website administrators can filter bots based on their UA strings:
# Python Flask example
from flask import request, abort
ALLOWED_BOTS = ['Googlebot', 'Bingbot', 'Baiduspider']
@app.before_request
def check_user_agent():
ua = request.headers.get('User-Agent', '')
# Block suspicious empty or very short UA strings
if len(ua) < 10:
abort(403)
# Allow known legitimate crawlers
is_known_bot = any(bot in ua for bot in ALLOWED_BOTS)
5.4 Web Analytics
UA data is a primary data source for analytics tools like Google Analytics, enabling statistics on:
- Browser distribution among users
- Operating system breakdown
- Desktop vs. mobile ratios
- Device model distribution
5.5 A/B Testing and Personalization
Different device types can be shown different UI designs or features:
// Only enable complex animations for desktop users
const isDesktop = !/Mobi|Android/i.test(navigator.userAgent);
if (isDesktop) {
enableParticleAnimation();
}
6. How to Read the User-Agent
6.1 In the Browser
// Read the complete UA string
const ua = navigator.userAgent;
console.log(ua);
// Use the modern API (more semantic)
const uaData = navigator.userAgentData; // Chrome 90+
console.log(await uaData.getHighEntropyValues([
'architecture', 'model', 'platform', 'platformVersion',
'fullVersionList'
]));
6.2 On the Server Side
Node.js (Express):
app.get('/', (req, res) => {
const ua = req.headers['user-agent'];
console.log('Client UA:', ua);
});
Python (Flask):
from flask import request
@app.route('/')
def index():
ua = request.headers.get('User-Agent')
print(f'Client UA: {ua}')
PHP:
<?php
$ua = $_SERVER['HTTP_USER_AGENT'];
echo "Client UA: " . htmlspecialchars($ua);
?>
Java (Spring):
@GetMapping("/")
public String index(@RequestHeader("User-Agent") String userAgent) {
System.out.println("Client UA: " + userAgent);
return "index";
}
6.3 Via Browser DevTools
- Open DevTools in Chrome with
F12 - Navigate to the Network tab
- Refresh the page and click any request
- Find
User-Agentunder Request Headers
7. How to Modify the User-Agent
7.1 Chrome DevTools (Temporary)
- Open DevTools (
F12) - Click ⋮ → More tools → Network conditions
- Uncheck Use browser default
- Select a preset device or enter a custom UA string
7.2 Browser Extensions
Recommended extensions:
- User-Agent Switcher and Manager (Chrome/Firefox)
- User-Agent Switcher (Firefox)
7.3 Command-Line Tools
cURL:
# Simulate Chrome browser
curl -H "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36" https://example.com
Python requests:
import requests
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36'
}
response = requests.get('https://example.com', headers=headers)
Python Playwright (Automation Testing):
from playwright.sync_api import sync_playwright
with sync_playwright() as p:
browser = p.chromium.launch()
context = browser.new_context(
user_agent='MyCustomBot/1.0'
)
page = context.new_page()
page.goto('https://example.com')
8. Client Hints: The Future of User-Agent
Because UA strings contain too much passive information (enabling browser fingerprinting), Google has championed User-Agent Client Hints (UA-CH) as a privacy-preserving replacement.
8.1 Core Principles of UA-CH
- Minimal by default: Only a minimal set of information is sent without explicit request
- Active disclosure: Servers must explicitly request the information they need
- Privacy-first: Reduces passive fingerprinting opportunities
8.2 UA-CH Header Examples
Client sends by default:
Sec-CH-UA: "Chromium";v="124", "Google Chrome";v="124", "Not-A.Brand";v="99"
Sec-CH-UA-Mobile: ?0
Sec-CH-UA-Platform: "Windows"
Server requests additional information via response header:
Accept-CH: Sec-CH-UA-Full-Version-List, Sec-CH-UA-Arch, Sec-CH-UA-Model
Client’s subsequent requests include the requested fields:
Sec-CH-UA-Full-Version-List: "Chromium";v="124.0.6367.82", "Google Chrome";v="124.0.6367.82"
Sec-CH-UA-Arch: "x86"
Sec-CH-UA-Model: ""
8.3 Reading UA-CH in JavaScript
// Read basic info (no permissions needed)
const uaData = navigator.userAgentData;
console.log(uaData.brands); // Browser brand list
console.log(uaData.mobile); // Is mobile?
console.log(uaData.platform); // Operating system
// Read detailed info (requires Permissions Policy)
const highEntropyValues = await uaData.getHighEntropyValues([
'architecture',
'bitness',
'model',
'platformVersion',
'fullVersionList',
'uaFullVersion',
'wow64'
]);
console.log(highEntropyValues);
8.4 UA-CH Browser Support
| Browser | Support Status |
|---|---|
| Chrome 90+ | ✅ Full support |
| Edge 90+ | ✅ Full support |
| Firefox | ❌ Not supported yet |
| Safari | ❌ Not supported yet |
9. Best Practices for UA Detection
9.1 Prefer Feature Detection Over UA Sniffing
UA detection is a form of “user agent sniffing” and should be a last resort. In frontend development, always prefer feature detection.
// ✅ Recommended: Detect capabilities directly
if ('geolocation' in navigator) {
// Geolocation API is supported
}
if (CSS.supports('display', 'grid')) {
// CSS Grid is supported
}
// ❌ Avoid: Inferring capabilities from UA
if (navigator.userAgent.includes('Chrome')) {
// Assumes Chrome supports a feature
}
9.2 When UA Detection Is Appropriate
| Use Case | Recommended Approach |
|---|---|
| Feature support detection | Feature detection (Modernizr, etc.) |
| Mobile vs. desktop layout | CSS media queries + UA as supplement |
| Server-side content delivery | UA + Accept headers combined |
| Analytics and statistics | UA parsing (combined with UA-CH) |
| Bot filtering | UA + behavioral analysis + IP reputation |
9.3 Recommended UA Parsing Libraries
| Language | Recommended Libraries |
|---|---|
| JavaScript | ua-parser-js, bowser, detect-browser |
| Python | user-agents (based on ua-parser) |
| PHP | WhichBrowser/Parser |
| Java | uap-java |
| Go | mileusna/useragent |
10. Frequently Asked Questions
Can UA strings be faked?
Yes, very easily. The UA string is a self-declared field — the server has no way to verify its authenticity. Any HTTP client can send any UA string it wants. This is why UA alone should never be the sole basis for security decisions. Always combine it with IP reputation, behavioral analysis, and other signals.
Why do all browsers start with Mozilla/5.0?
It’s a historical artifact. Early websites served rich content only to Netscape (Mozilla) browsers. Other browsers started including Mozilla in their UA to receive the same content. This convention has persisted and virtually all modern browsers still begin with Mozilla/5.0.
Will navigator.userAgent be deprecated in favor of UA-CH?
Not immediately. Google previously planned to “freeze” the UA string in Chrome (reducing it to minimal info), but that plan has been paused. Long-term, UA-CH is the officially recommended direction, but the legacy navigator.userAgent API isn’t going away anytime soon.
How can I reliably distinguish real users from bots?
Relying on UA alone is insufficient. Combine multiple approaches:
- UA checking: Detect known bot UA signatures
- Behavioral analysis: Request frequency, mouse trajectories, JavaScript execution
- IP reputation: Identify datacenter IPs and known malicious sources
- CAPTCHA: Human verification challenges
- Honeypots: Hidden link traps invisible to humans
What’s the difference between User-Agent and Accept headers?
User-Agent identifies what the client is (which software), while Accept headers (Accept, Accept-Language, Accept-Encoding) describe what content types the client can handle. Used together, they allow servers to deliver the most appropriate response.
11. Online Analysis Tool
Want to instantly parse your current browser’s User-Agent — or analyze any UA string? Try our User-Agent Analyzer, which supports:
- Automatically read and display your current browser UA
- Parse browser name and version
- Identify operating system and version
- Detect device type (desktop / mobile / tablet)
- Display rendering engine information
- Flag whether the client is a crawler or bot
12. Conclusion
The User-Agent is a small but profound piece of web infrastructure. From Mosaic’s simple self-identification in 1993 to Chrome’s complex, multi-engine string today, the evolution of UA reflects the entire arc of web technology development.
| Key Takeaway | Recommendation |
|---|---|
| UA can be faked | Never use UA as the sole security signal |
| Prefer feature detection | Use feature detection in frontend code instead of UA sniffing |
| Learn about UA-CH | Follow the development of User-Agent Client Hints |
| Use established libraries | Parse UA with community-maintained specialist libraries |
| Combine signals | For anti-bot purposes, combine UA, behavior, and IP analysis |
Whether you’re doing frontend development, backend services, infrastructure monitoring, or web security, understanding User-Agent is an essential skill for every web developer. Use our User-Agent Analyzer to inspect and parse your browser’s information right now!