HTML Formatterhtmlformatteronline.com

HTML entity encoder and decoder

Escape reserved characters so they display instead of being read as markup — or decode entities back into readable text.

Input 0 lines
Encode
Escaped 0 lines
Paste text on the left and press Encode, or switch to Decode.

The five that matter

HTML reserves a handful of characters. Put one in your text unescaped and the browser reads it as markup, which is how a stray < swallows the rest of your paragraph — and how a stray <script> in user input becomes a cross-site scripting hole.

CharacterNamedNumericEscape it when
&&amp;&#38;Always — it starts every other entity
<&lt;&#60;Always
>&gt;&#62;Always, by convention
"&quot;&#34;Inside double-quoted attribute values
'&apos;&#39;Inside single-quoted attribute values

Escape the ampersand first when you do this by hand. Escape it last and you will turn every &lt; you just created into &amp;lt;.

When you actually need this

Showing code on a page. To display <div> as text rather than create a div, it has to be written &lt;div&gt;. Every code example on this site is escaped this way.

Putting text into an attribute. A product name containing a quotation mark will end the attribute early and produce markup you did not write.

CDATA-free XML and RSS. Feed descriptions carrying HTML must either be escaped or wrapped in CDATA. Escaping is the more portable of the two.

CSV and spreadsheet exports. Text pulled out of a CMS often still contains entities. Decoding turns Caf&eacute; back into Café before the file reaches anyone.

Reading scraped markup. Decoding makes a page's text readable again after the HTML has been stripped.

Named or numeric

Both do the same thing. &mdash; and &#8212; both produce an em dash.

Named entities are readable — you can tell what &pound; is without looking it up. There are over 2,000 of them in the HTML5 specification, and this tool uses the several dozen that come up in practice.

Numeric references work for every character that exists, including ones with no name, and they are valid in XML where most named entities are not. XML defines only five named entities; use anything else in an XML document and the parser will reject it.

Untick Use named entities to get numeric references throughout. That is what you want when the output is going into XML, an RSS feed or a sitemap.

The one you almost certainly do not want

&nbsp; is a non-breaking space. It looks like a space, but no line break can happen at it, and consecutive ones are not collapsed. It has two legitimate uses: keeping a number with its unit (50&nbsp;kg) and keeping a name together (Mr&nbsp;Smith).

Everywhere else it is a symptom. WYSIWYG editors emit runs of them for indentation, which produces text that will not wrap on a phone and cannot be reflowed. If you are pasting content in and find dozens, the code cleaner is the page you want — decoding them to plain spaces here first makes them easy to find.

Escaping is not the same as sanitising

Escaping is the right defence when you are inserting untrusted text as content — it guarantees the text will be displayed rather than executed.

It is not enough when the text goes into a URL attribute, an inline style, or a <script> block. Each of those has its own escaping rules, and a javascript: URL survives HTML escaping perfectly intact. If you are accepting rich HTML from users, use a sanitiser with an allow-list — DOMPurify on the client, or the equivalent in your server language — rather than escaping by hand.

Doing it in code

JavaScript
const escapeHtml = s => s.replace(/[&<>"']/g, c => ({{
  "&": "&amp;", "<": "&lt;", ">": "&gt;", '"': "&quot;", "'": "&#39;"
}}[c]));

// safest of all: let the DOM do it
element.textContent = untrustedString;
Python
import html
html.escape('<a href="x">&</a>')   # &lt;a href=&quot;x&quot;&gt;&amp;&lt;/a&gt;
html.unescape("Caf&eacute;")       # Café

In a template language you rarely need any of this: Jinja, Twig, Liquid, Blade, ERB and React all escape interpolated values by default. The bugs happen at the point where someone reaches for innerHTML, dangerouslySetInnerHTML or a "raw" filter to get around it.

Questions about this tool

Should I escape every accented character?

No. Any page served as UTF-8 — which is every page you should be writing — handles é, 日 and 🎨 natively. The Escape all non-ASCII option exists for legacy systems that mangle anything outside ASCII, not as a default.

Why is &apos; sometimes a problem?

It is valid in HTML5 and in XML, but not in HTML 4, and Internet Explorer 8 rendered it as literal text. If you need to support anything that old, use &#39; instead — which is what this tool emits when named entities are turned off.

Can I decode entities with a textarea trick instead?

Setting innerHTML on a detached element and reading back textContent does decode entities, and it is a well-known trick. It also parses the string as HTML, which means untrusted input can trigger side effects. This tool decodes with an explicit table instead, which has no such surface.

What happens to entities the tool does not know?

They are left exactly as they are and listed underneath, so nothing is silently corrupted. All numeric references decode regardless, since those need no lookup table.

Related tools

Learn the why, not just the how

Longer reading on formatting, indentation and minification.