Dev.to WebDev πŸ›  Dev πŸ‘ 0 πŸ“– 6 min read

Understanding Browser User-Agent Strings: Why Does Chrome Still Say "KHTML, like Gecko"?

If you've ever inspected the HTTP headers sent by your browser, you've probably seen something like this: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36

If you've ever inspected the HTTP headers sent by your browser, you've probably seen something like this:

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

At first glance, it looks confusing.

Questions immediately come to mind:

  • Why does Chrome identify itself as Mozilla?
  • What is AppleWebKit?
  • What is KHTML?
  • What does "like Gecko" actually mean?
  • Why does Chrome say Safari even though it isn't Safari?

The answer lies in more than 30 years of browser history.

Let's travel back in time.

What Is a User-Agent?

A User-Agent is an HTTP header that tells a web server information about the client making the request.

Example:

GET / HTTP/1.1
Host: example.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64)
AppleWebKit/537.36 (KHTML, like Gecko)
Chrome/139.0.0.0 Safari/537.36

A server can use this information to:

  • Detect the browser
  • Detect the operating system
  • Serve mobile or desktop layouts
  • Enable browser-specific features
  • Collect analytics
  • Debug compatibility issues

Today, browsers are slowly moving toward User-Agent Client Hints, but traditional User-Agent strings are still widely used.

Breaking Down a User-Agent

Let's analyze Chrome's User-Agent.

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

Every part has historical significance.

Part 1: Mozilla/5.0

This is probably the strangest part.

Chrome is not Mozilla.

Safari isn't Mozilla.

Edge isn't Mozilla.

So why does almost every browser start with:

Mozilla/5.0

To understand this, we need to go back to the 1990s.

The Browser Wars

In the early days of the web, two browsers dominated:

  • Netscape Navigator
  • Internet Explorer

Netscape identified itself as:

Mozilla

The word Mozilla was originally a combination of:

Mosaic + Godzilla

Mosaic was one of the earliest web browsers.

Developers nicknamed Netscape's browser "Mozilla" because it was expected to "destroy" Mosaic.

Later, Mozilla became Netscape's internal codename.

Websites Started Checking for Mozilla

Many websites contained code like:

if (browser == "Mozilla") {
    enableAdvancedFeatures();
}

If your browser wasn't Mozilla...

The website simply didn't work correctly.

Everyone Pretended to Be Mozilla

Internet Explorer began sending:

Mozilla/2.0

Later:

Mozilla/4.0

Then Opera.

Then Safari.

Then Chrome.

Even Microsoft Edge.

Eventually every browser began pretending to be Mozilla for compatibility.

That's why the prefix still exists today.

It isn't identifying the browser anymore.

It's simply a historical compatibility marker.

Why Version 5.0?

Modern browsers almost universally report:

Mozilla/5.0

because Netscape 5 was never actually released.

Developers standardized on this value, and changing it today would risk breaking websites that still rely on old detection logic.

Part 2: Windows NT 10.0

This identifies the operating system.

Examples:

Windows:

Windows NT 10.0

Linux:

X11; Linux x86_64

macOS:

Macintosh; Intel Mac OS X 10_15_7

Android:

Linux; Android 15

iPhone:

iPhone; CPU iPhone OS 18_0 like Mac OS X

This information helps websites adapt to different platforms.

Part 3: AppleWebKit

This tells us which browser engine is being used.

But why Apple?

Chrome isn't made by Apple.

What Is a Browser Engine?

A browser engine converts HTML, CSS, and JavaScript into the web pages you see.

Think of it as the browser's rendering engine.

HTML
CSS
JavaScript
      β”‚
      β–Ό
Browser Engine
      β”‚
      β–Ό
Visible Web Page

Popular browser engines include:

Engine Used By
Blink Chrome, Edge, Opera, Brave
WebKit Safari
Gecko Firefox

Years ago, there were many more.

Where Did WebKit Come From?

Before WebKit existed, there was another engine called KHTML.

Meet KHTML

In 1998, the KDE project created:

  • KHTML (HTML rendering engine)
  • KJS (JavaScript engine)

They were lightweight, fast, and open source.

Apple was building Safari and needed a rendering engine.

Instead of writing one from scratch...

Apple chose KHTML.

Apple Forked KHTML

Apple modified KHTML heavily.

Eventually it became:

WebKit

So the relationship looks like this:

KHTML
    β”‚
    β–Ό
WebKit
    β”‚
    β–Ό
Blink

This family tree explains a lot.

Why Does Chrome Say AppleWebKit?

Google originally built Chrome using WebKit.

Chrome inherited:

AppleWebKit/537.36

Even after Google created Blink in 2013, it kept the same User-Agent token.

Changing it would've broken countless websites.

So today:

Chrome uses Blink...

but still reports:

AppleWebKit/537.36

for compatibility.

What Is KHTML?

KHTML was one of the earliest fast, standards-compliant rendering engines.

It powered:

  • Konqueror
  • KDE applications

Although KHTML itself is rarely used today, its influence lives on because both WebKit and Blink originated from it.

What Does "KHTML, like Gecko" Mean?

This is one of the most misunderstood parts of a User-Agent.

Chrome reports:

(KHTML, like Gecko)

Notice something important.

It does not say:

Gecko

It says:

like Gecko

Those two words make all the difference.

What Is Gecko?

Gecko is Firefox's rendering engine.

It was created by Mozilla after Netscape.

Firefox uses:

Gecko

But Chrome doesn't.

Safari doesn't.

Edge doesn't.

So Why "like Gecko"?

During the browser wars, websites began checking specifically for Gecko.

Example:

if (engine == "Gecko") {
    enableCSSAnimation();
}

Chrome wanted those websites to work.

But Chrome wasn't Gecko.

So it reported:

like Gecko

This essentially means:

"I'm not Gecko, but I behave similarly enough for compatibility."

It's a compatibility statementβ€”not a declaration of the rendering engine.

Chrome Doesn't Actually Use Gecko

Chrome's rendering engine is:

Blink

Firefox's rendering engine is:

Gecko

Safari's rendering engine is:

WebKit

Yet Chrome still includes:

KHTML, like Gecko

because millions of websites expect to see it.

Part 4: Chrome/139.0.0.0

This identifies the browser.

Example:

Chrome/139.0.0.0

Firefox would instead report:

Firefox/142.0

Safari uses:

Version/18.0

This is usually the easiest part of the User-Agent to understand.

Part 5: Safari/537.36

This surprises many developers.

Chrome says:

Safari/537.36

But Chrome isn't Safari.

This token exists because Chrome originally inherited WebKit from Safari.

Many websites looked for the Safari token to determine WebKit compatibility.

Removing it would have broken those websites.

So Google left it in place.

The Browser Engine Family Tree

Here's the history in one diagram:

Mosaic
   β”‚
   β–Ό
Netscape Navigator
   β”‚
   β–Ό
Mozilla
   β”‚
   β–Ό
Gecko
   β”‚
   β–Ό
Firefox


KHTML
   β”‚
   β–Ό
WebKit
   β”‚
   β”œβ”€β”€β”€β”€β”€β”€β”€β”€β–Ί Safari
   β”‚
   β–Ό
Blink
   β”‚
   β”œβ”€β”€β”€β”€β”€β”€β”€β”€β–Ί Chrome
   β”œβ”€β”€β”€β”€β”€β”€β”€β”€β–Ί Edge
   β”œβ”€β”€β”€β”€β”€β”€β”€β”€β–Ί Opera
   └────────► Brave

Why Are User-Agent Strings So Messy?

Because they carry over three decades of browser history.

Every browser had to maintain compatibility with websites that performed browser sniffing.

Instead of identifying themselves accurately, browsers gradually accumulated historical tokens that websites expected to see.

A modern User-Agent is less a precise description of the browser and more a record of the web's evolution.

The Future: User-Agent Client Hints

Traditional User-Agent strings reveal a lot of information and are difficult to change without breaking websites.

To improve privacy and reduce fingerprinting, modern browsers are introducing User-Agent Client Hints.

Instead of sending everything in one long string, browsers expose only the information a website requests, often requiring explicit opt-in from the server.

Example:

Sec-CH-UA
Sec-CH-UA-Platform
Sec-CH-UA-Mobile

This provides a more structured and privacy-friendly way to identify browser capabilities.

Should You Parse User-Agent Strings?

In most cases, no.

Instead of checking:

"Is this Chrome?"

Prefer checking:

"Does this browser support the feature I need?"

This approach, known as feature detection, is more reliable because browsers evolve over time while capabilities matter more than names.

Libraries like Modernizrβ€”or native JavaScript feature checksβ€”are generally better than relying on browser sniffing.

Conclusion

The next time you see a User-Agent like this:

Mozilla/5.0
AppleWebKit/537.36
(KHTML, like Gecko)
Chrome/139.0.0.0
Safari/537.36

remember that it isn't describing Chrome in the way you'd expect.

It's carrying decades of browser history:

  • Mozilla exists because of Netscape compatibility.
  • AppleWebKit reflects Chrome's origins before Blink.
  • KHTML is the ancestor of WebKit.
  • like Gecko tells websites Chrome behaves similarly enough for compatibilityβ€”it is not using Gecko.
  • Safari remains for historical compatibility with WebKit-based browser detection.

What looks like a simple identification string is actually a living artifact of the web's evolution. Understanding it offers a fascinating glimpse into how browsers have balanced innovation with the need to keep billions of websites working across generations.

πŸ“° Read the original article on Dev.to WebDev

Originally published by Dev.to WebDev. Aggregated on AIWithGhost for educational purposes β€” full credit and traffic to the original publisher.