3 min read

Don’t Use the X- Prefix for HTTP Headers

The HTTP protocol is defined by a wide range of standards. For example, RFC 2068 from 1997 subtly touches on compatibility issues related to the X- prefix. In section 3.5, it states:

For compatibility with previous implementations of HTTP, applications should consider “x-gzip” and “x-compress” to be equivalent to “gzip” and “compress” respectively.

Here, the prefix isn’t part of the header key but part of the header value. Why this matters becomes clearer when we look at the historical context. References to custom headers also appear in RFC 2047 from November 1996. This RFC deals with MIME and message header extensions. Specifically, Keith Moore notes:

An ‘encoded-word’ may also appear in any user-defined (“X-”) message or body part header field.

So, this time we’re not just talking about values but actual header keys. The note itself is more of an acknowledgment of existing practice than an official declaration. Even this RFC was just an update to earlier ones where the X- prefix was already commonly mentioned. Special attention to X- headers can also be found in RFC 2045 section 6.3 and in the best practices of RFC 2048. At that time, using the X- prefix was also recommended for certain media types that weren’t yet standardized.

In other words, in the early days of the internet, people would occasionally invent their own HTTP headers and use them for their own purposes. To distinguish them from standardized ones, they followed the RFC pattern and used the X- prefix.

But the problem arose when some of these custom headers became successful and eventually standard. By the time a feature gets standardized, it’s often already in widespread use. If clients have been relying on a particular X- header for years, you can’t simply mandate everyone to switch names once the standard is published. For backward compatibility, either both versions are accepted, or the standard ends up with an ugly HTTP header carrying the X- prefix. Many such headers were standardized between 1997 and 2011.

In 2012, RFC 6648 was published under the title “Deprecating the ‘X-’ Prefix and Similar Constructs in Application Protocols.” It explains why. Among other things, it notes that the X- prefix was historically tied to the FTP protocol, with references going all the way back to RFC 691 from 1975:

I suggest that parameters be allowed to be more than one letter, and that an initial letter X be used for really local idiosyncracies.

This idea of using X- for “local idiosyncrasies” survived for over 45 years. And today developers still argue about whether the X- prefix should be used for HTTP headers in REST APIs. The prefix made its way from FTP, through email headers, into HTTP RFCs as I mentioned earlier. Finally, in 2012, RFC 6648 formally analyzed the issues with X-.

Conclusion

I’ll try to interpret the conclusions as described in the RFC, but from the perspective of web application developers (rather than protocol authors). When designing HTTP headers, developers should keep in mind that any header could eventually become a standard. They should always prefer an existing standard header, and only if no suitable one exists, choose a clear and descriptive custom name. Developers should not use the X- prefix.

The end of the analysis also mentions exceptions where the X- prefix might be justifiable. These are situations where it is extremely unlikely that a header with that particular key would ever become a standard. For example, X-CoffeeShop is unlikely to be standardized. Even in such cases, however, it’s better to choose a more descriptive name or replace the prefix with something more meaningful, such as App-CoffeeShop.

Using X- could also make sense where it is meant to carry special semantic meaning or emphasis. For example, to indicate higher priority compared to another standard header (though this is speculative at best). Still, even in such cases the standard recommends choosing a more suitable synonym.

The last exception includes scenarios where the goal is to minimize header length, and where X again has a specific meaning.

In short, to sum it up in the words of RFCs from 10 years ago: developers should not use the X- prefix.

Either way, I would recommend focusing your energy on the question of how to properly document HTTP headers. Whether I accept a request header with or without the prefix doesn’t really matter in the end. What truly matters is that the API consumer knows exactly what they’re supposed to send. And this is precisely the piece of information missing from most REST API documentation.

Comments