X Xerobit

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...

Mian Ali Khalid · · 4 min read
Use the tool
User Agent Parser
Parse any User-Agent string into browser, OS, device, and engine. Or detect your own. Built on the maintained ua-parser-js dataset.
Open User Agent Parser →

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 posts

Related tool

User Agent Parser

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.