PHPEnkoder is a port of the excellent Hivelogic Enkoder to PHP and, more specifically, to WordPress. It is used to display text in a way that users can see and bots can’t.

The encoding system is directly and unabashedly stolen from the BSD-licensed source of Hivelogic Enkoder, which works by randomly encoding a piece of text and sending to the browser self-evaluating Javascript that will generate the original text. This works in two ways: first, a bot must first have a fairly complete Javascript implementation; second, the decoding process can be made arbitrarily computationally intensive. This is similar to the idea of charging computational payments to send e-mail, only this is actually implemented.

The code is released under the New BSD license, where I am the copyright holder, but the work is acknowledged as a derivative of the Hivelogic Enkoder. What this really means is that you can do whatever you want with the code so long as you leave the license and copyright information at the top.

I don’t accept donations; if you’d like to recognize the work that goes in to this plugin, I’d be delighted if you donated to either the EFF or the Center for Prison Reform.

Authoritative downloads are available from the WordPress plugin directory. The source code is up on github and the WordPress SVN.


The easiest way to install PHPEnkoder is through your WordPress dashboard. Just search for “PHPEnkoder” and click “Install now”.

To install manually, download PHPEnkoder and extract the archive in your wordpress/wp-content/plugins directory. PHPEnkoder can then be configured in the PHPEnkoder subpage of the Options configuration menu; by default, it will mask plaintext e-mails in addition to explicit mailto: links. (Note that attributes of the mailto: links, such as title and class, work fine — the entire anchor element is encoded.) In RSS, it will replace e-mails with customizable text (by default, email hidden; JavaScript is required).

To request support, bug fixes, and features, please send e-mail to email hidden; JavaScript is required.

Shortcode use

To enkode arbitrary text in a post or a page, you can use the enkode shortcode. Writing [enkode]your secret[/enkode] will enkode your secret in the published page. There are also three options, set like HTML attributes.

The text option sets the text displayed to non-Javascript browsers (and bots). For example, [enkode text="get with the times"]your secret[/enkode] will insult Mosaic users.

The passes option sets an upper bound on the number of enkoding passes. More passes makes dekoding take longer, at the expense of more enkoded text (i.e., a bigger download for the client). The default is 20.

The length option sets an upper bound on the length of the enkoded string. This can interact with the passes option, since enkoding increases the size of the text. If length is very low, not many passes will be run regardless of the passes setting.

Manual use

If you’d like to use the encoding functions in your own code, they are documented in the source file. For quick reference, here are their formal signatures:

function enkode_mailto($email, $text, $subject = "", $title = "")
function enkode($content, $max_passes = 20, $max_length = 1024)

$text is the text of the generated link. $title is the “title” attribute of the link; it will be turned into a tooltip. $max_passes is the maximum number of encodings to perform; $max_length is the maximum length (in characters) of the generated Javascript. To give a vague idea, about four passes encode a mailto: link into around 1000 characters. The constant cost of the Javascript is 157 characters.

And some examples of use:

// generate a subject-less, title-less mailto link
enkode_mailto("secret@email", "send the mail (link text)");

We can also encode arbitrary text:

// up to (approximately) 1024 characters (usually about 4 passes)
enkode("A little secret.  Any text, can include tags."); 
// up to 10K characters, a lot of passes (lots of client computation)
enkode("A serious secret.  Shh!", 40, 10000); 

Known bugs

WordPress creates excerpts by simply stripping tags from truncated content. This results in some Javascript-protecting comments appearing in the excerpt text, as I haven’t found a convenient way to determine if content being rendered is meant for an excerpt or the page. For now, a customizable message appears; by default, it will be rendered as /* email hidden; JavaScript is required */. Any ideas for workarounds would be appreciated; please send them along.

Change log

New in version 1.14

I’ve added a shortcode [noenkode] that allows you to turn off PHPEnkoder for a specific page. Thanks to sk19er for inspiring the feature.

New in version 1.13

I’ve fixed several E_NOTICE-level warnings that were showing up when WP_DEBUG was on. Thanks to Rootside for pointing this out.

New in version 1.12

PHPEnkoder handles accents correctly! This has been a longstanding issue, and I’m delighted to have it finally fixed. Please report any problems.

New in version 1.8

Per Tom’s report, version 1.8 fixes a few minor bugs. If PHPEnkoder is working for you, there’s no pressing need to upgrade.

New in version 1.7

Per Julius Welby’s request, there is now an option to set a class attribute on the a tags generated for mailto: links. If you leave this option empty (the default), then no class attribute will be set.

New in version 1.6

Martin Rees noticed that PHPEnkoder was making it hard to edit posts with comments containing e-mails. PHPEnkoder is now disabled on the administrative screens. The spans and functions being generated now have names that are more likely to be unique. The enkode shortcode was introduced, allowing for arbitrary enkoding to be done easily, like so: [enkode]this will be enkoded[/enkode].

New in version 1.5

Martin Rees noticed that PHPEnkoder’s settings panel was editable by any user. Now, the manage_options capability is necessary to change PHPEnkoder’s settings.

New in version 1.4

Gretchen Zimmerman noticed a bug that was causing funny output in some version of IE; this version fixes that bug.

New in version 1.3

Ron Blaisdell pointed out that my use of noscript elements wasn’t XHTML compliant. Instead of using noscript tags, each enkoded section is preceded by a span containing the “you don’t have JavaScript” message. When the dekoded text is written to the document, this span is deleted.

New in version 1.2

Steve Huston noticed a bug in a elements that had both a mailto: href and an e-mail address in the PCDATA; the problem is fixed in this version. Thanks Steve!

New in version 1.1

Apart from a few bugfixes in RSS handling, version 1.1 supports a configurable message for non-JavaScript capable readers, which (optionally) includes RSS. Message configuration is in the usual configuration menu.