HTTP User-Agent Header — Format, Parsing, and Common Values
The User-Agent header identifies the client making an HTTP request. Learn its format, why parsing it is unreliable, common browser UA strings, and how to use it for device...
The User-Agent header is a string browsers send with every HTTP request identifying the browser, engine, OS, and device. It’s notoriously complex to parse and easy to spoof.
Parse user agent strings with the User-Agent Parser.
User-Agent format
General format:
Mozilla/5.0 (<system-info>) <platform> (<platform-details>) <extensions>
Chrome on Windows:
Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36
Firefox on macOS:
Mozilla/5.0 (Macintosh; Intel Mac OS X 14.2; rv:120.0) Gecko/20100101 Firefox/120.0
Safari on iPhone:
Mozilla/5.0 (iPhone; CPU iPhone OS 17_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.1 Mobile/15E148 Safari/604.1
Chrome on Android:
Mozilla/5.0 (Linux; Android 14; Pixel 7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.6099.110 Mobile Safari/537.36
Node.js (no UA by default, sets this in fetch):
Node.js/20.10.0
Why “Mozilla/5.0”? Historical compatibility: all browsers prefix with Mozilla/5.0 because early web servers served richer content to Netscape (which used “Mozilla”). Every browser pretends to be Mozilla.
Extract UA components in Node.js
import { UAParser } from 'ua-parser-js'; // npm install ua-parser-js
const ua = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36';
const parser = new UAParser(ua);
parser.getResult();
// {
// browser: { name: 'Chrome', version: '120.0.0.0', major: '120' },
// engine: { name: 'Blink', version: '120.0.0.0' },
// os: { name: 'Windows', version: '10' },
// device: { model: undefined, type: undefined, vendor: undefined },
// cpu: { architecture: 'amd64' }
// }
// Just the browser name:
parser.getBrowser().name; // "Chrome"
parser.getOS().name; // "Windows"
parser.getDevice().type; // undefined (desktop has no type)
Mobile detection
import { UAParser } from 'ua-parser-js';
function isMobile(userAgent) {
const parser = new UAParser(userAgent);
const deviceType = parser.getDevice().type;
return deviceType === 'mobile' || deviceType === 'tablet';
}
// In Express:
app.get('/api/content', (req, res) => {
const ua = req.headers['user-agent'] || '';
const mobile = isMobile(ua);
res.json({
version: mobile ? 'mobile' : 'desktop',
});
});
Caveat: Prefer CSS media queries for responsive design. Server-side UA detection for layout changes is a maintenance burden. Use UA detection only for:
- Downloading platform-specific binaries
- Analytics breakdown
- Progressive enhancement (not core layout)
Common User-Agent patterns
// Check without a full library (simple cases):
function quickUA(ua) {
if (/bot|crawler|spider|slurp|googlebot/i.test(ua)) return 'bot';
if (/Mobi|Android|iPhone|iPad/i.test(ua)) return 'mobile';
return 'desktop';
}
// Detect specific browsers:
const isChrome = /Chrome\//.test(ua) && !/Chromium\//.test(ua) && !/Edg\//.test(ua);
const isFirefox = /Firefox\//.test(ua);
const isSafari = /Safari\//.test(ua) && !/Chrome\//.test(ua);
const isEdge = /Edg\//.test(ua);
Bot detection
const BOT_PATTERNS = [
/Googlebot/i,
/Bingbot/i,
/Slurp/i, // Yahoo
/DuckDuckBot/i,
/Baiduspider/i,
/YandexBot/i,
/facebookexternalhit/i,
/Twitterbot/i,
/LinkedInBot/i,
/Applebot/i,
/bot|crawler|spider/i, // Generic patterns
];
function isBot(ua) {
return BOT_PATTERNS.some(pattern => pattern.test(ua));
}
// Skip analytics for bots:
app.use((req, res, next) => {
req.isBot = isBot(req.headers['user-agent'] || '');
next();
});
User-Agent spoofing
Any client can send any User-Agent string — never rely on it for security:
# curl with custom UA:
curl -H "User-Agent: Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)" https://example.com
# wget:
wget --user-agent="Mozilla/5.0 Chrome/120" https://example.com
// Node.js fetch:
fetch('https://api.example.com/data', {
headers: {
'User-Agent': 'MyApp/1.0 (contact@example.com)',
},
});
Frozen/reduced User-Agent (User-Agent Reduction)
Chrome is freezing parts of the User-Agent to reduce fingerprinting. As of Chrome 107+:
Old UA: Mozilla/5.0 (Windows NT 10.0; Win64; x64) Chrome/107.0.5304.87
New UA: Mozilla/5.0 (Windows NT 10.0; Win64; x64) Chrome/107.0.0.0
Minor version, patch, and build number frozen to "0.0"
Google is migrating to User-Agent Client Hints (Sec-CH-UA-* headers) for detailed browser information on opt-in basis.
Related tools
- User-Agent Parser — parse UA strings visually
- Client Hints API Guide — modern alternative to UA
- HTTP Status Codes — HTTP request/response reference
Related posts
- Bot Detection Using User Agent Strings — Googlebot, Bingbot, and Crawlers — Identify search engine crawlers, social media bots, and malicious scrapers from …
- Browser Detection in JavaScript — Feature Detection vs User Agent Parsing — Detect browsers, OS, and device type in JavaScript using user agent strings, fea…
- User-Agent Client Hints — Modern Browser Detection Without UA Sniffing — User-Agent Client Hints replace UA string parsing with structured HTTP headers. …
Related tool
Parse any User-Agent string into browser, OS, device, and engine. Or detect your own. Built on the maintained ua-parser-js dataset.
Written by Mian Ali Khalid. Part of the Dev Productivity pillar.