Email Protection with MooTools JavaScript

By  on  

Important Note: This article has been updated here.

We all know how spammers write scripts to slurp pages and collect as many emails as they possibly can, right? Well, I've created a really easy way to avoid this problem using MooTools JavaScript. Let me show you the process.


	<a href="/david|" class="email" title="Email me.">David Walsh</a>

We create a link with the CSS class "email". The email address is inside the href attribute, but the "@" is replaced with "|". Worthless to a spammer's slurp script. The href's beginning "/" is an IE workaround.

The MooTools JavaScript

$$('.email').each(function(el) { 
	el.set('href','mailto:' + el.get('href').replace('|','@').replace('/','')); 

Once the DOM is ready (as always), we grab each link with the email class. We take each link's href (the modified email address) and reformat the address so that it acts as a normal email link.

Have a better solution? Share it!

Recent Features

  • By
    Write Better JavaScript with Promises

    You've probably heard the talk around the water cooler about how promises are the future. All of the cool kids are using them, but you don't see what makes them so special. Can't you just use a callback? What's the big deal? In this article, we'll...

  • By
    CSS vs. JS Animation: Which is Faster?

    How is it possible that JavaScript-based animation has secretly always been as fast — or faster — than CSS transitions? And, how is it possible that Adobe and Google consistently release media-rich mobile sites that rival the performance of native apps? This article serves as a point-by-point...

Incredible Demos


  1. I’d go against the anchor tag altogether, since it pretty much is a dead link if your JS breaks (it happens) or if JS is turned off.

    I figure using a span, and replacing it altogether with the generated anchor, or linking it to an actual page and using a ‘rel’ property to store the information, maybe…

  2. @keif: Didn’t think of that — awesome idea.

  3. Steinmann

    I’m using rot13() to “encrypt” the email, and then javascript to decrypt it.

    Used a combo of urlencoding and htmlentities before. But I think thats useless…

  4. Catar4x

    Nice and easy ! Thanks !

  5. Andrei

    Span + background image of the url I think, just in case JS is switched off.

    Can spamailbots read alt tags?

  6. @Andrei: Yes.

  7. Rich

    for jQuery:

    el = $('.email');
    {el.attr('href','mailto:' + el.attr('href').replace('|','@').replace('/',''));});

    let me know if there is a simpler way.

    thanks Dave..always awesome posts!

  8. Why not redirect instead of obfuscate? This is my solution:

    The XHTML

      <a href="nospam.php" class="email" title="Email me.">David Walsh</a>

    The PHP (nospam.php)



    The MooTools Javascript (not quite sure about that …)

      window.addEvent('domready', function()
      {       $each($$('.prevent'),function(el)
      {               event.preventDefault(); 
                  window.location.href =
      "";         }); 
          });   });

    What do you think?

  9. @Dirk: Very interesting!

  10. Andy Couch

    One idea I had is to take your approach, but make the link work without javascript. So instead of linking to “/david|”, link to something like “email.html?david|” then have the email.html page explain what happened and why the link didn’t work if JavaScript wasn’t available. You could even provide instructions on how to manually recreate the email address with actually writing it out on the page. Not a perfect solution, but better than just returning a 404.

    Also, you could take advantage of URL re-writing to give you a cleaner email URL. Maybe something like “email/david|”.

    That’s my 2¢

  11. Andy Couch

    Correction: “…recreate the email address withOUT actually writing it out on the page.”

  12. @Andy: Another good solution.

  13. gret stuff, could it be that this solution doesn’t work in IE ( using Outlook Express 6)?. I’m working with Mac Os, it works fine. But the Virtual Machine of Windows doesn’t accept this. Sorry for my bad english,

    greetings from germany

  14. Andrei

    @David: Cheers for the reply. Was thinking of a fallback for when JS is shut off.

  15. peter

    newbie question :

    I am trying stuff with this script.
    Currently I have my e-mail setup like this

    <a href="/firstname_lastname|domain_ext" class="email" title="Send email">mail</a>

    and the javascript :

    $$('.email').each(function(el) {   
            el.set('href','mailto:' + el.get('href').replace('|','@').replace('/','').replace('_','.'));   

    but it shows up like this :

    how can I have the script also change the second underscore ?

    I’m not asking if this is a good or useful way to obscure the address, I’m just learning mootools and would like to know how to handle multiple instances of the underscore.

    Do I need to wrap it inside a nested .each ?

  16. Hey David. Thanks for the great articles. I read your blog often. I think this is my first response so I hope it’s of value to you and your readers.

    I wanted to leave a comment for you with my $0.02 As stated above by others, having a link on the page is probably bad form and will produce a 404 error to a non JS enabled browser. I wrote an article about this similar topic a short wile back to

    In particular I really like the Javascript obscure methods. The last method described in the “Project Honey Pot” really seams to work well. Joe Mailer’s method works really well to, and does not require a lot of obfuscation legwork.

    I urge you and your readers to check it out as an option too. Perhaps you can make a mootools script so that it could be automated and less work to impliment.

  17. Andy Couch

    @peter: I don’t use MooTools, but if it works the same as the standard JavaScript replace method, you would use replace(/_/g,'.');

  18. peter

    just a quick note for anyone interested, I solved my problem aboove with the following code :

  19. Andy Couch

    @peter: In your example, the brackets aren’t necessary. In regular expressions, the brackets define a character set, which is used in searching for more than one character or a range of characters. Since you are searching for a single character, they aren’t needed in this case. Also, the i modifier tells the regular expression search to be case-insensitive. But since the underscore character does have a case, that bit is unnecessary as well. So replace(/_/g,’.’) would do the same as replace(/[_]/gi,’.’).

  20. peter

    many thanks for the explanation, learning everyday. regular expressions are still on a distant planet for me… I should have known that the brackets define a set though, just like in php and javascript where they are used for arrays.

    thanks again.

  21. Just the replacement of ‘|’ is probably not the safest way to do it as you can also confirm from the study by Silvan Mühlemann: Nine ways to obfuscate e-mail addresses compared

    A tool for Mac OS X users that uses the similar techniques to ones Silvan tested, is a widget called obfuscatr also available from Apple Downloads.

    obfuscatr 1.1.0 was featured in MacWorld.

  22. could also use php to echo different parts of the email address…this isn’t that sophistocated, as some email spammers could scan the line an put it together….you could put a different number of characters in each echo statement to make it a little more difficult to pick apart.

    echo ('s');
    echo ('h');
    echo('t');echo('o'); echo('o');
  23. @shaun Your above code doesn’t prevent spam in any way. Many echo’s is meaningless — may as well echo out the entire address at once.

  24. liam dilley

    If you were going to use similar and change text with in an element

    window.addEvent('domready', function(){
        $$('breadcrumbs').each(function(el) { 
            el.set('html' + el.get('html').replace('.html','.link')); 

    How do you target the html in this way as this does not seem to work?

  25. tips

    Your site is a refreshing change from the majority of sites I have visited. When I first started visiting web sites I was excited by the potential of the internet as a resource and was very disappointed initially. You have restored my enthusiasm and I thank you for your efforts to share your insights and help the world become a better place.

  26. click

    Nice! We very enjoyed your site .

  27. Release date of obfuscatr version 1.3.0 confirmed to be 1st August 2009.

    New version will feature CSS-obfuscation.

  28. Oren

    @peter: You can add a recursive flag to .replace() look at example 3

  29. chad

    also maybe add this to the beginning of the js function:

  30. chad

    i guess it pays to read instructions :)
    js code:

    $$('.email').each(function(el) { 
    el.set('href','mailto:' + el.get('href').replace('|','@').replace('/','')); 

    html code:


Wrap your code in <pre class="{language}"></pre> tags, link to a GitHub gist, JSFiddle fiddle, or CodePen pen to embed!