What is the most reliable way to hide / spoof the referrer in JavaScript?

44,647

Solution 1

I have found a solution which works in Chrome and Firefox. I've implemented the code in a Userscript, Don't track me Google.

Demo (tested in Firefox 9 and Chrome 17): http://jsfiddle.net/RxHw5/

Referrer hiding for Webkit (Chrome, ..) and Firefox 37+ (33+*)

Webkit-based browsers (such as Chrome, Safari) support <a rel="noreferrer">spec.
Referrer hiding can fully be implemented by combining this method with two event listeners:

  • mousedown - On click, middle-click, right-click contextmenu, ...
  • keydown (Tab Tab Tab ... Enter).

Code:

function hideRefer(e) {
   var a = e.target;
   // The following line is used to deal with nested elements,
   //  such as: <a href="."> Stack <em>Overflow</em> </a>.
   if (a && a.tagName !== 'A') a = a.parentNode;
   if (a && a.tagName === 'A') {
      a.rel = 'noreferrer';
   }
}
window.addEventListener('mousedown', hideRefer, true);
window.addEventListener('keydown', hideRefer, true);

* rel=noreferrer is supported in Firefox since 33, but support was limited to in-page links. Referrers were still sent when the user opened the tab via the context menu. This bug was fixed in Firefox 37 [bug 1031264].

Referrer hiding for old Firefox versions

Firefox did not support rel="noreferrer" until version 33 `[bug 530396] (or 37, if you wish to hide the referrer for context menus as well).

A data-URI + <meta http-equiv=refresh> can be used to hide the referrer in Firefox (and IE). Implementing this feature is more complicated, but also requires two events:

  • click - On click, on middle-click, Enter
  • contextmenu - On right-click, Tab Tab ... Contextmenu

In Firefox, the click event is fired for each mouseup and hitting Enter on a link (or form control). The contextmenu event is required, because the click event fires too late for this case.

Based on data-URIs and split-second time-outs:
When the click event is triggered, the href attribute is temporarily replaced with a data-URI. The event finished, and the default behaviour occurs: Opening the data-URI, dependent on the target attribute and SHIFT/CTRL modifiers.
Meanwhile, the href attribute is restored to its original state.

When the contextmenu event is triggered, the link also changes for a split second.

  • The Open Link in ... options will open the data-URI.
  • The Copy Link location option refers to the restored, original URI.
  • ☹ The Bookmark option refers to the data-URI.
  • Save Link as points to the data-URI.

Code:

// Create a data-URI, redirection by <meta http-equiv=refresh content="0;url=..">
function doNotTrack(url) {
   // As short as possible. " can potentially break the <meta content> attribute,
   // # breaks the data-URI. So, escape both characters.
   var url = url.replace(/"/g,'%22').replace(/#/g,'%23');
   // In case the server does not respond, or if one wants to bookmark the page,
   //  also include an anchor. Strictly, only <meta ... > is needed.
   url = '<title>Redirect</title>'
       + '<a href="' +url+ '" style="color:blue">' +url+ '</a>'
       + '<meta http-equiv=refresh content="0;url=' +url+ '">';
   return 'data:text/html,' + url;
}
function hideRefer(e) {
   var a = e.target;
   if (a && a.tagName !== 'A') a = a.parentNode;
   if (a && a.tagName === 'A') {
      if (e.type == 'contextmenu' || e.button < 2) {
         var realHref = a.href; // Remember original URI
         // Replaces href attribute with data-URI
         a.href = doNotTrack(a.href);
         // Restore the URI, as soon as possible
         setTimeout(function() {a.href = realHref;}, 4);
      }
   }
}
document.addEventListener('click', hideRefer, true);
document.addEventListener('contextmenu', hideRefer, true);

Combining both methods

Unfortunately, there is no straightforward way to feature-detect this feature (let alone account for bugs). So you can either select the relevant code based on navigator.userAgent (i.e. UA-sniffing), or use one of the convoluted detection methods from How can I detect rel="noreferrer" support?.

Solution 2

Can't you create a linking system that resides within iframes?

If you wrap an iframe around every link, the iframe can act as an external de-refer. The user would click on the link inside the frame, opening a page whose referrer is set to the iFrame's location, instead of the actual page.

Solution 3

As requested, by using JavaScript:

var meta = document.createElement('meta');
meta.name = "referrer";
meta.content = "no-referrer";
document.getElementsByTagName('head')[0].appendChild(meta);

This will add the following meta tag to head section of the web page:

<meta name="referrer" content="no-referrer" />

As of 2015 this is how you prevent sending the Referer header.

Solution 4

There is a cross browser solution in Javascript that removes the referrer, it uses Iframes created dynamically, you can take a look to a proof of concept ( disclaimer: it uses a little JS library I wrote ).

Solution 5

You could use the new Referrer Policy standard draft to prevent that the referer header is sent to the request origin. Example:

<meta name="referrer" content="none">

Although Chrome and Firefox have already implemented a draft version of the Referrer Policy, you should be careful with it because for example Chrome expects no-referrer instead of none (and I have also seen never somewhere). I don't know the behaviour if you just add three separate meta tags, but in case that does not work you could still just implement a short script which iterates over all three values and checks if the value was really set after setting the attribute/property of the meta tag.

This meta tag applies to all requests on the current page (ajax, images, scripts, other resources...) and navigation to another page.

Share:
44,647

Related videos on Youtube

Rob W
Author by

Rob W

I like to develop useful software, web apps and browser extensions. Reply faster by getting real-time Desktop notifications for your SE inbox (for Firefox / Chrome) or install the user script / Chrome extension to “View Vote totals” without 1000 rep.

Updated on July 09, 2022

Comments

  • Rob W
    Rob W almost 2 years

    Normally, the referrer is traceable through:

    • JavaScript's document.referrer
    • The request headers, e.g. PHP's $_SERVER['HTTP_REFERER']

    I have set up a Codepad demo which shows these properties, for testing purposes.

    #Requirements:

    1. The original referrer should effectively be hidden, at least for all mouse events.
    2. Cross-browser support (at least Chrome and Firefox).
    3. Stand-alone, without any external content (plugins, libraries, redirection pages, ...).
    4. No side-effects: Links should not be rewritten, history entries should be preserved.

    The solution will be used to hide the referrer when following a link of <a href="url">.


    ##Exact description of the use-case As described in this question on Webapps, links at Google Search are modified on click. Consequently,

    1. Google is able to track your search behaviour (Privacy-- )
    2. The page request is slightly delayed.
    3. The linked page cannot track your Google search query (Privacy++ )
    4. Dragged/Copied URLs look like http://google.com/lotsoftrash?url=actualurl.

    I'm developing a Userscript (Firefox) / Content script (Chrome) (code), which removes Google's link-mutilating event. As a result, points 1, 2 and 4 are dealt with.

    Point 3 remains.

    • Chrome: <a rel="noreferrer">
    • Firefox: data-URIs. I have created a sophisticated approach to implement this feature for left- and middle-clicks, while still enforcing point 4. However, I'm struggling with the right-click method.
    • Matt
      Matt over 12 years
      FWIW, Facebook redirect all external links to l.php?the_url_you_want_to_visit, to ensure no personal information is included in the referrer attribute. This might be a hint towards "it isn't possible". Their detailed engineering note might be of interest.
    • Rob W
      Rob W over 12 years
      @Matt The reason that I want to not use external redirect pages is 1) Right-click copying will return the redirect link (instead of the actual one). 2) An external page is involved, which reduces the speed of browsing. See this userscript.
    • Golmaal
      Golmaal over 12 years
      does the <a rel='nofollow'> serve the purpose? It effectively stops search engines from giving undue importance to user generated links such as those on forums (which people put in their signs)
    • OnTheFly
      OnTheFly over 12 years
      I think there is a better idea to break google's code's code which replaces plain links with their spyredirector
    • Ansel Halliburton
      Ansel Halliburton over 12 years
      @RobW What exactly do struggle with, concerning right-clicks? The "open in tab" context-menu entry? I'm pretty sure that requirement 4 makes that impossible to solve with a userscript.
    • Rob W
      Rob W over 12 years
      @Pumbaa80 On contextmenu: hide the referrer, but keep the original URL on copy. There are very few, if not none sources on the Internet for this problem. Some creativity is surely required to solve this problem.
    • Ansel Halliburton
      Ansel Halliburton over 12 years
      It's possible to keep on copy: jsfiddle.net/efa5Q (for some reason the copy command uses some special method). However the other context menu items like "save as...", "send" or "add bookmark" will recieve the data url.
    • jim tollan
      jim tollan almost 10 years
      +1 -this is such an enduring question. whether used for good or ad [sic] this has so much merit and there are times when you just NEED to bypass the referrer (I have an instance just now where referring via my link produces the correct url, but then the base url detects this redirsct and issues it's own redirect back to my domain -not what i want. i'll try your solution and see if it works. however, the +1 remains either way as the logic here piqued my mind!!
  • Rob W
    Rob W over 12 years
    Looked promising, originally. However, it's no more different than my own method (currently using data-urls+meta, rel="noreferrer"), except for the disabling of the middle-mouse method, which is not desired. I usually click through links using the scrollwheel.
  • Ansel Halliburton
    Ansel Halliburton over 12 years
    The openLinkIn implementation can be found in utilityOverlay.js
  • Ansel Halliburton
    Ansel Halliburton over 12 years
    Actually, you have a very slim chance to trick the contextmenu, since the "copy to clipboard" command uses a different method to get the URL, ignoring this.linkURL.
  • Rob W
    Rob W over 12 years
    Just digged through your linked resources. It seems not to be possible to implement a refferer-hiding feature without any side effects. If no-one else posts an alternative ,the bounty is yours.
  • Rob W
    Rob W over 12 years
    I have just read your answer again. That's a nice idea. Can you elaborate your thoughts on setting a different URL of the iFrame, without using external pages? What about positioning the iFrame?
  • Rob W
    Rob W over 12 years
    I have awarded the bounty to your answer, because it contained a potentially useful concept, after tweaking. This method has some shortcomings/issues though. The main issue is the positioning and location of the frame. Using the tab key to navigate between links becomes more complicated as well. Finally, the performance hit/smoothness of dynamically adding frames over all anchors is also a subject of concern.
  • Rob W
    Rob W almost 12 years
    Thanks for the answer. Unfortunately, the blog only mentions the options. Besides, literally every possible solution in the blog post is already covered here: rel="noreferrer", noreferrer on Github and iframe routing. The "Compromise usability" solution relies on creating an ugly redirect URL - exactly what I wanted to avoid.
  • Rob W
    Rob W over 11 years
    Thanks for posting the implementation of the method described in this answer. It does not work in Opera (tested 11.62, 12.00b, 12.02) though. On the other hand, it does work in Safari 3+, Chrome 1+, Firefox 1+ and IE6, 7 and 8. It does not work in Internet Explorer 9 and 10. So, in practice, it's only useful in Chrome, Safari and Firefox.
  • Rob W
    Rob W over 11 years
    jpgerek implemented the method described in this answer. See this answer on this page.
  • Jakub Vrána
    Jakub Vrána over 10 years
    Unfortunately, the data: URI couldn't be used in IE which supports it only for downloadable contents, not HTML.
  • Rob W
    Rob W over 10 years
    Doesn't work. visit jsfiddle.net/Bp52M/show/1 (source and type document.referrer in the console. You'll see that the referrer is still available.
  • Jayen
    Jayen about 10 years
    Middle-click with the event listener on the element (not the document) in Firefox 28 doesn't trigger hideRefer. Any ideas?
  • Jayen
    Jayen about 10 years
    Context menu with rel='noreferrer' (no javascript) doesn't hide the referrer on Chrome 34. Any ideas?
  • Jayen
    Jayen about 10 years
  • Lukas
    Lukas almost 10 years
    userscripts.org is down. The alternative userscripts-mirror.org/scripts/review/181268 is a highjacked version. Where can the current release be accessed?
  • Rob W
    Rob W almost 10 years
  • Stephan
    Stephan about 9 years
    The bug 530396 has been fixed.
  • Rob W
    Rob W almost 9 years
    This seems to work in Firefox, Chrome and Opera (and supposedly also in the latest version of Safari - caniuse.com/referrer-policy), but I don't see an explicit statement in the specification that inserting a meta tag via JavaScript becomes immediately effective. UAs are still standard-compliant if they stop processing script-injected meta tags. Apparently (based on reading about Firefox's implementation at bugzil.la/704320), the last processed meta tag always "wins". (to be continued)
  • Rob W
    Rob W almost 9 years
    <meta name=referrer> seems like an excellent choice if you always want to declare a specific referrer policy, but otherwise (if you only want to target a specific link) using <a rel="noreferrer"> is more suitable, because 1) it takes precedence over the referrer policy, 2) it is specific to the link and does not have side effects on other links in the document and 3) it has better browser support.
  • MarcG
    MarcG almost 9 years
    For links, yes. However, the meta tag also works for Ajax requests. And it seems the ONLY way to disable the referrer for Ajax.
  • vir us
    vir us over 3 years
    this link is dead