Email obfuscation: What works in 2025?

Last updated:
July 19, 2025

Here are some of the best techniques for keeping email addresses hidden from spammers—along with the statistics on how likely they are to be broken.

1 Plain text

These techniques protect an email address written out in plain text (e.g. “email@example.com”).

Ideally, you should be using multiple techniques in combination, by splitting the email address into segments, where each segment is protected by a different technique.

1.1 No protection

Blocked 0% of 42 spammers
HTML
aa@email.spencermortensen.com
Browser
aa@email.spencermortensen.com

1.2 HTML Entities

Blocked 74% of 42 spammers
HTML
ab@email.spencermortensen.com
Browser
ab@email.spencermortensen.com

HTML entities are often decoded automatically by server-side libraries, which means that even the most basic harvesters can get your email addresses without any special effort. This technique is essentially worthless.

1.3 HTML Comments

Blocked 90% of 42 spammers
HTML
ac@email.spencermortensen<!--.example-->.com
Browser
ac@email.spencermortensen.com

This will stop only the most basic harvesters that struggle with HTML tags. It offers minimal protection.

1.4 HTML SVG

Blocked 100% of 38 spammers
HTML
<object class="email" width="130" height="24" data="email.svg" type="image/svg+xml"></object>
SVG: email.svg
<svg viewBox="0 0 130 24" xmlns="http://www.w3.org/2000/svg"> <style> @import url('https://fonts.googleapis.com/css2?family=Indie+Flower&amp;display=swap'); text { dominant-baseline: middle; fill: #000; font-family: 'Indie Flower'; font-size: 16px; text-anchor: middle; } </style> <text x="50%" y="50%">email@example.com</text> </svg>
CSS
object.email { height: 2em; margin: -1em 0; vertical-align: middle; }
Browser

Inspiration: rouninmedia.github.io

This hides the email address in an unusual place where most harvesters won’t think to look. However, the email address is stored there in plain text.

This technique is accessible to all users, including those who depend on a screen reader. But you must use an object element for this to work: an img element would give you an image that is non-interactive, and inline SVG would put the email address in the source code where harvesters would find it easily.

The “width” and the “height” attributes help prevent layout shifts while the page is loading. Because the dimensions depend on the font, the SVG file has to explicitly specify a web font to prevent rendering issues.

1.5 CSS Display none

Blocked 100% of 42 spammers
HTML
<div class="email">ad@<span>email.</span>spencermortensen.<span>example.</span>com</div>
CSS
div.email > span:nth-child(2) { display: none; }
Browser
ad@email.spencermortensen.example.com

Most harvesters are unable to apply style rules, so this is one of the absolute best techniques. Be sure to vary the decoy tags so the harvester won’t know which parts to omit.

This is fully accessible to everyone, including those who depend on a screen reader. But you must use “display: none” to hide the text: if you use any visual-only technique (such as shrinking the font size, or repositioning the text off screen), then you’ll break accessibility.

1.6 JS Concatenation

Blocked 100% of 38 spammers
HTML
<script>document.write('a'+'i'+'@'+'e'+'m'+'a'+'i'+'l'+'.'+'s'+'p'+'e'+'n'+'c'+'e'+'r'+'m'+'o'+'r'+'t'+'e'+'n'+'s'+'e'+'n'+'.'+'c'+'o'+'m');</script>
Browser

This is convenient because it has no external dependencies, and yet still manages to block most harvesters. However, the full email address appears directly in the HTML source code, so this technique cannot be considered safe.

1.7 JS Rot18

Blocked 100% of 38 spammers
HTML
<span class="email">nw@rznvy.fcraprezbegrafra.pbz</span>
HTML
<head> <script src="text-rot18.js" defer></script> </head>
Browser
nw@rznvy.fcraprezbegrafra.pbz

This technique can be undone by basic harvesters that don’t interpret JavaScript. At the very least, you should rotate your letters by something other than 13, and rotate your numbers by something other than 5.

1.8 JS Conversion

Blocked 100% of 37 spammers
HTML
<span id="text-conversion">zibby example com</span>
HTML
<head> <script src="text-conversion.js" defer></script> </head>
Browser
zibby example com

In this technique, the HTML source code contains gibberish, and you write a custom function that converts the gibberish into a working email address.

Most harvesters can only access the HTML source code—and the source code contains nothing of value. The only practical way to restore the email address is to run your custom conversion function in a web client with DOM and JavaScript support. This is not possible for most harvesters.

You can write a custom function for each email address, or you can write a single function and apply it to all of the email addresses on the page.

Despite being frighteningly simple, this is expected to be one of the very best techniques.

1.9 JS AES encryption

Blocked 97% of 37 spammers
HTML
<span class="email">Kreuz2xa6xB8Fpjaa0lFgACNLO6n_Auu1CGjcG8z_Ec</span>
HTML
<head> <script src="text-aes.js" defer></script> </head>
Browser
Kreuz2xa6xB8Fpjaa0lFgACNLO6n_Auu1CGjcG8z_Ec

This technique uses AES 256 to encrypt the email address. (AES is the only publicly-available cipher approved by the NSA for top secret information.) The email address cannot be recovered without the JavaScript file—which most harvesters cannot access or run. This implementation uses the browser’s own built-in cryptography library, so it will not run outside of the browser, even in JavaScript-capable environments.

The cryptography library, SubtleCrypto, is only available in secure contexts (such as over https or on localhost)—which could be a blocker if you’re using http. You must upgrade to https before you can use this technique!

1.10 JS User interaction

Blocked 100% of 37 spammers
HTML
<span id="text-interaction">whose baby example com</span>
HTML
<head> <script src="text-interaction.js" defer></script> </head>
Browser
whose baby example com

This technique keeps the email address hidden until the user interacts with the page; only then is the email address revealed. This raises the bar for harvesters: they not only need to run a full web client, they also need to interact with it.

This technique can be used to trigger other techniques.

1.11 HTML Symbol substitution

Blocked 86% of 42 spammers
HTML
ag AT email DOT spencermortensen DOT com
Browser
ag AT email DOT spencermortensen DOT com

This technique is well known, and easily reversible, so it cannot be considered safe.

Breaks usability. This forces the user to undo every substitution before they can send their email.

1.12 HTML Instructions

Blocked 100% of 38 spammers
HTML
au.fluff@email.spencermortensen.com (remove the “.fluff” before writing to me)
Browser
au.fluff@email.spencermortensen.com
(remove the “.fluff” before writing to me)

In general, only a human or an AI can break this. It’s mainly useful for when you need to publish your email address on an untrusted site.

This is at minimum inconvenient for your users, and may prevent them from reaching you at all.

Breaks usability. The user has to understand and follow the instructions perfectly, or they will be unable to reach you.

1.13 HTML Image

Blocked 100% of 42 spammers
HTML
<img src="email.jpg" width="216" height="18" alt="email address">
Browser
email

This is inconvenient or inaccessible for every one of your users.

Breaks usability. Sighted users are forced to type out the full email address by hand. The remaining users have no way to reach you.

1.14 CSS Content

Blocked 100% of 42 spammers
HTML
<span class="email" data-user="af" data-domain="email.spencermortensen.com"></span>
CSS
span.email::after { content: attr(data-user) '@' attr(data-domain); }
Browser

This breaks basic usability (e.g. the text can be seen, but not copied), so it is worthless.

It is possible for harvesters to recover the full email address from the HTML alone, without interpreting the CSS, so this cannot be considered safe.

Breaks usability. The email address can be seen, but not selected. This is very frustrating! Eventually, the user is forced to give up or type out the full email address by hand.

1.15 CSS Text direction

Blocked 100% of 42 spammers
HTML
<span class="email">moc.nesnetromrecneps.liame@ea</span>
CSS
span.email { unicode-bidi: bidi-override; direction: rtl; }
Browser
moc.nesnetromrecneps.liame@ea

This technique breaks usability, and can be undone by basic harvesters that don’t interpret CSS, so it is useless.

Breaks usability. The email address can be copied, but the text is reversed. Eventually, the user is forced to give up or type out the full email address by hand.

These techniques protect a clickable link that will open the user’s mail client (e.g. email). Note that only the href “mailto:” attribute is protected. If the link text also contains the email address, then the email address is additionally exposed as plain text, and you’ll need to layer on at least one of the plain-text obfuscation techniques.

Blocked 0% of 32 spammers
HTML
<a href="mailto:am@email.spencermortensen.com">email</a>
Browser
email
Blocked 97% of 32 spammers
HTML
<a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#97;&#110;&#64;&#101;&#109;&#97;&#105;&#108;&#46;&#115;&#112;&#101;&#110;&#99;&#101;&#114;&#109;&#111;&#114;&#116;&#101;&#110;&#115;&#101;&#110;&#46;&#99;&#111;&#109;">email</a>
Browser
email

HTML entities are often decoded automatically by server-side libraries, which means that even the most basic harvesters can get your email addresses without any special effort. This technique is essentially worthless.

Blocked 78% of 32 spammers
HTML
<a href="mailto:%61%6f%40%65%6d%61%69%6c%2e%73%70%65%6e%63%65%72%6d%6f%72%74%65%6e%73%65%6e%2e%63%6f%6d">email</a>
Browser
email

Server-side libraries make it trivial to undo URL encoding, so this technique is essentially worthless.

Blocked 100% of 32 spammers
HTML
<a rel="nofollow, noindex" href="email/">email</a>
.htaccess
RewriteEngine On RewriteRule ^email/$ 'mailto:email@example.com' [R=302,L]
.htaccess
RewriteEngine On RewriteRule ^email/$ 'mailto:email@example.com?subject=Hi' [R=302,QSA,L]
Browser
email

This technique turns a “mailto:” link into a regular link, without breaking its mail capability, and hides it among the other links on the page.

If you’re planning to fill out any of the fields of the email, then you should use the second form of the “.htaccess” file (with the QSA flag included) to ensure that the query string is preserved.

Because the link doesn’t lead to an actual webpage, search engines might report this to you as a broken link. The “nofollow, noindex” tags prevent this by instructing search engines not to follow and index the link.

When you’re fully satisfied with the redirect, you may wish to switch from a temporary (302) redirect to a permanent (301) redirect. After you’ve loaded a permanent (301) redirect, your browser will ignore any further changes that you make. This makes further testing more difficult, but it can save a roundtrip to the server.

Blocked 100% of 32 spammers
HTML
<object class="email" width="33" height="24" data="email.svg" type="image/svg+xml"></object>
SVG: email.svg
<svg viewBox="0 0 33 24" xmlns="http://www.w3.org/2000/svg"> <style> @import url('https://fonts.googleapis.com/css2?family=Indie+Flower&amp;display=swap'); text { dominant-baseline: middle; fill: #000; font-family: 'Indie Flower'; font-size: 16px; text-anchor: middle; } </style> <a href="mailto:email@example.com"> <text x="50%" y="50%">email</text> </a> </svg>
CSS
object.email { height: 2em; margin: -1em 0; vertical-align: middle; }
Browser

Inspiration: rouninmedia.github.io

This hides the email address in an unusual place where most harvesters won’t think to look. However, the email address is stored there in plain text.

This technique is accessible to all users, including those who depend on a screen reader. But you must use an object element for this to work: an img element would give you an image that is non-interactive, and inline SVG would put the email address in the source code where harvesters would find it easily.

The “width” and the “height” attributes help prevent layout shifts while the page is loading. Because the dimensions depend on the font, the SVG file has to explicitly specify a web font to prevent rendering issues.

Blocked 100% of 32 spammers
HTML
<script>document.write('<a href="mailto:'+'a'+'p'+'@'+'e'+'m'+'a'+'i'+'l'+'.'+'s'+'p'+'e'+'n'+'c'+'e'+'r'+'m'+'o'+'r'+'t'+'e'+'n'+'s'+'e'+'n'+'.'+'c'+'o'+'m'+'">email</a>');</script>
Browser

This is convenient because it has no external dependencies, and yet still manages to block most harvesters. However, the full email address appears directly in the HTML, so this technique cannot be considered safe.

Blocked 100% of 32 spammers
HTML
<a class="email" href="znvygb:nd@rznvy.fcraprezbegrafra.pbz">email</a>
HTML
<head> <script src="link-rot18.js" defer></script> </head>
Browser
email

This technique can be undone by basic harvesters that don’t interpret JavaScript. At the very least, you should rotate your letters by something other than 13, and rotate your numbers by something other than 5.

Blocked 100% of 31 spammers
HTML
<a id="link-conversion" rel="nofollow, noindex" href="to-email-spencer/">email</a>
HTML
<head> <script src="link-conversion.js" defer></script> </head>
Browser
email

In this technique, the HTML source code contains a decoy link, and you write a custom function that converts that decoy link into a working “mailto” link.

Most harvesters can only access the HTML source code—and the source code contains nothing of value. The only practical way to restore the “mailto” link is to run your custom conversion function in a web client with DOM and JavaScript support. This is not possible for most harvesters.

You can write a custom function for each email address, or you can write a single function and apply it to all of the email addresses on the page.

Despite being frighteningly simple, this is expected to be one of the very best techniques.

Blocked 100% of 31 spammers
HTML
<a class="email" rel="nofollow, noindex" href="xd7L-AOA9Qckl5RXbFuFw8LxuiPZPk3vzyPS55-KlD-a78c00rng">email</a>
HTML
<head> <script src="link-aes.js" defer></script> </head>
Browser
email

This technique uses AES 256 to encrypt the email address. (AES is the only publicly-available cipher approved by the NSA for top secret information.) The email address cannot be recovered without the JavaScript file—which most harvesters cannot access or run. This implementation uses the browser’s own built-in cryptography library, so it will not run outside of the browser, even in JavaScript-capable environments.

The cryptography library, SubtleCrypto, is only available in secure contexts (such as over https or on localhost)—which could be a blocker if you’re using http. You must upgrade to https before you can use this technique!

Blocked 100% of 32 spammers
HTML
<a id="link-interaction" rel="nofollow, noindex" href="to-email-spencer/">email</a>
HTML
<head> <script src="link-interaction.js" defer></script> </head>
Browser
email

This technique keeps the email address hidden until the user interacts with the page; only then is the email address revealed. This raises the bar for harvesters: they not only need to run a full web client, they also need to interact with it.

This technique can be used to trigger other techniques.

3 Observations

Most harvesters are easily defeated

Because any obfuscation technique can be broken by a sophisticated harvester, some people assume that obfuscation is pointless. Nothing could be further from the truth! Most harvesters are unsophisticated, and even the simplest techniques are very effective at defeating them.

Harvesters follow leads more than links

Harvesters prefer high-popularity pages over low-popularity pages, even when the pages are directly linked. This inconsistent attention can lead people to falsely conclude that no pages ever need protection—when, in fact, some pages legitimately do need protection.

4 Methodology

This article is not just an article for human readers, it’s also a honeypot for harvesters. Each technique protects a unique email address: when that email address receives spam, I know that the corresponding technique was broken. From this, I can infer which techniques were not broken during the attack—and that gives me the protection statistics.

I group messages together by spammer, noting which email addresses the spammer knows, while ignoring the total volume of email, so as not to be affected by the abitrary details of a marketing campaign. However, it is often difficult to identify who exactly is behind a given message: Spammers often hide behind a variety of sender email addresses in order to get around spam filtering. The contact information is the most reliable, so I use the contact information, rather than the various sender addresses, to identify the spammer. This reduces overcounting, but can’t eliminate it, because the same spammer is usually promoting more than one venture, and spammers sometimes circulate lists of email addresses that they themselves never harvested.

Before collecting any statistics, it’s very important to have all spam filtering turned off. The big mail providers filter out a huge amount of spam that never reaches their users (it may appear in a Spam folder, or it may be silently deleted and never shown). Desktop mail clients often do something similar: I had to set up my own mail server and my own mail client before I was sure that I had completely disabled all mail filtering at every step along the way.

The total spammer counts may vary a bit from technique to technique: Harvesters generally don’t target both plain-text address and clickable links, so I keep those statistics independently. Also, some of the techniques were added later than others, which slightly affects the numbers.

The sample sizes are growing, but still small, so there is some uncertainty in the statistics. The more people link to this article, and share it, the better these statistics will become!