Back to HTTP Headers

User-Agent general request

Identifies the client software making the request — browser, bot, or API client.

What it does

User-Agent identifies the client making the request — its software, version, and sometimes the platform it's running on. Servers use it to understand who's talking to them: a Chrome browser, a Googlebot crawler, a mobile app, or a custom API client.

It's sent automatically by browsers and most HTTP clients. The information is advisory — servers can't verify it, and clients can set it to anything.

Syntax

User-Agent: <product>/<version> [<comment>]
User-Agent: <product>/<version> (<system-info>) [<engine>/<version>] [<platform>/<version>]

Examples:

User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36
User-Agent: Mozilla/5.0 (iPhone; CPU iPhone OS 17_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.0 Mobile/15E148 Safari/604.1
User-Agent: Googlebot/2.1 (+http://www.google.com/bot.html)
User-Agent: curl/8.4.0
User-Agent: python-requests/2.31.0
User-Agent: MyApp/1.0 ([email protected])

Reading browser User-Agent strings

Browser UA strings are notoriously complex. The reason: historical compatibility hacks. Every browser identified as "Mozilla" because servers would check for "Mozilla" to send rich content, and non-Mozilla browsers wanted that content too. The pattern stuck.

A modern Chrome UA string dissected:

Mozilla/5.0                                    ← Legacy compat token (meaningless)
(Windows NT 10.0; Win64; x64)                 ← OS: Windows 10, 64-bit
AppleWebKit/537.36                             ← Rendering engine (Blink, WebKit-based)
(KHTML, like Gecko)                            ← More legacy compat
Chrome/125.0.0.0                               ← Actual browser and version
Safari/537.36                                  ← More legacy compat (Chrome pretends to be Safari)

The useful bits: the OS info in parentheses, and the Chrome/X.X.X.X or Firefox/X.X or Safari/X.X product token.

Detecting bots and crawlers

Common bot User-Agents:

Agent User-Agent contains
Googlebot Googlebot
Bingbot bingbot
Facebook crawler facebookexternalhit
Twitter card crawler Twitterbot
Slack link preview Slackbot
curl curl/
Python requests python-requests/
Go HTTP client Go-http-client/

Don't rely solely on User-Agent for bot detection — it's trivially spoofable. Use it as a signal alongside IP reputation, request patterns, and browser fingerprinting for serious bot detection.

Why UA sniffing is a bad idea

For feature detection: Use navigator.userAgent in JavaScript only as a last resort. Use feature detection (if ('serviceWorker' in navigator)) instead — it's accurate regardless of UA string.

For browser-specific content: UA strings are unreliable. Chrome pretends to be Safari and Mozilla. Opera pretends to be Chrome. Edge pretended to be IE for years. Serve standards-based content and let the browser handle it.

For blocking/allowing: UA is trivially changed. Any sophisticated bot will clone a Chrome UA. Use server-side signals (request rate, timing, TLS fingerprinting) for real bot detection.

Setting User-Agent in API clients

For programmatic clients, a descriptive User-Agent helps server operators understand their traffic:

User-Agent: MyApp/2.0 (https://myapp.com; [email protected])
User-Agent: DataPipeline/1.0 (+https://company.com/bot)
User-Agent: Monitoring/1.0 [email protected]

Good convention: AppName/Version (purpose or contact URL). This mirrors what good crawlers do.

# Python requests
import requests
headers = {'User-Agent': 'DataFetcher/1.0 ([email protected])'}
requests.get('https://api.example.com/data', headers=headers)

User-Agent Reduction and Client Hints

Browsers are moving toward User-Agent reduction (Chrome's initiative) — reducing the information in the UA string to prevent passive fingerprinting. The frozen UA provides only major version and platform:

Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36

Minor versions and exact platform details are removed. Servers that need detailed client information should use User-Agent Client Hints (Sec-CH-UA, Sec-CH-UA-Platform, etc.) which require explicit opt-in.

Common mistakes and gotchas

Blocking requests with no User-Agent. Some scripts and API clients don't set User-Agent. Blocking them may block legitimate clients like automated tests, serverless functions, or internal tools.

Using User-Agent for security decisions. A malicious bot claiming to be Googlebot/2.1 gets whatever content you'd serve to Googlebot. For security, don't trust User-Agent — use authentication and authorisation.

Parsing UA strings manually. UA strings are notoriously complex and inconsistent across versions. Use a dedicated UA parsing library (ua-parser, device-detector) rather than writing regex.

Real-world examples

Desktop Chrome:

User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36

Mobile Safari:

User-Agent: Mozilla/5.0 (iPhone; CPU iPhone OS 17_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.0 Mobile/15E148 Safari/604.1

Googlebot:

User-Agent: Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)

curl:

User-Agent: curl/8.4.0

FAQ

Can I change my browser's User-Agent?

Yes — browser DevTools allow overriding User-Agent (useful for testing mobile layouts). Extensions can also change it. Servers can't detect that it's been changed.

Does User-Agent affect SEO?

Not directly — Googlebot uses its own UA and isn't affected by your app's UA string. However, if you serve different content to Googlebot vs real users (cloaking), that can negatively affect SEO and violates Google's guidelines.

What is User-Agent Client Hints?

An API replacing UA string parsing: browsers send structured hints (Sec-CH-UA: "Chrome"; v="125") rather than a messy string. Servers explicitly request the level of detail they need, and browsers only send what was requested. Reduces passive fingerprinting surface while still enabling legitimate use cases.

Fun fact

The "Mozilla/5.0" prefix in virtually every browser's User-Agent string is a compatibility fossil. In the early web (mid-1990s), many servers checked if User-Agent contained "Mozilla" to decide whether to send advanced HTML features (tables, frames, JavaScript). Netscape Navigator was Mozilla; IE was not. To get the rich content, IE 3.0 started identifying as "Mozilla/2.0 (compatible; MSIE 3.0)". Every other browser followed suit. Today, Chrome, Safari, Edge, and Firefox all include "Mozilla/5.0" as the first token — a tribute to a browser that hasn't been the dominant force on the web in 25 years.

Related Headers