Blog

Why Rendering Engine Names Pile Up in One String

A typical desktop browser string names several rendering engines that have never run in the same process. Each appears because removing it risked breaking pages that check for it.

Engine names entered as capability shorthand

Once engines diverged, sites began testing for the engine rather than the browser, on the reasoning that layout behaviour followed the engine. That was a better proxy than the product name.

Engine tokens therefore acquired meaning independent of the browser that shipped them. A site could target a rendering behaviour without enumerating every product built on it.

The reasoning was sound while engines were few and stable. It stopped being sound as soon as engines forked, merged and were replaced inside products that kept their names.

Forks inherited the parent's token

When an engine forked, the new engine kept the old token so that existing sites would continue to treat it as compatible. The fork was real; the identifier suggested otherwise.

That decision was defensible in the short term and corrosive in the long term. Sites gating on the old token now received a codebase that had diverged substantially from what they tested against.

Each fork adds a token without retiring one, because retiring one requires knowing that no deployed page depends on it. Nobody has that knowledge.

Browser switches added another layer

When a browser replaces its engine, it faces a choice between announcing the truth and preserving access. Products that switched engines generally kept tokens from both eras.

The string ends up describing the browser's history rather than its present. A parser reading it chronologically sees the engine lineage, not the code currently laying out the page.

For detection this is worse than a plain lie. A false statement can be corrected; a string of half-true legacy tokens has no single correct interpretation.

Version numbers attached to engine tokens froze

Some engine tokens carry version numbers that stopped advancing years ago. They are held constant because sites compare against them numerically and the comparisons assume a range.

A frozen number is functionally a constant with the appearance of data. Code that parses it and branches on the result is branching on nothing.

Distinguishing a frozen number from a live one requires knowledge that lives outside the string. This is precisely the knowledge that ad hoc parsing code never has.

Reading the pile-up correctly

The practical rule is that only certain tokens in a modern string are load-bearing, and which ones depends on the browser family. The rest are compatibility scaffolding.

Maintained parser libraries encode that knowledge as data, updated as vendors change behaviour. That is the difference between a library and a regular expression someone wrote once.

Anyone reading these strings directly should assume that most engine tokens describe lineage rather than implementation, and should look elsewhere for anything that must be accurate.