[{"data":1,"prerenderedAt":577},["ShallowReactive",2],{"guide-html-encode-email-addresses":3},{"id":4,"title":5,"body":6,"date":569,"description":570,"extension":571,"meta":572,"navigation":145,"path":573,"readingTime":185,"seo":574,"stem":575,"__hash__":576},"guides\u002Fguides\u002Fhtml-encode-email-addresses.md","HTML Encoding Email Addresses",{"type":7,"value":8,"toc":563},"minimark",[9,13,18,30,33,56,59,62,66,69,76,271,294,300,304,307,314,450,456,530,536,539,543,546,549,552,560],[10,11,12],"p",{},"Publishing an email address on a public webpage is an open invitation to spam. Automated crawlers—often called email harvesters—scan millions of pages daily, extracting mailto links and plain-text addresses to add to spam databases. HTML entity encoding offers a lightweight obfuscation technique that makes addresses harder for bots to read while keeping them functional for human visitors.",[14,15,17],"h2",{"id":16},"how-email-harvesters-work","How Email Harvesters Work",[10,19,20,21,25,26,29],{},"Spam bots crawl the web using patterns similar to search engine spiders but with a different purpose. They look for strings matching the email format (",[22,23,24],"code",{},"local@domain.tld",") and ",[22,27,28],{},"mailto:"," hyperlinks. Most harvesters operate at scale, processing thousands of pages per minute with minimal computational overhead per address.",[10,31,32],{},"Basic harvesters use regular expressions to find email-like patterns in raw HTML:",[34,35,40],"pre",{"className":36,"code":37,"language":38,"meta":39,"style":39},"language-python shiki shiki-themes github-light github-dark","import re\nemail_pattern = re.compile(r'[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}')\n","python","",[22,41,42,50],{"__ignoreMap":39},[43,44,47],"span",{"class":45,"line":46},"line",1,[43,48,49],{},"import re\n",[43,51,53],{"class":45,"line":52},2,[43,54,55],{},"email_pattern = re.compile(r'[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}')\n",[10,57,58],{},"More sophisticated crawlers render JavaScript and decode entities before scanning. However, many harvesters skip entity decoding to save processing time, given that decoding every page's HTML entities across billions of URLs is computationally expensive.",[10,60,61],{},"This asymmetry—bots skipping decoding for speed while browsers always decode for display—is the foundation of entity-based obfuscation.",[14,63,65],{"id":64},"encoding-email-addresses-with-html-entities","Encoding Email Addresses with HTML Entities",[10,67,68],{},"The technique replaces characters in the email address with their numeric or named HTML entity equivalents. The browser decodes these entities before displaying the address or handling the mailto link, so users see and click the correct email.",[10,70,71,72,75],{},"For the address ",[22,73,74],{},"hello@example.com",", encoded versions might look like:",[34,77,81],{"className":78,"code":79,"language":80,"meta":39,"style":39},"language-html shiki shiki-themes github-light github-dark","\u003C!-- Named entities -->\n\u003Ca href=\"mailto:hello&#64;example&#46;com\">hello&#64;example&#46;com\u003C\u002Fa>\n\n\u003C!-- Decimal numeric entities -->\n\u003Ca href=\"&#109;&#97;&#105;&#108;&#116;&#111;&#58;hello&#64;example&#46;com\">\n  hello&#64;example&#46;com\n\u003C\u002Fa>\n\n\u003C!-- Hexadecimal numeric entities -->\n\u003Ca href=\"&#x6D;&#x61;&#x69;&#x6C;&#x74;&#x6F;&#x3A;hello&#x40;example&#x2E;com\">\n  hello&#x40;example&#x2E;com\n\u003C\u002Fa>\n","html",[22,82,83,89,140,147,153,183,198,208,213,219,249,262],{"__ignoreMap":39},[43,84,85],{"class":45,"line":46},[43,86,88],{"class":87},"sJ8bj","\u003C!-- Named entities -->\n",[43,90,91,95,99,103,106,110,114,117,120,123,126,128,130,132,135,137],{"class":45,"line":52},[43,92,94],{"class":93},"sVt8B","\u003C",[43,96,98],{"class":97},"s9eBZ","a",[43,100,102],{"class":101},"sScJk"," href",[43,104,105],{"class":93},"=",[43,107,109],{"class":108},"sZZnC","\"mailto:hello",[43,111,113],{"class":112},"sj4cs","&#64;",[43,115,116],{"class":108},"example",[43,118,119],{"class":112},"&#46;",[43,121,122],{"class":108},"com\"",[43,124,125],{"class":93},">hello",[43,127,113],{"class":112},[43,129,116],{"class":93},[43,131,119],{"class":112},[43,133,134],{"class":93},"com\u003C\u002F",[43,136,98],{"class":97},[43,138,139],{"class":93},">\n",[43,141,143],{"class":45,"line":142},3,[43,144,146],{"emptyLinePlaceholder":145},true,"\n",[43,148,150],{"class":45,"line":149},4,[43,151,152],{"class":87},"\u003C!-- Decimal numeric entities -->\n",[43,154,156,158,160,162,164,167,170,173,175,177,179,181],{"class":45,"line":155},5,[43,157,94],{"class":93},[43,159,98],{"class":97},[43,161,102],{"class":101},[43,163,105],{"class":93},[43,165,166],{"class":108},"\"",[43,168,169],{"class":112},"&#109;&#97;&#105;&#108;&#116;&#111;&#58;",[43,171,172],{"class":108},"hello",[43,174,113],{"class":112},[43,176,116],{"class":108},[43,178,119],{"class":112},[43,180,122],{"class":108},[43,182,139],{"class":93},[43,184,186,189,191,193,195],{"class":45,"line":185},6,[43,187,188],{"class":93},"  hello",[43,190,113],{"class":112},[43,192,116],{"class":93},[43,194,119],{"class":112},[43,196,197],{"class":93},"com\n",[43,199,201,204,206],{"class":45,"line":200},7,[43,202,203],{"class":93},"\u003C\u002F",[43,205,98],{"class":97},[43,207,139],{"class":93},[43,209,211],{"class":45,"line":210},8,[43,212,146],{"emptyLinePlaceholder":145},[43,214,216],{"class":45,"line":215},9,[43,217,218],{"class":87},"\u003C!-- Hexadecimal numeric entities -->\n",[43,220,222,224,226,228,230,232,235,237,240,242,245,247],{"class":45,"line":221},10,[43,223,94],{"class":93},[43,225,98],{"class":97},[43,227,102],{"class":101},[43,229,105],{"class":93},[43,231,166],{"class":108},[43,233,234],{"class":112},"&#x6D;&#x61;&#x69;&#x6C;&#x74;&#x6F;&#x3A;",[43,236,172],{"class":108},[43,238,239],{"class":112},"&#x40;",[43,241,116],{"class":108},[43,243,244],{"class":112},"&#x2E;",[43,246,122],{"class":108},[43,248,139],{"class":93},[43,250,252,254,256,258,260],{"class":45,"line":251},11,[43,253,188],{"class":93},[43,255,239],{"class":112},[43,257,116],{"class":93},[43,259,244],{"class":112},[43,261,197],{"class":93},[43,263,265,267,269],{"class":45,"line":264},12,[43,266,203],{"class":93},[43,268,98],{"class":97},[43,270,139],{"class":93},[10,272,273,274,276,277,280,281,283,284,25,286,280,289,283,291,293],{},"Each variation renders identically in the browser as a clickable ",[22,275,74],{}," link. The key characters to encode are ",[22,278,279],{},"@"," (",[22,282,113],{}," or ",[22,285,239],{},[22,287,288],{},".",[22,290,119],{},[22,292,244],{},"), since these are the anchors for email-detecting regex patterns.",[10,295,296,297,299],{},"For stronger obfuscation, encode the entire address including the ",[22,298,28],{}," prefix using decimal or hex entities. The more characters you encode, the less likely a pattern-matching harvester will detect the address.",[14,301,303],{"id":302},"combining-multiple-obfuscation-techniques","Combining Multiple Obfuscation Techniques",[10,305,306],{},"Relying on a single method leaves gaps. Combining techniques significantly reduces harvest success rates.",[10,308,309,313],{},[310,311,312],"strong",{},"JavaScript generation."," Write the email address dynamically at runtime so it never appears in the static HTML source:",[34,315,317],{"className":78,"code":316,"language":80,"meta":39,"style":39},"\u003Cscript>\n  const user = 'hello';\n  const domain = 'example.com';\n  document.write(`\u003Ca href=\"mailto:${user}@${domain}\">${user}@${domain}\u003C\u002Fa>`);\n\u003C\u002Fscript>\n\u003Cnoscript>\n  \u003C!-- Fallback for noscript users: show contact form link instead -->\n  \u003Ca href=\"\u002Fcontact\">Contact us\u003C\u002Fa>\n\u003C\u002Fscript>\n",[22,318,319,328,346,360,398,406,415,420,441],{"__ignoreMap":39},[43,320,321,323,326],{"class":45,"line":46},[43,322,94],{"class":93},[43,324,325],{"class":97},"script",[43,327,139],{"class":93},[43,329,330,334,337,340,343],{"class":45,"line":52},[43,331,333],{"class":332},"szBVR","  const",[43,335,336],{"class":112}," user",[43,338,339],{"class":332}," =",[43,341,342],{"class":108}," 'hello'",[43,344,345],{"class":93},";\n",[43,347,348,350,353,355,358],{"class":45,"line":142},[43,349,333],{"class":332},[43,351,352],{"class":112}," domain",[43,354,339],{"class":332},[43,356,357],{"class":108}," 'example.com'",[43,359,345],{"class":93},[43,361,362,365,368,371,374,377,380,383,386,388,390,392,395],{"class":45,"line":149},[43,363,364],{"class":93},"  document.",[43,366,367],{"class":101},"write",[43,369,370],{"class":93},"(",[43,372,373],{"class":108},"`\u003Ca href=\"mailto:${",[43,375,376],{"class":93},"user",[43,378,379],{"class":108},"}@${",[43,381,382],{"class":93},"domain",[43,384,385],{"class":108},"}\">${",[43,387,376],{"class":93},[43,389,379],{"class":108},[43,391,382],{"class":93},[43,393,394],{"class":108},"}\u003C\u002Fa>`",[43,396,397],{"class":93},");\n",[43,399,400,402,404],{"class":45,"line":155},[43,401,203],{"class":93},[43,403,325],{"class":97},[43,405,139],{"class":93},[43,407,408,410,413],{"class":45,"line":185},[43,409,94],{"class":93},[43,411,412],{"class":97},"noscript",[43,414,139],{"class":93},[43,416,417],{"class":45,"line":200},[43,418,419],{"class":87},"  \u003C!-- Fallback for noscript users: show contact form link instead -->\n",[43,421,422,425,427,429,431,434,437,439],{"class":45,"line":210},[43,423,424],{"class":93},"  \u003C",[43,426,98],{"class":97},[43,428,102],{"class":101},[43,430,105],{"class":93},[43,432,433],{"class":108},"\"\u002Fcontact\"",[43,435,436],{"class":93},">Contact us\u003C\u002F",[43,438,98],{"class":97},[43,440,139],{"class":93},[43,442,443,445,448],{"class":45,"line":215},[43,444,203],{"class":93},[43,446,325],{"class":447},"s7hpK",[43,449,139],{"class":93},[10,451,452,455],{},[310,453,454],{},"CSS text reversal."," Display the address right-to-left using CSS while keeping the HTML reversed, so the source reads backwards:",[34,457,459],{"className":78,"code":458,"language":80,"meta":39,"style":39},"\u003Cstyle>\n  .obfuscated { direction: rtl; unicode-bidi: bidi-override; }\n\u003C\u002Fstyle>\n\u003Cspan class=\"obfuscated\">moc.elpmaxe@olleh\u003C\u002Fspan>\n",[22,460,461,470,501,509],{"__ignoreMap":39},[43,462,463,465,468],{"class":45,"line":46},[43,464,94],{"class":93},[43,466,467],{"class":97},"style",[43,469,139],{"class":93},[43,471,472,475,478,481,484,487,490,493,495,498],{"class":45,"line":52},[43,473,474],{"class":101},"  .obfuscated",[43,476,477],{"class":93}," { ",[43,479,480],{"class":112},"direction",[43,482,483],{"class":93},": ",[43,485,486],{"class":112},"rtl",[43,488,489],{"class":93},"; ",[43,491,492],{"class":112},"unicode-bidi",[43,494,483],{"class":93},[43,496,497],{"class":112},"bidi-override",[43,499,500],{"class":93},"; }\n",[43,502,503,505,507],{"class":45,"line":142},[43,504,203],{"class":93},[43,506,467],{"class":97},[43,508,139],{"class":93},[43,510,511,513,515,518,520,523,526,528],{"class":45,"line":149},[43,512,94],{"class":93},[43,514,43],{"class":97},[43,516,517],{"class":101}," class",[43,519,105],{"class":93},[43,521,522],{"class":108},"\"obfuscated\"",[43,524,525],{"class":93},">moc.elpmaxe@olleh\u003C\u002F",[43,527,43],{"class":97},[43,529,139],{"class":93},[10,531,532,535],{},[310,533,534],{},"Contact forms."," The most effective approach is removing the email address from the page entirely and replacing it with a server-side contact form. This eliminates the harvesting vector altogether.",[10,537,538],{},"Research from independent studies shows that combining entity encoding with JavaScript generation blocks over 95% of harvesters, while any single technique alone blocks 60-80%.",[14,540,542],{"id":541},"limitations-and-trade-offs","Limitations and Trade-Offs",[10,544,545],{},"Entity encoding is a deterrent, not a guarantee. Advanced harvesters that render pages in a headless browser (like Puppeteer) will decode entities and extract the address. The technique raises the cost of harvesting your address, which is sufficient to deter most automated crawlers.",[10,547,548],{},"Accessibility is another consideration. Screen readers should handle entity-encoded content correctly since the browser decodes it before the accessibility tree is built. However, JavaScript-based obfuscation can fail for users with JavaScript disabled, so always provide a noscript fallback.",[10,550,551],{},"Finally, once an address appears in any harvested list, encoding the page version will not stop spam that originates from previously compromised lists. Obfuscation is preventive, not curative—it protects new addresses going forward.",[10,553,554,555,559],{},"To encode your own email addresses for obfuscation, use the ",[98,556,558],{"href":557},"\u002Ftools\u002Fhtml-encoder","HTML Encoder tool"," to convert characters into entity references quickly.",[467,561,562],{},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .s9eBZ, html code.shiki .s9eBZ{--shiki-default:#22863A;--shiki-dark:#85E89D}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .s7hpK, html code.shiki .s7hpK{--shiki-default:#B31D28;--shiki-default-font-style:italic;--shiki-dark:#FDAEB7;--shiki-dark-font-style:italic}",{"title":39,"searchDepth":52,"depth":52,"links":564},[565,566,567,568],{"id":16,"depth":52,"text":17},{"id":64,"depth":52,"text":65},{"id":302,"depth":52,"text":303},{"id":541,"depth":52,"text":542},"2026-05-28","Obfuscate email links with HTML entities to reduce spam bots harvesting addresses.","md",{},"\u002Fguides\u002Fhtml-encode-email-addresses",{"title":5,"description":570},"guides\u002Fhtml-encode-email-addresses","Ayzz00k8O01HC5HDgh9FuJdxNm8LpOMxom0P8rBiN6U",1780401334177]