Key Takeaways
- Single-layer HTML entity encoding — the technique used by nearly every free contact protection plugin on WordPress.org — is defeated by a single line of code. Server-side scraping libraries decode HTML entities automatically, meaning any harvesting operation worth worrying about clears it in milliseconds without any special effort.
- Dual-layer contact encoding combines HTML entity encoding with a CSS direction reversal technique, so that the contact data a scraper reads from the HTML source is both entity-encoded and written in reverse — two separate problems that must both be solved simultaneously to reconstruct the original address.
- The second layer (CSS reversal) specifically targets the class of scraper that processes the rendered DOM rather than reading raw HTML — adding meaningful friction at the exact point where single-layer encoding stops working.
- WhoKnew Shield™ is the only free WordPress plugin that applies both layers automatically across an entire site without shortcodes — every other plugin either stops at single-layer encoding on the free tier or requires a paid upgrade to access the second technique.
- Pro adds a third layer: site-specific military-grade encryption that makes the underlying contact data unreadable even to a scraper that successfully applies both CSS and entity decoding — but the free dual-layer combination already stops the overwhelming majority of bots in the wild.
If you’ve ever installed a WordPress plugin to protect your email address from scrapers, you’ve almost certainly installed one that uses HTML entity encoding. It’s the dominant technique in the space — used by Email Address Encoder, Email Encoder Bundle, and dozens of similar plugins — and it works well enough that most site owners install it and assume the problem is solved. The uncomfortable truth is that the scrapers most responsible for filling your inbox with spam, your phone with robocalls, and your office mailbox with junk mail aren’t the ones that HTML entity encoding stops. They haven’t been for years. Understanding why requires understanding what entity encoding actually does, what it doesn’t do, and what a second layer adds that changes the picture in a way that matters.
What HTML Entity Encoding Actually Does
An HTML entity is a way of representing a character using a code rather than the character itself. The at-sign in an email address — @ — can be represented as @ in decimal or @ in hexadecimal. A browser reading either of those sequences displays the same @ character a human would expect to see. A bot reading the raw HTML source, however, sees the entity code rather than the character — and if that bot is simply scanning HTML text for strings that match the pattern of an email address, the encoded version doesn’t match and the address isn’t harvested.
The problem is that this defense is significantly weaker than it sounds. Server-side scraping libraries — the tools used by even basic harvesting operations — decode HTML entities automatically. Spencer Mortensen’s independent research on email obfuscation is direct on this point: “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.” The bypass requires no sophistication whatsoever — entity encoding might slow down a crudely written regex bot scanning for plain-text @ signs, but any harvesting operation worth worrying about clears it in milliseconds.
What sits in HTML: hello@yoursite.com
// Looks protected. Here is the entire bypass:
// return html_entity_decode($encoded);
// One line of PHP. Runs automatically in every server-side scraping library.
// Result: 389d54b8@0a482b3a.com — in their database in seconds.
That’s the reality of single-layer entity encoding in 2026. It’s not a lock — it’s a “wet concrete” sign. The bots doing serious contact harvesting don’t even notice it. Beyond that, any headless browser — a full browser engine running without a visible window, used by Puppeteer, Playwright, and similar automation tools — renders the entire page exactly as a human’s browser would, then reads the decoded output. From a headless browser’s perspective, an entity-encoded email address looks identical to a plain-text one before any data extraction happens.
1
20–40%
2026

The Scraper Landscape in 2026: Three Distinct Tiers
Understanding why a second layer is needed — and what it needs to accomplish — requires understanding that “scraper” isn’t a single category. The bots harvesting contact information from WordPress sites in 2026 operate at three meaningfully different sophistication levels, and each tier defeats a different set of defenses.
| Tier | What it does | Single-Layer Entities | Dual-Layer (Entities + CSS) |
|---|---|---|---|
| Tier 1 — Basic scrapers Server-side library scrapers that auto-decode HTML entities | Reads HTML source and passes it through a server-side library that automatically decodes entities — one line of code. No special effort required. | ✗ Bypassed — one line of PHP | ✓ Blocked — CSS reversal adds a second problem |
| Tier 2 — DOM scrapers Mid-sophistication bots that parse the rendered DOM | Parses the page’s Document Object Model after browser rendering — sees entity-decoded text but doesn’t apply CSS transformations to reverse-direction text | ✗ Passes through | ✓ Blocked |
| Tier 3 — Headless browsers Puppeteer, Playwright, and similar full-browser automation tools | Renders the full page including CSS, extracts the visually rendered output — sees the email address exactly as a human would | ✗ Passes through | ~ Partially blocked |
The uncomfortable reality is that Tier 3 scrapers — full headless browser automation — can defeat both layers of encoding if they apply full CSS rendering before text extraction. A Puppeteer script that navigates to a page, waits for full render, and then reads document.body.innerText will see the final rendered email address regardless of what encoding was applied in the HTML. The honest framing is that dual-layer encoding raises the cost and complexity of extraction meaningfully for Tier 2, stops Tier 1 entirely, and applies genuine friction to Tier 3 — but it is not an absolute guarantee against the most sophisticated automated tooling. That’s why Shield Pro adds a third layer: site-specific encryption that protects contact data even from scrapers that apply full CSS rendering.
The Honest Scope of Encoding-Based ProtectionContact encoding is not a guarantee — it’s a cost-raising mechanism. The goal is to make your contact data more expensive to harvest than the data available from easier targets, so that automated harvesting operations move on to lower-cost sites rather than investing the additional compute and complexity required to defeat multiple layers. Most spam operations are volume-driven: they harvest from thousands of sites simultaneously and don’t invest in defeating site-specific defenses. Raising the cost of harvesting your specific site is a genuinely effective strategy against this model.
Dual-layer encoding is the highest-friction free solution currently available in the WordPress ecosystem. For the class of serious, targeted attacker willing to deploy headless browser automation against a specific site, Shield Pro’s site-specific encryption is the appropriate response — because encryption makes the data itself unreadable rather than just harder to pattern-match.
What the Second Layer Actually Does: CSS Direction Reversal
The second layer in Shield’s dual-layer encoding works by exploiting the difference between what sits in the HTML source and what the browser renders visually. The technique uses the CSS direction property to store the contact information in reverse order in the HTML — so that a scraper reading the DOM text content without applying CSS sees a reversed string — while the browser’s visual rendering engine uses the CSS direction: rtl (right-to-left) rule to display the characters in the correct readable order to a human visitor.
<span style=”direction:rtl;unicode-bidi:bidi-override”>
moc.etisruoy@olleh
</span>
// Human browser renders: 389d54b8@0a482b3a.com (direction CSS applied visually)
// Tier 1 scraper auto-decodes entities — still gets: moc.etisruoy@olleh (reversed, useless)
// Tier 2 DOM scraper extracts text without CSS: moc.etisruoy@olleh (reversed, useless)
// Tier 3 headless browser with full CSS render: 389d54b8@0a482b3a.com
// To get a usable address a scraper must solve both problems — not just one.
The practical effect is a second distinct problem a scraper must solve. A bot that successfully decodes the HTML entities still reads the reversed string — and a reversed email address doesn’t match an email pattern, doesn’t work as a contact address, and has no value to whoever is running the harvesting operation. To extract a usable address, the scraper must both decode the entities AND apply the CSS direction transformation before reading the text — which moves it from Tier 2 capability into Tier 3 territory, dramatically reducing the pool of bots capable of successful extraction.
Single-layer encoding gives a scraper one problem to solve. Dual-layer encoding gives it two different problems that must be solved simultaneously — and the second problem is one the first layer gives no hint of.

Why Every Other Free Plugin Stops at One Layer
This is the specific gap WhoKnew Shield™ fills, and it’s worth being direct about it: the dual-layer approach is not what other free contact protection plugins do. The competitive landscape in the WordPress plugin directory is clear on this point.
Email Address Encoder (over 100,000 active installs) — the most widely used contact protection plugin on WordPress.org — confirms in its own documentation that HTML entities are “the only option for the free plugin.” CSS direction encoding, ROT13, and ROT47/CSS are all listed as premium-only features. The free tier is single-layer.
Email Encoder Bundle — the second major option — offers automatic technique detection on the free tier, but that detection selects from single-layer methods. The second-layer techniques require the premium version.
Independent analysis from DEV Community in April 2026 is explicit: “Basic techniques like ROT13 and simple HTML encoding are largely defeated by modern scrapers. The most effective current approaches combine JavaScript-based rendering, CSS direction tricks, and server-side contact forms — ideally layered together.” The recommendation is for a combination — not a single technique. That combination is what Shield delivers in its free tier; other plugins deliver the combination only in paid versions.
Free in all plugins
Converts plain-text contact data into HTML entity sequences — decimal (@) or hexadecimal (@) representations of each character. Browsers decode and display these normally. The problem: server-side scraping libraries also decode them automatically. One line of PHP and the address is fully readable. This layer stops only the most crudely written bots.
Stops: Poorly written bots with no library support.
Does not stop: Any modern scraping library, DOM parser, or headless browser.
Free in Shield only
Stores the contact string in reverse order in the HTML source, with a CSS direction: rtl rule that instructs the browser to display the characters right-to-left — making the reversed string appear correct to a human reader. A scraper that auto-decodes the entities still reads a reversed, unusable string. Fixing it requires an additional step that most automated harvesting pipelines don’t bother with — because most sites don’t have this layer at all.
Stops: Tier 1 and Tier 2 scrapers — the vast majority of automated harvesting traffic.
Does not stop: Full headless browser rendering with CSS applied before text extraction.
Pro only
Shield Pro adds military-grade site-specific encryption — a key generated uniquely for each WordPress installation. The contact data is encrypted before it ever reaches a browser, so what sits in the HTML source is cryptographic output that doesn’t decode to anything readable without that specific site’s key. Even a Tier 3 headless browser rendering the full page cannot reconstruct the original contact data. Combined with Silent Contact™ — which renders contacts as PNG images with no text in the HTML at all — there is no path to the address regardless of what tool a scraper uses.
Stops: Tier 1, Tier 2, and Tier 3 scrapers.
Accessible from: Shield Pro at $8/month or $80/year.
Why Auto-Detection Matters as Much as the Layers Themselves
The number of encoding layers applied to any given piece of contact data only matters if the plugin finds that contact data in the first place. This is where shortcode-based protection plugins — the approach most older plugins use — have a fundamental structural problem that no amount of encoding sophistication can fix.
Manual shortcode plugins require a site owner to wrap every email address, phone number, and physical address across their entire site with a specific shortcode. Research on contact scraper gap analysis consistently finds that manual shortcode plugins miss 20 to 40 percent of a site’s exposed contact data — not because the plugin doesn’t work when applied, but because contact information exists in places site owners don’t think to check: old posts, widget areas, header and footer code, custom fields, page builder blocks, theme templates, and plugin-generated output.
❌ Manual Shortcode Approach
- Site owner must find and wrap every contact instance manually
- Misses contacts in old posts, widgets, theme files, page builders
- 20–40% of contact data typically left unprotected
- Every new piece of content requires remembering to apply the shortcode
- One forgotten contact is all a scraper needs to harvest the address
✓ Auto-Detection Approach
- Plugin scans the entire rendered page output — not just post content
- Catches emails, phone numbers, and addresses wherever they appear in HTML output
- Protects content added by themes, plugins, widgets, and page builders automatically
- No manual action required on new or existing content
- Coverage is the rendered page, not the content fields — same view the scraper gets
Shield’s auto-detection operates at the output buffer level — it intercepts the full rendered HTML that WordPress sends to the browser, scans it for contact data patterns, and applies dual-layer encoding before any of that HTML reaches the scraper. This means it protects email addresses that appear in a theme header, a footer widget, a WooCommerce checkout confirmation, an Elementor section, or anywhere else in the page output — without any shortcode placement, and without any knowledge on the site owner’s part that the contact data was in those locations at all. The result is a gap-free protection perimeter rather than a patchy one with shortcode-sized holes.
What the Layers Look Like in Practice: A Site Owner’s Perspective
From the site owner’s perspective, dual-layer encoding is invisible — visitors see contact information displayed exactly as it was entered, with full click-to-call and mailto functionality intact. The encoding and reversal happen entirely in the HTML source that browsers and scrapers receive; the browser’s rendering engine decodes both layers before displaying anything, so there’s no visual difference between a protected and an unprotected contact address from a reader’s point of view.
What changes is what a scraper sees when it downloads the page source. Where a plain email address would appear as hello@yoursite.com in unprotected HTML, a dual-layer encoded address appears as a reversed entity-encoded string that fails both a pattern match against email format and a naive string reversal — because the entity encoding must be resolved before the reversal makes any sense, and most harvesting pipelines aren’t written to handle both problems in sequence.
Verifying that dual-layer protection is active takes about thirty seconds: install the plugin, navigate to any page on your site, right-click and select View Page Source (not the browser inspector — that shows the rendered DOM, which will always show the decoded address), and search for any email address you know appears on the page. If Shield is working correctly, you will not find the plain-text address anywhere in the source.
Further Reading
- Why Most WordPress Contact Protection Plugins Are Useless — the single-layer gap that leaves the majority of installed contact protection effectively decorative against modern scraper tooling.
- Why Manual Shortcode Plugins Always Have Gaps — how the shortcode model structurally guarantees that 20–40% of a site’s contact data goes unprotected regardless of which plugin is used.
- What Is Silent Contact™ and How Does It Stop Scrapers? — Shield Pro’s PNG image rendering approach, which removes contact text from HTML entirely rather than encoding it.
- Beyond the Firewall: Your Firewall Is Watching the Wrong Door — why network-level defenses and contact-layer protection address different phases of the same attack and why both are needed.
- What Is a Scraper Trap Honeypot and How Does It Catch Bots? — the behavioral detection layer that catches scrapers by what they do rather than by what they read.
Who knew the difference between getting spammed and not getting spammed could come down to a single CSS property — and that every other free plugin in the WordPress directory had decided that property was a paid feature.
