The HTTP Referer header is a typo from the 1990s that can never be fixed, and almost everything built around it since then spells the word correctly. That split is why req.headers.referrer comes back undefined and why a Referer-Policy header does nothing at all.
This post covers how the typo got in and which spelling goes where. It ends with one line of config I think every site should send.
What the header does
When you click a link, or a page loads an image, the browser can tell the server which page the request came from. That address travels in a request header named Referer. Servers use it for analytics and for tracking down broken inbound links.
The English word is "referrer," with a double R in the middle. The header has a single one.
How the typo got in
People noticed early. In March 1995, John Franks asked the HTTP working group mailing list if anyone else had noticed that the header was spelled wrong. Roy Fielding, who co-wrote the HTTP specs, replied on March 9.
That's okay, neither one (referer or referrer) is understood by "spell" anyway. I say we should just blame it on France. ;-)
spell was the Unix spell checker. It rejected the right spelling along with the wrong one, so it was never going to catch this.
The typo is usually pinned on Phillip Hallam-Baker, who suggested the field. He replied in that thread a day later, and his message is a better story than the legend.
I also managed to mispell alt.games.mornington.cresent when I created it. I think this one is down to Tim. I sent him a note with the suggestion but I don't think I gave a name for the field.
Yes, "mispell" is misspelled in an email about misspelling. "Tim" is presumably Tim Berners-Lee, the first author listed on the HTTP/1.0 spec. So the man who usually gets the blame handed it to someone else almost immediately.
Why it stayed
HTTP/1.0 was written down as RFC 1945 in May 1996. That document says it "reflects common usage" of a protocol people were already running, and it prints Referer without comment. HTTP/1.1 followed in January 1997 as RFC 2068, and it added a small confession. The field became "Referer[sic]" with a note that "the header field is misspelled."
The current HTTP spec, RFC 9110 from June 2022, still carries the "[sic]" and still says the field name is misspelled. Nearly three decades of specs have documented the typo instead of correcting it.
They had no real choice. By the time anyone complained, browsers were sending the header and servers were reading it. Renaming it would have broken every one of them for the sake of a dictionary. The web keeps its mistakes when fixing them would break working sites, which is the same reason every browser still claims to be Mozilla.
Which spelling goes where
Here is the rule I use. The request header keeps the typo. Everything designed after it uses the dictionary spelling.
| Where you are | What to type |
|---|---|
| HTTP request header | Referer |
| Node.js request object | req.headers.referer |
| HTTP response header that controls it | Referrer-Policy |
| The DOM | document.referrer |
fetch() options |
referrer and referrerPolicy |
| HTML attribute | referrerpolicy |
| Document-wide meta tag | <meta name="referrer"> |
| Link relation | rel="noreferrer" |
There is a second trap hiding in that table. The link relation is noreferrer with no hyphen, and the policy value is no-referrer with one. MDN has a warning box about exactly this.
The server side is where the typo bites most often, because a wrong property name doesn't throw. It hands you undefined and your analytics quietly record nothing.
import { createServer } from "node:http";
const server = createServer((req, res) => {
const cameFrom = req.headers.referer; // one R in the middle, the 1995 spelling
const typo = req.headers.referrer; // the dictionary spelling, always undefined
res.setHeader("Referrer-Policy", "strict-origin-when-cross-origin");
res.setHeader("Content-Type", "application/json");
res.end(JSON.stringify({ cameFrom, typo }));
});
server.listen(3000);
Send that server a request with a Referer header and the JSON that comes back has cameFrom and no typo key at all. Notice the response header on line 7 uses the correct spelling. Both spellings in one handler is normal, and it is correct.
In HTML, you only ever need the dictionary spelling.
<a href="https://example.org/" rel="noreferrer">Visit our partner site</a>
<img
src="https://cdn.example.org/visits.png"
alt="Bar chart of monthly site visits"
referrerpolicy="no-referrer"
/>
What the header carries today
A lot of older tutorials assume the header holds the full URL of the previous page. For links between two different sites, that stopped being true years ago.
The default referrer policy is now strict-origin-when-cross-origin. Chrome switched to it in version 85 in August 2020, and Firefox followed in version 87 in March 2021. An origin is the scheme, host and port of a URL taken together. Under this policy, a request to the same origin gets the full URL. A request to a different origin gets only the origin, like https://example.com/, with no path and no query string. An HTTPS page linking to a plain HTTP one sends nothing.
So when your analytics show a bare domain as the source of a visit, nothing is broken. The visitor's browser trimmed the rest on purpose.
Set the policy yourself
I still send the header explicitly instead of trusting the default. Chrome's own guidance recommends the same thing.
Referrer-Policy: strict-origin-when-cross-origin
Spell it with the double R. A misspelled Referer-Policy is an unknown header, and browsers ignore unknown headers without a word in the console.
Pages with secrets in the URL deserve something stricter. MDN's example is a password reset page with a social media link in the footer. If the reset URL leaks through the referrer, the other site is holding a key to the account. For pages like that, no-referrer is the right call, along with keeping third-party content off them.
What it costs and where it fails
Don't treat the header as a security control. RFC 9110 says plainly that not all requests contain it, and users or policies can strip it. Chrome's guidance for cross-site request forgery checks points you at the Origin and Sec-Fetch-Site headers instead.
Going to no-referrer across a whole site has a price too. Sites you link to can no longer see that you sent them visitors, and your own page-to-page reports lose their trail. There is a subtler cost as well. Under no-referrer, MDN notes that form submissions go out with Origin: null, which can trip a server-side check that compares origins.
A strict policy also doesn't excuse putting sensitive data in URLs. The policy limits who sees the address. It doesn't make the address safe.
The short version
One header carries a typo forever, and everything around it is spelled properly. Read Referer on the server, type referrer everywhere else, and send a Referrer-Policy header on purpose. If you remember only one thing, remember that the misspelled one is the one the browser sends you.
Sources
- Re: Referer: (sic), Roy T. Fielding, ietf-http-wg, March 9, 1995
- Re: Referer: (sic), Phillip M. Hallam-Baker, ietf-http-wg, March 10, 1995
- RFC 1945, Hypertext Transfer Protocol HTTP/1.0
- RFC 2068, Hypertext Transfer Protocol HTTP/1.1
- RFC 9110, HTTP Semantics
- Referer header, MDN
- Referrer-Policy header, MDN
- Referer header: privacy and security concerns, MDN
- Document: referrer property, MDN
- RequestInit, MDN
- rel=noreferrer, MDN
- A new default Referrer-Policy for Chrome, Chrome for Developers
- Firefox 87 trims HTTP Referrers by default to protect user privacy, Mozilla Security Blog
- HTTP referer, Wikipedia