Why the User Agent Is One Line and Not Structured
The user agent header carries browser, engine, platform and device information in a single unstructured line. That design has clear costs, and understanding why it persisted explains the current transition.
Early headers were single values by default
HTTP headers began as simple name-and-value pairs, with structure left to whatever convention each header adopted. There was no shared way to express a list of typed fields.
A header needing several facts therefore encoded them in its own ad hoc syntax. The user agent header chose product tokens with comments, and that was reasonable at the time.
Structured field definitions arrived much later, long after the value's shape was fixed by deployed software on both sides.
One line means one all-or-nothing decision
A client sending the header sends everything in it. There is no way to send the browser name while withholding the device model, because they occupy the same value.
That coupling is the header's central design flaw from a privacy standpoint. The useful parts and the identifying parts travel together on every request.
It also prevents sites from asking for less. A server that only needs to know the platform still receives everything the client sends.
Unstructured values resist versioning
Changing a structured field is a schema change consumers can be told about. Changing an unstructured string is an unannounced behavioural change that breaks whichever parsers guessed wrong.
Vendors are therefore extremely cautious about editing the value. Even removing genuinely obsolete tokens carries unquantifiable risk.
The format's rigidity comes from its looseness. Because anyone may parse it any way, no change is safely backwards compatible.
Every request pays the same cost
The header is sent with every request to every origin, including requests for images and scripts where nothing consumes it. On a page with many subresources the repetition is substantial.
Header compression reduces the wire cost on modern connections but does not remove the design problem. The information is still broadcast where it is not needed.
A request-only model inverts this. Nothing detailed is sent until a server states what it needs, which turns a default broadcast into a negotiated exchange.
Structured replacement is additive by necessity
The replacement mechanism defines separate fields with defined types and values, so a consumer reads a field rather than a substring.
It could not replace the old header outright, because doing so would break everything currently parsing it. Both therefore ship together, with the old one reduced in detail rather than removed.
That dual-track state is the practical situation for anyone building detection now. Code must read structured fields where available and fall back to string parsing where they are not.