Try the HTML Entities

Double Encoding: Why "&" Shows Up, and Why the "Quick Fix" Can Be Dangerous

"&" appearing on a webpage instead of "&" is one of the most common HTML-entity bugs — an ampersand encoded twice, because encoding got applied at multiple uncoordinated points in a pipeline. Here's why this happens, why "encode once, at output, as late as possible" is the fix, and why "fixing" double-encoding by removing encoding from the wrong stage can quietly turn a cosmetic bug into an XSS vulnerability.

June 17, 2026 7 min read
Share: Facebook X WhatsApp LinkedIn Email
Double Encoding: Why "&" Shows Up, and Why the "Quick Fix" Can Be Dangerous

"&" appearing on a webpage — an ampersand that's been encoded twice — is one of the most common HTML-entity bugs, and it happens because encoding is applied at multiple points in a pipeline that doesn't communicate about what's already been encoded

The previous articles on this site covered HTML entity basics, XSS-context-specific escaping, and Unicode/UTF-8 fundamentals. This article addresses double encoding — a specific, extremely common bug pattern where text gets HTML-entity-encoded more than once, producing visible artifacts like & instead of & — and the related, opposite problem of missing encoding entirely.


What double encoding looks like, and why it happens

Single encoding: the character & becomes & — this is correct, standard HTML entity encoding.

Double encoding: the already-encoded string & gets encoded again — the & within & itself gets encoded to & — producing & — which, when rendered by a browser, displays as the literal text & (since the browser decodes & once, yielding &, which — unless decoded againdisplays as those literal characters, not as &).

Why this happens: data passes through multiple stages, and more than one stage applies encoding — e.g.:

  1. A user submits a form containing Tom & Jerry
  2. Stage A (perhaps a server-side templating system) encodes this for safe HTML output: Tom & Jerrycorrect, at this point
  3. This already-encoded string is then stored (e.g., in a database) — storing the encoded version (Tom & Jerry) rather than the original (Tom & Jerry) is itself a design choice with trade-offs, discussed below
  4. Stage B (a different part of the system — perhaps a different template, or the same template applied again, or a client-side JavaScript framework that also applies HTML-escaping to displayed text) encodes the value againnot "knowing" that Stage A already encoded it — Tom & Jerry becomes Tom & Jerry

The root cause: encoding and storage/display responsibilities aren't clearly separatedif multiple parts of a system each "defensively" apply encoding (each operating on the assumption "the input I'm receiving might not be encoded yet, so I'll encode it") — and the input has already been encoded by an earlier stagedouble (or, in some pipelines, triple or more) encoding results.


The general principle: encode once, as close to the output as possible

A widely-recommended principle (related to the XSS-context article's emphasis on output-context-specific escaping): store/process data in its raw, unencoded form — and apply HTML-entity encoding only at the point of output to HTML, as late as possible in the processing pipeline.

Why "as late as possible": if data is stored/passed around internally in its raw form — each stage of processing (validation, business logic, database storage, etc.) operates on the "true," unencoded data — and encoding happens exactly once, at the final step before the data is placed into HTML output — there's no ambiguity about "has this already been encoded?" because encoding is the very last thing that happens, by design, not something multiple stages each independently decide to apply.

Storing already-encoded data (Stage A's output, in the example above) — while sometimes done, historically, for various reasons (perhaps the system was originally designed with the assumption "this data will only ever be displayed as HTML, so encode it once, at storage time, and never worry about it again") — creates exactly the "is this already encoded?" ambiguity that leads to double-encoding bugs when a later-added stage (e.g., a new API endpoint returning this data as JSON for a JavaScript frontend, which then also escapes it for HTML display) doesn't know the data retrieved from storage is already HTML-encodedand applies its own encoding on top.


The "missing encoding" problem: the opposite, and more dangerous, failure mode

While double-encoding produces visible, annoying, but not directly security-critical artifacts (& displaying instead of & is a display bug, not, by itself, an XSS vulnerability) — the opposite failure — missing encoding entirely — is directly security-relevant, as covered in the previous XSS article.

A system that tries to "fix" double-encoding by removing one of the encoding stepsif removed from the wrong stage (e.g., removing the final, output-time encoding, rather than an earlier, storage-time encoding) — could introduce an XSS vulnerability where previously there was "merely" a double-encoding display bug"fixing" double-encoding by removing encoding from the wrong place can trade a cosmetic bug for a security vulnerability.

The correct fix is always: ensure encoding happens exactly once, at the final, output-time stageremoving encoding from earlier (storage/processing) stages, NOT from the final, output-time stagethis requires understanding the full pipeline (where is data encoded? Where is it stored? Where is it finally output?) — a "quick fix" applied without this understanding risks fixing the visible symptom (double-encoding artifacts) while introducing the invisible, more serious problem (missing output-time encoding, i.e., an XSS vector).


Decoding entities: also a one-time operation, in the opposite direction

Just as encoding should happen once, at outputdecoding (converting & back to &, for processing purposes) should also happen, if at all, in a controlled, single, well-understood locatione.g., if receiving data from an external source that provides it in HTML-entity-encoded form (some APIs/feeds do this), and your system needs the raw value (for processing, comparison, storage) — decoding once, upon receipt, before any further processingand then re-encoding (once) at outputmaintains the "raw internally, encode once at output" principle, even when external data sources provide pre-encoded content.

A system that receives & from an external source, and passes it through, unchanged, to HTML outputwithout decoding first — would display the literal text & (since the output-time HTML encoding step, applied to the already-encoded &, would produce &, displaying as &) — this is, again, the "double encoding" pattern, just with the "first encoding" having occurred at an external source, outside your own system's direct control.


How to use the HTML Entities tool on sadiqbd.com

  1. For diagnosing double-encoding: if you're seeing & (or similarany entity name with "amp;" prefixed, like <, >, etc.) in rendered outputdecoding the displayed text once (using this tool) should reveal the "intended" single-encoded form (&, <, etc.) — confirming double-encoding as the issue
  2. For establishing a "raw data" baseline: if migrating a system away from "store pre-encoded" toward "store raw, encode at output" — this tool can help decode existing, stored, pre-encoded data back to its raw form, as part of a data-migration process
  3. For testing output-encoding logic: encode known raw strings (containing &, <, >, quotes) and verify your system's output-time encoding produces the expected, single-encoded resultand that this result, if passed through any additional downstream encoding steps in your pipeline, doesn't become double-encoded

Frequently Asked Questions

Is double encoding ever intentional/correct? Generally, nodouble-encoding is, essentially always, a bug, reflecting an uncoordinated pipeline (multiple stages each applying encoding, without awareness of each other). There's no common, legitimate use case for "encode this twice, on purpose"if you're seeing double-encoded output, the appropriate response is to trace the data's path through your system and identify where encoding is being applied more than once, removing all but the final, output-time applicationnot to treat double-encoding as "the correct output" and build further logic around it.

Is the HTML Entities tool free? Yes — completely free, no sign-up required.

Try the HTML Entities tool free at sadiqbd.com — encode and decode HTML entities, and diagnose double-encoding issues instantly.

Share: Facebook X WhatsApp LinkedIn Email

HTML Entities

Free, instant results — no sign-up required.

Open HTML Entities →
Similar Tools
URL Encoder/Decoder Regex Tester Password Generator UUID Generator Timestamp Converter Base64 Encoder/Decoder JSON Formatter Random String Generator
HTML Entities — Encode & Decode Special Characters Correctly
Developer
HTML Entities — Encode & Decode Special Characters Correctly
HTML Entities — Encode & Decode Special Characters for Correct, Safe HTML
Developer
HTML Entities — Encode & Decode Special Characters for Correct, Safe HTML
XSS and HTML Encoding: The Five Contexts That Require Different Escaping
Developer
XSS and HTML Encoding: The Five Contexts That Require Different Escaping
Unicode Fundamentals: ASCII History, UTF-8 Encoding, Byte Order Marks, and Why Mojibake Happens
Developer
Unicode Fundamentals: ASCII History, UTF-8 Encoding, Byte Order Marks, and Why Mojibake Happens
In UTF-8, Most HTML Entities Are Unnecessary — But These Five Still Are
Developer
In UTF-8, Most HTML Entities Are Unnecessary — But These Five Still Are
HTML Encoding Doesn't Stop XSS in JavaScript Context — Why CSP Nonces Are the Missing Second Layer
Developer
HTML Encoding Doesn't Stop XSS in JavaScript Context — Why CSP Nonces Are the Missing Second Layer