47

When placing email addresses on a webpage do you place them as text like this:

joe.somebody@company.com

or use a clever trick to try and fool the email address harvester bots? For example:

HTML Escape Characters:

joe.somebody@company.com

Javascript Decrypter:

function XOR_Crypt(EmailAddress)
{
    Result = new String();
    for (var i = 0; i < EmailAddress.length; i++)
    {
        Result += String.fromCharCode(EmailAddress.charCodeAt(i) ^ 128);
    }
    document.write(Result);
}

XOR_Crypt("êïå®óïíåâïäùÀãïíðáîù®ãïí");

Human Decode:

joe.somebodyNOSPAM@company.com

joe.somebody AT company.com

What do you use or do you even bother?

cllpse
  • 21,396
  • 37
  • 131
  • 170
Gary Willoughby
  • 50,926
  • 41
  • 133
  • 199
  • 17
    incidentally, you should always use example.com for a "sample" domain. See RFC-2606. – nsayer Oct 06 '08 at 21:04
  • 6
    The best solution is **not to share your solution**. Unfortunately this is that sort of question. It's best to find your solution and keep it to yourself. If one gets standardized, spambots will be adapted to overcome it. – Dimitris Jun 12 '14 at 15:28
  • 1
    **The best solution is to combine several of the below solutions**, e.g. first part of email as image, second part `this.href.replace(/x/g,'')`, third part hex encoded, etc. No spam bot, no matter how clever, will try different methods of decoding on different parts of an email address. –  Mar 26 '15 at 09:18
  • Actually, you cannot really fool the bot! Just copy&paste your HTML escape characters to Google and see what I mean. I think the best way is to use a custom JavaScript. – katamayros Apr 03 '15 at 11:12
  • I don't think the comment above about not sharing a solution is valid. You can share a solution and offer suggestions as to how to make it more difficult (e.g. instead of [at] replace with some other combination of characters). This would allow a solution to be shared and still not be automated, as each page would need to be analyzed, which a bot won't do. – Outside the Box Developer Jun 17 '15 at 16:22
  • I think algorithmically obfuscating information _without key exchange_ is akin to deterministically computing random numbers. – greybeard Jun 22 '15 at 07:36

51 Answers51

129

Working with content and attr in CSS:

.cryptedmail:after {
  content: attr(data-name) "@" attr(data-domain) "." attr(data-tld); 
}
<a href="#" class="cryptedmail"
   data-name="info"
   data-domain="example"
   data-tld="org"
   onclick="window.location.href = 'mailto:' + this.dataset.name + '@' + this.dataset.domain + '.' + this.dataset.tld; return false;"></a>

When javascript is disabled, just the click event will not work, email is still displayed.

Another interesting approach (at least without a click event) would be to make use of the right-to-left mark to override the writing direction. more about this: https://en.wikipedia.org/wiki/Right-to-left_mark

cyptus
  • 3,346
  • 3
  • 31
  • 52
  • 4
    Awesome. But append a ";return false" to the onclick-event. This will prevent the ugly addition of # to the browsers URL (by canceling the original href-link) – T4NK3R Apr 19 '17 at 09:43
  • 10
    HOWEVER - I can't manually copy the (visible) mail-address (in either Chrome, Firefox or Edge) ? – T4NK3R Apr 19 '17 at 09:52
  • @T4NK3R yes - it's an pseudo element, so you can't select it. you could implement a link for copy the mail to the clipboard. An workaround for yourself, at least in chrome, would be, to press ctrl+p for printing and select the e-mail in the preview. – cyptus Apr 19 '17 at 13:40
  • I had accessibility concerns looking at this, but a quick research showed that current screen readers do read css generated content. An aria-label attribute that describes what will happen by clicking this link would still improve this, and since the href attribute does not describe the actual link target, a button element might be more appropriate and accessible. Also this might lead to fail this WCAG 2.0 test about "non-decorative content": https://www.w3.org/TR/WCAG20-TECHS/F87.html See also: https://adrianroselli.com/2019/02/f87-css-generated-content-and-wcag-conformance.html – makkabi Feb 24 '20 at 19:15
97

This is the method I used, with a server-side include, e.g. <!--#include file="emailObfuscator.include" --> where emailObfuscator.include contains the following:

<!-- // http://lists.evolt.org/archive/Week-of-Mon-20040202/154813.html -->
<script type="text/javascript">
    function gen_mail_to_link(lhs,rhs,subject) {
        document.write("<a href=\"mailto");
        document.write(":" + lhs + "@");
        document.write(rhs + "?subject=" + subject + "\">" + lhs + "@" + rhs + "<\/a>");
    }
</script>

To include an address, I use JavaScript:

<script type="text/javascript"> 
    gen_mail_to_link('john.doe','example.com','Feedback about your site...');
</script>
<noscript>
  <em>Email address protected by JavaScript. Activate JavaScript to see the email.</em>
</noscript>

Because I have been getting email via Gmail since 2005, spam is pretty much a non-issue. So, I can't speak of how effective this method is. You might want to read this study (although it's old) that produced this graph:

enter image description here

Doomjunky
  • 1,148
  • 17
  • 18
Fuhrmanator
  • 11,459
  • 6
  • 62
  • 111
  • Why do you need server-side include of `emailObfuscator.include`? Wouldn't it be same just as writing it in plain .html? (perhaps it's just an example?) Also why do you use html comments `` inside script? And finally why one of your ` – Templar Jul 21 '14 at 16:13
  • @Templar The SSI isn't necessary, nor does it confuse bots as far as I know. It makes (made) my site modular (don't really use this method anymore). The comment was citing the source of where I found the hack (now a broken link). The change in case is just a fluke. If it confuses bots, all the better, but I doubt it has any effect. – Fuhrmanator Jul 21 '14 at 21:09
  • 4
    A more recent and complete study exploring the same idea: http://www.grall.name/posts/1/antiSpam-emailAddressObfuscation.html – Lucas Cimon Jul 06 '17 at 11:43
90

Have a look at this way, pretty clever and using css.

CSS

span.reverse {
  unicode-bidi: bidi-override;
  direction: rtl;
}

HTML

<span class="reverse">moc.rehtrebttam@retsambew</span>

The CSS above will then override the reading direction and present the text to the user in the correct order.

Hope it helps

Cheers

wittich
  • 2,079
  • 2
  • 27
  • 50
roundcrisis
  • 17,276
  • 14
  • 60
  • 92
  • 61
    It's surely funny. But unfortunately, this is not clickable and won't work for copy/paste, while neglecting any non-CSS browser such as braille readers. – Arjan Jul 05 '09 at 10:09
  • Mhh nice, but once people who write crawlers see it, it becomes useless. – Mau Aug 03 '10 at 09:51
  • 6
    Matching reverse e-mail address with a RegEx is just as easy as matching it non-reversed. Spamming is a billion-dollar business and the spammer's aren't even using their own CPU cycles to scrape the screens. In fact, they have already read this conversation and have adjusted their methods accordingly. Anything computer readable is going to be readable by the bots. Whether it be executed by CSS or JavaScript. – Jani Hyytiäinen Aug 24 '13 at 11:54
  • 3
    @JaniHyytiäinen I disagree. The fact they are not paying for the CPU, does not mean they have unlimited resources. If running a JS interpreter turns out to yield too few addresses for its cost, they'll disable it. – o0'. Feb 23 '15 at 11:32
  • @Lohoris As long as there are spammers willing to pay for new e-mail addresses there will be a poor soul in some 3rd world country willing to code a screen scraping toolbar to pay for medicine for his daughter who'll die without them. As long as there are miserable people in miserable situations and there are stupid people to pay for spammers, it's not about resources. If you knew you'd need some money in 4 weeks or else..., would you be too concerned about optimizing your screen scraping routines? Knowing that everyone has everything on their browsers. Attach to domready and regex away! – Jani Hyytiäinen Feb 24 '15 at 18:22
  • @JaniHyytiäinen I didn't explain myself clearly. Spammers don't have **infinite** power, I hope we agree on that. The more their parser is heavy, the less pages it will be able to parse. So, **it is possible that making it lighter will actually yield more addresses in the same time frame**. _Hope it's clear now._ – o0'. Feb 24 '15 at 18:33
  • 1
    @Lohoris: Google reports average page load time being (2.45s) and average page size (320KB), it gives you an idea how much parsing you can do. While a downloading thread is doing the requests, a parsing thread can do the parsing. Majority of downloading is waiting. Which gives the dl thread the possibility of checking prerequisites before deciding to send it to parser. E.g. rendering page, indexOf('@'), indexOf('mailto:'), etc. The parsing thread would receive only +-200 chars around the match which would allow so complex parsing that it would 'appear' to be infinite in terms of parsing power. – Jani Hyytiäinen Feb 28 '15 at 08:33
  • If you are going to use this method making the element un-selectable can be a good idea. A serious user should have no problem with using his/her hands for typing an email address. http://stackoverflow.com/questions/924916/is-there-a-way-to-make-a-div-unselectable – Ram Aug 26 '16 at 22:23
  • This is great, I made a Vue.js component specifically for this https://gist.github.com/tripflex/d6b995a4141b3e56f6b530cf08ca4aac – sMyles Dec 17 '19 at 19:38
52

Not my idea originally but I can't find the author:

<a href="mailto:coxntact@domainx.com"
    onmouseover="this.href=this.href.replace(/x/g,'');">link</a>

Add as many x's as you like. It works perfectly to read, copy and paste, and can't be read by a bot.

Andy Swift
  • 2,179
  • 3
  • 32
  • 53
  • 2
    Neat! But what about mobile users? – Bodzio Jul 13 '15 at 19:51
  • Mouseovers are also triggered when you touch a link. It should work fine. – Andy Swift Jul 16 '15 at 14:36
  • 4
    Works as long as your address doesn't contain any x's. :-p But, I know, just use a different letter. – Dan Henderson Oct 07 '15 at 19:27
  • 1
    But then If javascript is disabled you are presenting users with nonexisting address that will bounce back loosing you a customer/user. – Xeevis Jan 03 '16 at 19:24
  • 41
    If javascript is disabled, none of my sites works at all ;-) – Andy Swift Jan 13 '16 at 16:25
  • abcdefghijklmonpqrstuvwxyz@0123456789.com - If you use a character like **#** (which cannot be used in a valid email address), this would cut down on some crawlers, however, crawlers may remove invalid characters anyway. You could consider using a string instead of 1 character (ie: 'ZyX441ab'). – NotJay Jul 22 '16 at 15:12
  • Yet another obfuscation technique. However these become all ineffective, since spam crwalers interprete JS by now. – bytecode77 Jan 02 '17 at 06:08
  • @bytecode77 Got some proof about that? Because Interpreting JS and triggering UI events are two different things. And I doubt the latter because how is a crawler supposed to know which event to trigger? – AndyO Sep 11 '18 at 11:32
45

I generally don't bother. I used to be on a mailing list that got several thousand spams every day. Our spam filter (spamassassin) let maybe 1 or 2 a day through. With filters this good, why make it difficult for legitimate people to contact you?

tloach
  • 8,009
  • 1
  • 33
  • 44
  • 2
    So you don't need brakes in a car, because you have an air-bag which protects you? :-D Sorry about that joke, but I think to reduce the worldwide spam you should try at least to make it harder for bots to read the e-mail address. – zypro Dec 06 '18 at 15:08
27

Invent your own crazy email address obfuscation scheme. Doesn't matter what it is, really, as long as it's not too similar to any of the commonly known methods.

The problem is that there really isn't a good solution to this, they're all either relatively simple to bypass, or rather irritating for the user. If any one method becomes prevalent, then someone will find a way around it.

So rather than looking for the One True email address obfuscation technique, come up with your own. Count on the fact that these bot authors don't care enough about your site to sit around writing a thing to bypass your slightly crazy rendering-text-with-css-and-element-borders or your completely bizarre, easily-cracked javascript encryption. It doesn't matter if it's trivial, nobody will bother trying to bypass it just so they can spam you.

Dan
  • 61,568
  • 9
  • 61
  • 78
16

You can protect your email address with reCAPTCHA, they offer a free service so people have to enter a CAPTCHA (Completely Automated Public Turing test to tell Computers and Humans Apart) to see your email: https://www.google.com/recaptcha/admin#mailhide

Soundlink
  • 3,915
  • 2
  • 28
  • 36
GavinCattell
  • 3,863
  • 20
  • 22
  • CAPTCHA is not a 100% reliable solution. See e.g., http://www.blackhat-seo.com/2009/captcha-farms/ – mouviciel Nov 06 '09 at 12:27
  • 8
    Part of the point is to make it convenient to viewers to get email addresses ... how is this "easy"? – Robert K Nov 06 '09 at 12:51
  • i found it easy to hack this but requires minimal human interaction, so imagine thousands of people just solving captchas the whole day. Thats also the reason why it costs money – john Smith Oct 29 '16 at 10:24
16

I've written an encoder (source) that uses all kinds of parsing tricks that I could think of (different kinds of HTML entities, URL encoding, comments, multiline attributes, soft hyphens, non-obvious structure of mailto: URL, etc)

It doesn't stop all harvesters, but OTOH it's completely standards-compliant and transparent to the users.

Another IMHO good approach (which you can use in addition to tricky encoding) is along lines of:

<a href="mailto:userhatestogetspam@example.com" 
   onclick="this.href=this.href.replace(/hatestogetspam/,'')">
Kornel
  • 97,764
  • 37
  • 219
  • 309
  • I like the idea of the second approach, except that when you hover over the link it displays the masked address, so make sure you don't use a swear word for the replacement word ;) – demoncodemonkey Oct 19 '11 at 20:58
16

I think the only foolproof method you can have is creating a Contact Me page that is a form that submits to a script that sends to your email address. That way, your address is never exposed to the public at all. This may be undesirable for some reason, but I think it's a pretty good solution. It often irks me when I'm forced to copy/paste someone's email address from their site to my mail client and send them a message; I'd rather do it right through a form on their site. Also, this approach allows you to have anonymous comments sent to you, etc. Just be sure to protect your form using some kind of anti-bot scheme, such as a captcha. There are plenty of them discussed here on SO.

rmeador
  • 25,504
  • 18
  • 62
  • 103
  • 6
    The only problem with this is that you don't have a copy of the message you sent unless you take the time to copy and paste it somewhere else. Personally I don't mind copy and paste but to each their own. – gvkv Jun 13 '09 at 19:58
  • 6
    As for the sender not having a copy: for many kind of forms on the web I love the option to get a copy myself. However, often such an option allows for abuse for anonymously sending messages to just about anyone... – Arjan Jul 05 '09 at 10:12
  • 12
    This may HIDE your email address, but it wont stop the spam at all, unless you secure your form with a captcha image validation script. – SimonDowdles Aug 03 '10 at 09:33
  • 1
    You can also solve the problem of the sender not having a copy by including an option to send it to them as well. – steinybot Jun 11 '13 at 11:00
  • @SimonDowdles you can use reCAPTCHA for your captcha, but if you're doing that, just use reCAPTCHA to hide your email address – Cole Tobin Feb 18 '15 at 23:52
  • 1
    The option "Send a copy to yourself" - effectively turns the form into a spam-canon, with you as the sender - bad idea! – T4NK3R Apr 19 '17 at 10:39
11

If you have php support, you can do something like this:

<img src="scriptname.php">

And the scriptname.php:

<?php
header("Content-type: image/png");
// Your email address which will be shown in the image
$email    =    "you@yourdomain.com";
$length    =    (strlen($email)*8);
$im = @ImageCreate ($length, 20)
     or die ("Kann keinen neuen GD-Bild-Stream erzeugen");
$background_color = ImageColorAllocate ($im, 255, 255, 255); // White: 255,255,255
$text_color = ImageColorAllocate ($im, 55, 103, 122);
imagestring($im, 3,5,2,$email, $text_color);
imagepng ($im);
?>
mati
  • 5,218
  • 3
  • 32
  • 49
  • 1
    rather than using php you could physically create the image. And as with the css invert you still have the problem of not being clickable and can't be copied unless using a pen :P – Claudiu Mar 26 '15 at 17:17
9

I know my answer won't be liked by many but please consider the points outlined here before thumbing down.

Anything easily machine readable will be easily machine readable by the spammers. Even though their actions seem stupid to us, they're not stupid people. They're innovative and resourceful. They do not just use bots to harvest e-mails, they have a plethora of methods at their disposal and in addition to that, they simply pay for good fresh lists of e-mails. What it means is, that they got thousands of black-hat hackers worldwide to execute their jobs. People ready to code malware that scrape the screens of other peoples' browsers which eventually renders any method you're trying to achieve useless. This thread has already been read by 10+ such people and they're laughing at us. Some of them may be even bored to tears to find out we cannot put up a new challenge to them.

Keep in mind that you're not eventually trying to save your time but the time of others. Because of this, please consider spending some extra time here. There is no easy-to-execute magic bullet that would work. If you work in a company that publishes 100 peoples' e-mails on the site and you can reduce 1 spam e-mail per day per person, we're talking about 36500 spam emails a year. If deleting such e-mail takes 5 seconds on average, we're talking about 50 working hours yearly. Not to mention the reduced amount of annoyance. So, why not spend a few hours on this?

It's not only you and the people who receive the e-mail that consider time an asset. Therefore, you must find a way to obfuscate the e-mail addresses in such way, that it doesn't pay off to crack it. If you use some widely used method to obfuscate the e-mails, it really pays off to crack it. Since as an result, the cracker will get their hands on thousands, if not tens or hundreds of thousands of fresh e-mails. And for them, they will get money.

So, go ahead and code your own method. This is a rare case where reinventing the wheel really pays off. Use a method that is not machine readable and one which will preferably require some user interaction without sacrificing the user experience.

I spent some 20 minutes to code off an example of what I mean. In the example, I used KnockoutJS simply because I like it and I know you won't probably use it yourself. But it's irrelevant anyway. It's a custom solution which is not widely used. Cracking it won't pose a reward for doing it since the method of doing it would only work on a single page in the vast internet.

Here's the fiddle: http://jsfiddle.net/hzaw6/

The below code is not meant to be an example of good code. But just a quick sample of code which is very hard for machine to figure out we even handle e-mails in here. And even if it could be done, it's not gonna pay off to execute in large scale.

And yes, I do know it doesn't work on IE = lte8 because of 'Unable to get property 'attributes' of undefined or null reference' but I simply don't care because it's just a demo of method, not actual implementation, and not intended to be used on production as it is. Feel free to code your own which is cooler, technically more solid etc..

Oh, and never ever ever name something mail or email in html or javascript. It's just way too easy to scrape the DOM and the window object for anything named mail or email and check if it contains something that matches an e-mail. This is why you don't want any variables ever that would contain e-mail in it's full form and this is also why you want user to interact with the page before you assign such variables. If your javascript object model contains any e-mail addresses on DOM ready state, you're exposing them to the spammers.

The HTML:

<div data-bind="foreach: contacts">
    <div class="contact">
        <div>
            <h5 data-bind="text: firstName + ' ' + lastName + ' / ' + department"></h5>
            <ul>
                <li>Phone: <span data-bind="text: phone"></span></li>
                <li><a href="#999" data-bind="click:$root.reveal">E-mail</a> <span data-bind="visible: $root.msgMeToThis() != ''"><input class="merged" data-bind="value: mPrefix" readonly="readonly" /><span data-bind="text: '@' + domain"></span></span></li>
            </ul>
        </div>
    </div>
</div>

The JS

function ViewModel(){
    var self = this;

    self.contacts = ko.observableArray([
        { firstName:'John', mPrefix: 'john.doe', domain: 'domain.com', lastName: 'Doe', department: 'Sales', phone: '+358 12 345 6789' },
        { firstName:'Joe', mPrefix: 'joe.w', domain: 'wonder.com', lastName: 'Wonder', department: 'Time wasting', phone: '+358 98 765 4321' },
        { firstName:'Mike', mPrefix: 'yo', domain: 'rappin.com', lastName: 'Rophone', department: 'Audio', phone: '+358 11 222 3333' }
    ]);
    self.msgMeToThis = ko.observable('');
    self.reveal = function(m, e){
        var name = e.target.attributes.href.value;
        name = name.replace('#', '');
        self.msgMeToThis(name);
    };
}
var viewModel = new ViewModel();
ko.applyBindings(viewModel);
Jani Hyytiäinen
  • 5,293
  • 36
  • 45
8

One of my favorite methods is to obfuscate the email address using php, a classic example is to convert the characters to HEX values like so:

function myobfiscate($emailaddress){
 $email= $emailaddress;                
 $length = strlen($email);                         
 for ($i = 0; $i < $length; $i++){                
 $obfuscatedEmail .= "&#" . ord($email[$i]).";";
 }
 echo $obfuscatedEmail;
}

And then in my markup I'll simply call it as follows:

  <a href="mailto:<?php echo myobfiscate('someone@somewhere.com'); ?>"
title="Email me!"><?php echo myobfiscate('someone@somewhere.com');?> </a>

Then examine your source, you'll be pleasantly surprised!

Krishna Karki
  • 749
  • 12
  • 31
SimonDowdles
  • 2,026
  • 4
  • 24
  • 36
8

You can try to hide characters using html entities in hexa (ex: &#x40 for @). This is convenient solution, as a correct browser will translate it, and you can have a normal link. The drawback is that a bot can translate it theorically, but it's a bit unusual. I use this to protect my e-mail on my blog.

Another solution is to use javascript to assemble part of the address and to decode on-the-fly the address. The drawback is that a javascript-disabled browser won't show your adress.

The most effective solution is to use an image, but it's a pain for the user to have to copy the address by hand.

Your solution is pretty good, as you only add a drawback (writing manually the @) only for user that have javascript disabled. You can also be more secure with :

onclick="this.href='mailto:' + 'admin' + '&#x40;' + 'domain.com'"
ofaurax
  • 1,417
  • 1
  • 20
  • 27
6

I wouldn't bother -- it is fighting the SPAM war at the wrong level. Particularly for company web sites I think it makes things look very unprofessional if you have anything other than the straight text on the page with a mailto hyperlink.

There is so much spam flying around that you need good filtering anyway, and any bot is going end up understanding all the common tricks anyway.

Rob Walker
  • 46,588
  • 15
  • 99
  • 136
  • This thing about a bot understanding the common tricks is wrong. AFAIK, spammers generally don't try any OCR or javascript evaluation, becuase they don't really need to. – PeterAllenWebb Oct 02 '08 at 17:58
  • I agree with your comment about company web sites not having anything other than a straight mailto: link, but those links should always go to role addresses like "sales@" or "info@" or what not. Those addresses will be less valuable to spammers anyway. Things are different for personal pages. – nsayer Oct 02 '08 at 18:10
6

HTML:

<a href="#" class="--mailto--john--domain--com-- other classes goes here" />

JavaScript, using jQuery:

// match all a-elements with "--mailto--" somehere in the class property
$("a[class*='--mailto--']").each(function ()
{
    /*
    for each of those elements use a regular expression to pull
    out the data you need to construct a valid e-mail adress
    */
    var validEmailAdress = this.className.match();

    $(this).click(function ()
    {
        window.location = validEmailAdress;
    });
});
cllpse
  • 21,396
  • 37
  • 131
  • 170
5

Spambots won't interpret this, because it is a lesser-known method :)

First, define the css:

email:before {
    content: "admin";
}

email:after {
    content: "@example.com";
}

Now, wherever you want to display your email, simply insert the following HTML:

<div id="email"></div>

And tada!

Aaron Esau
  • 1,083
  • 3
  • 15
  • 31
4

I use a very simple combination of CSS and jQuery which displays the email address correctly to the user and also works when the anchor is clicked or hovered:

HTML:

<a href="mailto:me@example.spam" id="lnkMail">moc.elpmaxe@em</a>

CSS:

#lnkMail {
    unicode-bidi: bidi-override;
    direction: rtl;
}

jQuery:

$('#lnkMail').hover(function(){
    // here you can use whatever replace you want
    var newHref = $(this).attr('href').replace('spam', 'com');
    $(this).attr('href', newHref);
});

Here is a working example.

Sergiu
  • 1,397
  • 1
  • 18
  • 33
  • will it show the correct value of href in the browser status bar when the link is hovered over? – Nik O'Lai Jun 18 '15 at 18:51
  • Yes, it does show the correct value of href when the link is hovered. That's why the jQuery method .hover needs to be implemented. – Sergiu Jun 22 '15 at 06:57
  • Unfortunately, no, it does not show the correct value of href, at least, when you hover over the link the first time (it is me@example.spam). On the second hover everything was ok. Test it with your own link. – Nik O'Lai Jul 03 '15 at 14:52
  • 1
    It's working in Chrome and IE. Seems like only on Firefox, on first hover, the status bar is not updated. I'll try to find a solution for Firefox. – Sergiu Jul 06 '15 at 06:53
3

!- Adding this for reference, don't know how outdated the information might be, but it tells about a few simple solutions that don't require the use of any scripting

After searching for this myself i came across this page but also these pages:

http://nadeausoftware.com/articles/2007/05/stop_spammer_email_harvesters_obfuscating_email_addresses

try reversing the emailadress

Example plain HTML:

<bdo dir="rtl">moc.elpmaxe@nosrep</bdo>
Result : person@example.com

The same effect using CSS

CSS:
.reverse { unicode-bidi:bidi-override; direction:rtl; }
HTML:
<span class="reverse">moc.elpmaxe@nosrep</span>
Result : person@example.com

Combining this with any of earlier mentioned methods may even make it more effective

3

I don't bother. You'll only annoy sophisticated users and confuse unsophisticated users. As others have said, Gmail provides very effective spam filters for a personal/small business domain, and corporate filters are generally also very good.

Phil
  • 31
  • 2
3

A response of mine on a similar question:

I use a very simple combination of CSS and jQuery which displays the email address correctly to the user and also works when the anchor is clicked:

HTML:

<a href="mailto:me@example.spam" id="lnkMail">moc.elpmaxe@em</a>

CSS:

#lnkMail {
  unicode-bidi: bidi-override;
  direction: rtl;
}

jQuery:

$('#lnkMail').hover(function(){
  // here you can use whatever replace you want
  var newHref = $(this).attr('href').replace('spam', 'com');
  $(this).attr('href', newHref);
});

Here is a working example.

Community
  • 1
  • 1
Sergiu
  • 1,397
  • 1
  • 18
  • 33
3

Here is my working version:


Create somewhere a container with a fallback text:

<div id="knock_knock">Activate JavaScript, please.</div>

And add at the bottom of the DOM (w.r.t. the rendering) the following snippet:

<script>
  (function(d,id,lhs,rhs){
    d.getElementById(id).innerHTML = "<a rel=\"nofollow\" href=\"mailto"+":"+lhs+"@"+rhs+"\">"+"Mail"+"<\/a>";
  })(window.document, "knock_knock", "your.name", "example.com");
</script>

It adds the generated hyperlink to the specified container:

<div id="knock_knock"><a rel="nofollow" href="your.name@example.com">Mail</a></div>

In addition here is a minified version:

<script>(function(d,i,l,r){d.getElementById(i).innerHTML="<a rel=\"nofollow\" href=\"mailto"+":"+l+"@"+r+"\">"+"Mail"+"<\/a>";})(window.document,"knock_knock","your.name","example.com");</script>
Darius
  • 10,762
  • 2
  • 29
  • 50
3

The best method hiding email addresses is only good until bot programmer discover this "encoding" and implement a decryption algorithm.

The JavaScript option won't work long, because there are a lot of crawler interpreting JavaScript.

There's no answer, imho.

guerda
  • 23,388
  • 27
  • 97
  • 146
  • Are there crawlers interpreting JavaScript? My one JavaScript encoding method has seemed to work well for me over the past few years--my spam rate has been a fairly steady ~4/week, so I haven't worried about other people's addresses that I entrusted to this method. Should I? – Kev Jan 27 '09 at 13:46
  • For sure, it may exclude lots of crawlers, but me, if I created an address crawler, I would implement a JavaScript lib :) – guerda Jan 28 '09 at 14:17
  • more effort than you might think –  Jun 13 '09 at 12:03
  • Google is crawling through some JS now. – Alister Bulman Jun 13 '09 at 12:38
3

One easy solution is to use HTML entities instead of actual characters. For example, the "me@example.com" will be converted into :

<a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#109;&#101;&#64;&#101;&#120;&#97;&#109;&#112;&#108;&#101;&#46;&#99;&#111;&#109;">email me</A>
Kevin Fegan
  • 1,292
  • 1
  • 16
  • 29
Romain Linsolas
  • 79,475
  • 49
  • 202
  • 273
  • Could you please tip me about a site which has a service for quick conversion such you did. – abatishchev Jan 27 '09 at 12:31
  • 2
    Try http://www.google.se/search?q=HTML+entities+converter that should keep you busy ;) – grapefrukt Jan 27 '09 at 12:34
  • 1
    Google can find you lots of page for that. One example: http://hp.vector.co.jp/authors/VA022023/javascript/make_html_entity-en.htm – Romain Linsolas Jan 27 '09 at 12:36
  • 4
    But couldn't a bot just as easily regex that as well? – gargantuan Jun 13 '09 at 12:04
  • 20
    Ouch, the me@stack... example should better be written as me@example.com, me@example.net or me@example.org -- those are the only domain names non-owners should use in examples! – Arjan Jun 13 '09 at 12:29
  • 4
    Not so effective, according to http://techblog.tilllate.com/2008/07/20/ten-methods-to-obfuscate-e-mail-addresses-compared/ – Fuhrmanator Sep 16 '12 at 15:09
3

A neat trick is to have a div with the word Contact and reveal the email address only when the user moves the mouse over it. E-mail can be Base64-encoded for extra protection.

Here's how:

<div id="contacts">Contacts</div>

<script>
  document.querySelector("#contacts").addEventListener("mouseover", (event) => {
    // Base64-encode your email and provide it as argument to atob()
    event.target.textContent = atob('aW5mb0BjbGV2ZXJpbmcuZWU=')
  });
</script>
mrts
  • 16,697
  • 8
  • 89
  • 72
2

The only safest way is of course not to put the email address onto web page in the first place.

gabr
  • 26,580
  • 9
  • 75
  • 141
  • Yes. If you want to _really_hide_ your email address, put a captcha-protected form on the webpage which sends email to you in the background (without displaying the address in the GUI, of course). – gabr Oct 04 '08 at 14:41
  • 3
    Very true, except that in some countries it is required by law. Germany is an example. – Ludwig Weinzierl May 11 '09 at 21:56
2

Use a contact form instead. Put all of your email addresses into a database and create an HTML form (subject, body, from ...) that submits the contents of the email that the user fills out in the form (along with an id or name that is used to lookup that person's email address in your database) to a server side script that then sends an email to the specified person. At no time is the email address exposed. You will probably want to implement some form of CAPTCHA to deter spambots as well.

Bill
  • 4,323
  • 8
  • 28
  • 32
2

There are probably bots that recognize the [at] and other disguises as @ symbol. So this is not a really effective method.

Sure you could use some encodings like URL encode or HTML character references (or both):

// PHP example
// encodes every character using URL encoding (%hh)
function foo($str) {
    $retVal = '';
    $length = strlen($str);
    for ($i=0; $i<$length; $i++) $retVal.=sprintf('%%%X', ord($str[$i]));
    return $retVal;
}
// encodes every character into HTML character references (&#xhh;)
function bar($str) {
    $retVal = '';
    $length = strlen($str);
    for ($i=0; $i<$length; $i++) $retVal.=sprintf('&#x%X;', ord($str[$i]));
    return $retVal;
}

$email = 'user@example.com';
echo '<a href="'.bar('mailto:?to=' . foo(','.$email.'')).'">mail me</a>';

// output
// <a href="&#x6D;&#x61;&#x69;&#x6C;&#x74;&#x6F;&#x3A;&#x3F;&#x74;&#x6F;&#x3D;&#x25;&#x32;&#x43;&#x25;&#x37;&#x35;&#x25;&#x37;&#x33;&#x25;&#x36;&#x35;&#x25;&#x37;&#x32;&#x25;&#x34;&#x30;&#x25;&#x36;&#x35;&#x25;&#x37;&#x38;&#x25;&#x36;&#x31;&#x25;&#x36;&#x44;&#x25;&#x37;&#x30;&#x25;&#x36;&#x43;&#x25;&#x36;&#x35;&#x25;&#x32;&#x45;&#x25;&#x36;&#x33;&#x25;&#x36;&#x46;&#x25;&#x36;&#x44;">mail me</a>

But as it is legal to use them, every browser/e-mail client should handle these encodings too.

Gumbo
  • 643,351
  • 109
  • 780
  • 844
2

One possibility would be to use isTrusted property (Javascript).

The isTrusted read-only property of the Event interface is a Boolean that is true when the event was generated by a user action, and false when the event was created or modified by a script or dispatched via EventTarget.dispatchEvent().

eg in your case:

getEmail() {
  if (event.isTrusted) {
    /* The event is trusted */
    return 'your-email@domain.com';
  } else {
    /* The event is not trusted */
    return 'chuck@norris.com';
  }
}

⚠ IE isn't compatible !

Read more from doc: https://developer.mozilla.org/en-US/docs/Web/API/Event/isTrusted

Emeric
  • 6,315
  • 2
  • 41
  • 54
1

after using so many techniques i found an easy way and very friendly, the bots search for @ Símbolo and recently they search for [at] ant it's variation so i use 2 techniques

  1. i write my email on an image like the domaintolls use and it works perfectly or
  2. to replace the Símbolo (@) with an image of it like

@ replace and the image alt will be alt="@" so the bot will find an image and any human will see it as a normal address so if he copy it he will copy the email and the job is don so the code will be

<p>myname<img src="http://www.traidnt.net/vb/images/mail2.gif" width="11" height="9" alt="@" />domain.com</p>
1

what about HTML_CHARACTER?:

joe&#064;mail.com

outputs

joe@mail.com
T.Todua
  • 53,146
  • 19
  • 236
  • 237
  • 1
    The email address isn't clickable this way and the placement of the @ symbol isn't going to be bulletproof, in that it won't always look the same as it does if it was placed inline. – Brent O'Connor Aug 08 '13 at 23:26
1

I make mine whateverDOC@whatever.com and then next to it I write "Remove the capital letters"

Joe Phillips
  • 49,743
  • 32
  • 103
  • 159
1

Another, possibly unique, technique might be to use multiple images and a few plain-text letters to display the address. That might confuse the bots.

Joe Phillips
  • 49,743
  • 32
  • 103
  • 159
1

Gmail which is free has an awesome spam filter.

If you don't want to use Gmail directly you could send the email to gmail and use gmail forwarding to send it back to you after it has gone through their spam filter.

In a more complex situation, when you need to show a @business.com address you could show the public@business.com and have all this mail forwarded to a gmail account who then forwards it back to the real@business.com

I guess it's not a direct solution to your question but it might help. Gmail being free and having such a good SPAM filter makes using it a very wise choice IMHO.

I receive about 100 spam per day in my gmail account but I can't remember the last time one of them got to my inbox.

To sum up, use a good spam filter whether Gmail or another. Having the user retype or modify the email address that is shown is like using DRM to protect against piracy. Putting the burden on the "good" guy shouldn't be the way to go about doing anything. :)

1

For your own email address I'd recommend not worrying about it too much. If you have a need to make your email address available to thousands of users then I would recommend either using a gmail address (vanilla or via google apps) or using a high quality spam filter.

However, when displaying other users email addresses on your website I think some level of due diligence is required. Luckily, a blogger named Silvan Mühlemann has done all the difficult work for you. He tested out different methods of obfuscation over a period of 1.5 years and determined the best ones, most of them involve css or javascript tricks that allow the address to be presented correctly in the browser but will confuse automated scrapers.

Wedge
  • 19,513
  • 7
  • 48
  • 71
1

And my function. I've created it looking at answers placed in this topic.

 function antiboteEmail($email)
 {
        $html = '';

        $email = strrev($email);
        $randId = rand(1, 500);

        $html .= '<span id="addr-'.$randId.'" class="addr">[turn javascript on to see the e-mail]</span>';
        $html .= <<<EOD
                <script>
                $(document).ready(function(){

                    var addr = "$email";
                    addr = addr.split("").reverse().join("");
                    $("#addr-$randId").html("<a href=\"mailto:" + addr + "\">" + addr + " </a>");
                });
                </script>
EOD;

        return $html;
    }

It uses two methods: right to left dir and javascript putting.

webrama.pl
  • 1,870
  • 1
  • 23
  • 36
1

Option 1 : Split email address into multiple parts and create an array in JavaScript out of these parts. Next join these parts in the correct order and use the .innerHTML property to add the email address to the web page.

 <span id="email">  </span>   // blank tag

 <script>
 var parts = ["info", "XXXXabc", "com", "&#46;", "&#64;"];
 var email = parts[0] + parts[4] + parts[1] + parts[3] + parts[2];
 document.getElementById("email").innerHTML=email; 
 </script>

Option 2 : Use image instead of email text

Image creator website from text : http://www.chxo.com/labelgen/

Option 3 : We can use AT instead of "@" and DOT instead of " . "

i.e :

 info(AT)XXXabc(DOT)com 
saun4frsh
  • 383
  • 1
  • 4
  • 21
  • 1
    I think option 1 is not a good option. A parser running alongside a bot could easily figure out the value of the innerHTML, and option 3 is probably not so good either because a smart bot could figure it out. I think option 2 is the best. – John Sonderson Feb 05 '15 at 21:32
1

I don't like JavaScript and HTML to be mixed, that's why I use this solution. It works fine for me, for now.

Idea: you could make it more complicated by providing encrypted information in the data-attributes and decrypt it within the JS. This is simply done by replacing letters or just reversing them.

HTML:

<span class="generate-email" data-part1="john" data-part2="gmail" data-part3="com">placeholder</span>

JS:

$(function() {
    $('.generate-email').each(function() {
        var that = $(this);
        that.html(
            that.data('part1') + '@' + that.data('part2') + '.' + that.data('part3')
        );
    });  
});

Try it: http://jsfiddle.net/x6g9L817/

Mr. B.
  • 8,041
  • 14
  • 67
  • 117
1

Does it work if I right-click on the link and choose "copy URL"? If not, it's very much not an ideal situation (I very seldom click on a mailto link, preferring to copy the email address and paste it into my mail application or wherever else I need it at a specific point in time).

I used to be fairly paranoid protecting my mail address on-line (UseNet, web and the like), but these days I suspect more "possible targets for spam" are actually generated matching local-parts to domains programmatically. I base this on having, on occasion, gone through my mail server logs. There tends to be quite a few delivery attempts to non-existing addresses (including truncated versions of spam-bait I dangled on UseNet back in the late 90s, when address-scraping was very prevalent).

Vatine
  • 20,782
  • 4
  • 54
  • 70
1

First I would make sure the email address only shows when you have javascript enabled. This way, there is no plain text that can be read without javascript.

Secondly, A way of implementing a safe feature is by staying away from the <button> tag. This tag needs a text insert between the tags, which makes it computer-readable. Instead try the <input type="button"> with a javascript handler for an onClick. Then use all of the techniques mentioned by otherse to implement a safe email notation.

One other option is to have a button with "Click to see emailaddress". Once clicked this changes into a coded email (the characters in HTML codes). On another click this redirects to the 'mailto:email' function

An uncoded version of the last idea, with selectable and non-selectable email addresses:

<html>
<body>
<script type="text/javascript">
      e1="@domain";
      e2="me";
      e3=".extension";
email_link="mailto:"+e2+e1+e3;
</script>
<input type="text" onClick="this.onClick=window.open(email_link);" value="Click for mail"/>
<input type="text" onClick="this.value=email;" value="Click for mail-address"/>
<input type="button" onClick="this.onClick=window.open(email_link);" value="Click for mail"/>
<input type="button" onClick="this.value=email;" value="Click for mail-address"/>
</body></html>

See if this is something you would want and combine it with others' ideas. You can never be too sure.

Kevin Fegan
  • 1,292
  • 1
  • 16
  • 29
xaddict
  • 1,302
  • 3
  • 19
  • 38
0

I like ofaurax's answer best but I would modify to this for a little more hidden email:

onclick="p1='admin'; p2='domain.com'; this.href='mailto:' + p1 + '& #x40;' + p2"
abatishchev
  • 98,240
  • 88
  • 296
  • 433
Donny
  • 9
  • 1
0

A script that saves email addresses to png files would be a secure solution ( if you have enough space and you are allowed to embed images in your page )

Prog
  • 249
  • 1
  • 9
  • That (along with most of the answers here) would prevent people from copying and pasting the content. – moopet Nov 23 '16 at 17:14
0

This is what we use (VB.NET):

Dim rxEmailLink As New Regex("<a\b[^>]*mailto:\b[^>]*>(.*?)</a>")
Dim m As Match = rxEmailLink.Match(Html)
While m.Success
    Dim strEntireLinkOrig As String = m.Value
    Dim strEntireLink As String = strEntireLinkOrig
    strEntireLink = strEntireLink.Replace("'", """") ' replace any single quotes with double quotes to make sure the javascript is well formed
    Dim rxLink As New Regex("(<a\b[^>]*mailto:)([\w.\-_^@]*@[\w.\-_^@]*)(\b[^>]*?)>(.*?)</a>")
    Dim rxLinkMatch As Match = rxLink.Match(strEntireLink)
    Dim strReplace As String = String.Format("<script language=""JavaScript"">document.write('{0}{1}{2}>{3}</a>');</script>", _
                RandomlyChopStringJS(rxLinkMatch.Groups(1).ToString), _
                ConvertToAsciiHex(rxLinkMatch.Groups(2).ToString), _
                rxLinkMatch.Groups(3), _
                ConvertToHtmlEntites(rxLinkMatch.Groups(4).ToString))
    Result = Result.Replace(strEntireLinkOrig, strReplace)
    m = m.NextMatch()
End While

and

    Public Function RandomlyChopStringJS(ByVal s As String) As String
        Dim intChop As Integer = Int(6 * Rnd()) + 1
        Dim intCount As Integer = 0
        RandomlyChopStringJS = ""
        If Not s Is Nothing AndAlso Len(s) > 0 Then
            For Each c As Char In s.ToCharArray()
                If intCount = intChop Then
                    RandomlyChopStringJS &= "'+'"
                    intChop = Int(6 * Rnd()) + 1
                    intCount = 0
                End If
                RandomlyChopStringJS &= c
                intCount += 1
            Next
        End If
    End Function

We override Render and run the outgoing HTML through this before it goes out the door. This renders email addresses that render normally to a browser, but look like this in the source:

<script language="JavaScript">document.write('<a '+'clas'+'s='+'"Mail'+'Link'+'" hr'+'ef'+'="ma'+'ilto:%69%6E%66%6F%40%62%69%63%75%73%61%2E%6F%72%67">&#105;&#110;&#102;&#111;&#64;&#98;&#105;&#99;&#117;&#115;&#97;&#46;&#111;&#114;&#103;</a>');</script>

Obviously not foolproof, but hopefully cuts down on a certain amount of harvesting without making things hard for the visitor.

Herb Caudill
  • 50,043
  • 39
  • 124
  • 173
0

It depends on what exactly your needs are. For most sites with which I work, I have found it far more useful to put in a "contact me/us" form which sends an email from the system to whomever needs to be contacted. I know that this isn't exactly the solution that you are seeking but it does completely protect against harvesting and so far I have never seen spam sent through a form like that. It will happen but it is very rare and you are never harvested.

This also gives you a chance to log the messages before sending them giving you an extra level of protection against losing a contact, if you so desire.

0

I just have to provide an another answer. I just came up with something fun to play with.

I found out that in many common character tables, the letters @ and a-z reappear more than once. You can map the original characters to the new mappings and make it harder for spam bots to figure out what the e-mail is.

If you loop through the string, and get the character code of a letter, then add 65248 to it and build a html entity based on the number, you come up with a human readable e-mail address.

var str = 'john.doe@email.com';
str = str.toLowerCase().replace(/[\.@a-z]/gi, function(match, position, str){
    var num = str.charCodeAt(position);
    return ('&#' + (num + 65248) + ';');
});

Here is a working fiddle: http://jsfiddle.net/EhtSC/8/

You can improve this approach by creating a more complete set of mappings between characters that look the same. But if you copy/paste the e-mail to notepad, for example, you get a lot of boxes.

To overcome some of the user experience issues, I created the e-mail as link. When you click it, it remaps the characters back to their originals.

To improve this, you can create more complex character mappings if you like. If you can find several characters that can be used for example in the place of 'a' why not randomly mapping to those.

Probably not the most secure approach ever but I really had fun playing around with it :D

Jani Hyytiäinen
  • 5,293
  • 36
  • 45
0

Option 1 : Split email address into multiple parts and create an array in JavaScript out of these parts. Next join these parts in the correct order and use the .innerHTML property to add the email address to the web page.

 <span id="email">  </span>   // blank tag

 <script>
 var parts = ["info", "XXXXabc", "com", "&#46;", "&#64;"];
 var email = parts[0] + parts[4] + parts[1] + parts[3] + parts[2];
 document.getElementById("email").innerHTML=email; 
 </script>

Option 2 : Use image instead of email text

Image creator website from text : http://www.chxo.com/labelgen/

Option 3 : We can use AT instead of "@" and DOT instead of " . "

i.e :

 info(AT)XXXabc(DOT)com 
saun4frsh
  • 383
  • 1
  • 4
  • 21
0

Spam bots will have their own Javascript and CSS engines over time, so I think you shouldn't look in this direction.

ychaouche
  • 4,922
  • 2
  • 44
  • 52
0

I just coded the following. Don't know if it's good but it's better then just writing the email in plain text. Many robots will be fooled but not all of them.

<script type="text/javascript">
    $(function () {
        setTimeout(function () {
            var m = ['com', '.', 'domain', '@', 'info', ':', 'mailto'].reverse().join('');

            /* Set the contact email url for each "contact us" links.*/
            $('.contactUsLink').prop("href", m);
        }, 200);
    });
</script>

If the robot solve this then there's no need to add more "simple logic" code like "if (1 == 1 ? '@' : '')" or adding the array elements in another order since the robot just evals the code anyway.

Sasse
  • 1,108
  • 10
  • 14
0

Font-awesome works!

<link rel="stylesheet" href="path/to/font-awesome/css/font-awesome.min.css">

<p>myemail<i class="fa fa-at" aria-hidden="true"></i>mydomain.com</p>

http://fontawesome.io/

Ogun Adebali
  • 1
  • 1
  • 2
0

Hidden Base64 solution.

I think it does not matter if you put an email address in a :before/:after pseudo or split it in reverse written data attributes ... Spambots are clever and analyze parsed webpages.

This solution is interactive. The user has to click "show" to get an base64 decoded email address which can be copied and/or is clickable.

// search for [data-b64mail] attributes
document.querySelectorAll('[data-b64mail]').forEach(el => {

  // set "show" link
  el.innerHTML = '<span style="text-decoration:underline;cursor:pointer">show</span>';
    
  // set click event to all elements
  el.addEventListener('click', function (e) {
    let cT = e.currentTarget;

    // show address
    cT.innerHTML = atob(cT.getAttribute('data-b64mail'));
    
    // set mailto on a tags
    if (cT.tagName === 'A')
      cT.setAttribute('href', 'mailto:' + atob(cT.getAttribute('data-b64mail')));

  });

});

// get base64 encoded string
console.log(btoa('mail@example.org'));
<p>E-mail (span): <span data-b64mail="bWFpbEBleGFtcGxlLm9yZw=="></span></p>

<p>E-mail (link): <a href="#" data-b64mail="bWFpbEBleGFtcGxlLm9yZw=="></a></p>
tom
  • 9,550
  • 6
  • 30
  • 49
0

Here is a simple jquery solution to this problem:

<script type="text/javascript">
$(document).ready(function() {
    str1="mailto:";
    str2="info";
    str3="@test.com";
    $("#email_a").attr("href", str1+str2+str3);

});
</script>

<a href="#" id="email_a"><img src="sample.png"/></a>
Haluk
  • 2,091
  • 2
  • 27
  • 35
-1

Another option, I perefer font awesome icons

Fa implementation:

<link rel="stylesheet" href="path/to/font-awesome/css/font-awesome.min.css">

Mail Address:

<a href="mailto:info@uploadimage.club"><span class="label">info<i class="fa fa-at"></i>uploadimage.club</span></a>
Project Mayhem
  • 439
  • 5
  • 12