Introduction
Email addresses on websites are prime targets for spam bots and web scrapers. When you display email addresses in plain text or as simple mailto links, you're essentially offering them up to harvesting bots. In this article, I'll share a robust Vue.js solution we implemented to protect email addresses while maintaining usability for real users.
The Problem
In a typical footer component, email addresses are often displayed like this:
html
<a href="mailto:contact@example.com">contact@example.com</a>
This approach is problematic because:
- Email scrapers can easily identify the mailto pattern
- The plaintext email address is directly accessible in the DOM
- There's no protection layer between bots and your email
The Solution: A Three-Component Architecture
We developed a solution using three Vue.js components working together:
- EmailProtected.vue: A specialized component to render protected email addresses
- ContactItem.vue: A component that handles different types of contact information
- FooterContact.vue: The parent component organizing all contact information
1. The EmailProtected Component
This component is the core of our solution. It implements several anti-scraping techniques:
<template>
<span>
<a
href="#"
@click.prevent="handleClick"
@mouseenter="generateEmail"
class="email-protected"
:aria-label="`Email address: ${visualEmail}`"
tabindex="0"
@keydown.enter="handleClick"
@keydown.space="handleClick"
>
<span v-for="(part, index) in emailParts" :key="index" :class="`email-part-${index}`">{{ part }}</span>
<span class="domain" v-if="showDomain">{{ '@' + domain }}</span>
</a>
</span>
</template>
<script>
export default {
name: 'EmailProtected',
props: {
username: {
type: String,
required: true
},
domain: {
type: String,
required: true
}
},
data() {
return {
emailParts: [],
showDomain: false,
emailGenerated: false
}
},
computed: {
visualEmail() {
return `${this.username}@${this.domain}`;
},
fullEmail() {
return `${this.username}@${this.domain}`;
}
},
mounted() {
// Split username into parts to make it harder for bots to recognize as email
const parts = [];
for (let i = 0; i < this.username.length; i++) {
parts.push(this.username.charAt(i));
}
this.emailParts = parts;
},
methods: {
generateEmail() {
if (!this.emailGenerated) {
this.showDomain = true;
this.emailGenerated = true;
}
},
handleClick() {
this.generateEmail();
// Use setTimeout to delay the creation of the mailto link
setTimeout(() => {
window.location.href = `mailto:${this.fullEmail}`;
}, 50);
}
}
}
</script>
Anti-Scraping Techniques Used
- Email Fragmentation: The email username is split into individual characters stored in an array, making pattern recognition more difficult.
- Delayed Rendering: The domain part of the email is only shown after user interaction (hover, focus, or click).
- Dynamic Link Creation: The mailto link is created on-demand via JavaScript instead of being present in the static HTML.
- CSS Obfuscation: We use CSS techniques like unicode-bidi to make automated parsing more challenging.
- No Static Email Strings: There's no complete email string in the HTML that could be found with regular expressions.
2. The ContactItem Component
This component handles different types of contact items including our protected emails:
vue
3. The Parent FooterContact Component
This component organizes all our contact information and uses the type-based system:
vue
How This Solution Works
- Data Organization: Email addresses are split into username and domain parts in the data structure
- Conditional Rendering: Different types of contact info are rendered differently
- Progressive Enhancement: Emails start partially obfuscated and are completed on user interaction
- User Experience: Remains intuitive for actual users (hover shows the full email, click creates a mailto link)
- Accessibility: Maintains keyboard navigation and screen reader support
Additional Techniques You Can Add
Our solution is solid, but you could enhance it further with these techniques:
- Server-side Rendering Considerations: Add data-attributes that are only processed client-side
- Unicode Character Substitution: Replace some characters with similar-looking Unicode alternatives
- Image or SVG Emails: Convert emails to images or SVGs for critical cases
- Contact Forms: Provide a form alternative to directly exposing emails
- CAPTCHA for Email Visibility: Require CAPTCHA completion before revealing email addresses
Browser Compatibility and Accessibility Considerations
Our solution works well across modern browsers and maintains accessibility through:
- Proper semantic HTML (
<address>elements for contact info) - ARIA attributes for screen readers
- Keyboard navigation support
- Focus states and clear interactive elements
Conclusion
By implementing this three-component architecture, you can significantly reduce the risk of email harvesting without compromising user experience. The techniques combine frontend obfuscation strategies that make automated scraping difficult while keeping emails accessible to actual visitors.
While no solution is 100% bot-proof, these techniques create multiple layers of protection that will deter most scraping attempts. The modular approach also allows you to easily update your protection methods as spam techniques evolve.
Remember that email protection is a continuous process, and it's good practice to monitor your spam levels and adjust your protection strategies accordingly.
What anti-scraping techniques have you implemented in your projects? Share your experiences in the comments below.
Top comments (0)