KeroTools

HTML Entity Encoder and Decoder

Encode text to safe HTML entities or decode them back, instantly — a free tool for developers.

Input
0 chars
Output

Your text stays on your device

Nothing to delete afterwards

Safe for real user data

Works in every modern browser

How it works

  1. 1

    Paste your text

    A string with angle brackets, an ampersand, quotes or accented characters that has to sit inside markup.

  2. 2

    Choose the context

    Text content, attribute value, or full encoding — each escapes a different set of characters.

  3. 3

    Copy the result

    Paste it into a template, an XML document, a feed or an email body.

Why use this tool

Context is a choice, not a guess

Escaping for text content, for an attribute value and for a URL are different jobs, and you pick which one.

Double encoding is caught

An input that already contains entities is flagged, so you do not turn an ampersand into an ampersand entity twice.

Named or numeric output

Numeric references work in XML, feeds and SVG, where most named entities are simply undefined.

Decoding is round-trip safe

Both named and numeric forms are recognised, including the hexadecimal spelling and the entities without a semicolon.

Honest about what escaping does

It makes text safe to place in a context, which is a smaller claim than making untrusted HTML safe.

Nothing leaves the browser

Text is converted on this page, so the ticket contents and customer names you are testing with stay yours.

There is no single “escape for HTML” — the context decides

This is the idea that makes the rest of the subject make sense. A browser parses a document in several different states, and the characters that can end the current state are different in each one. Inside text content, only `<` and `&` can start something new, so those are the two that must be escaped. Inside a double-quoted attribute value, `<` is harmless and `"` is fatal, because the quote ends the attribute. Inside an unquoted attribute value, a space ends it, and so do a tab, a newline, a backtick, an equals sign and a greater-than sign. Inside a `<script>` block, HTML escaping does nothing useful at all and JavaScript string escaping is what you need. This is why a single `escape()` helper applied everywhere produces both broken output and real vulnerabilities: it over-escapes where the characters were safe, and under-escapes where they were not. Choosing a context before you encode is not a nicety — it is the whole decision.

Only a handful of characters ever have to change

It is worth knowing exactly how short the list is, because most over-escaping comes from not knowing. The characters with syntactic meaning in HTML are `<`, `>`, `&`, `"` and the apostrophe. Of those, `&` always needs escaping because it starts an entity, and `<` always needs escaping because it starts a tag. `>` is a courtesy rather than a requirement in text content — a browser renders a bare `>` fine — though escaping it is habit in most codebases because it costs nothing and helps when markup is later processed by something stricter. The two quotes matter only inside attribute values, and only the one you used as the delimiter. Everything else, including every accented letter, every Arabic or Chinese character, every emoji, needs no escaping at all in a UTF-8 document: the encoding already handles them. Turning `café` into `caf&eacute;` is legal and almost always pointless, and it makes your file larger and harder to search.

Double encoding is the bug this tool exists to prevent

Escaping is not idempotent, and forgetting that produces one of the most recognisable defects on the web. Encode `&` once and you get `&amp;`. Encode the result again and you get `&amp;amp;`, which renders on the page as the literal text `&amp;`. You have seen it: page titles reading “Tom &amp; Jerry”, email subject lines with `&#39;` in the middle of a word, product names with `&quot;` around them in search results. It happens because escaping was applied at two layers that did not know about each other — a template engine that auto-escapes, plus a controller that escaped defensively before handing the string over. The fix is never to escape twice, and the way to be sure is to escape exactly once, at the last possible moment, at the point where the string enters the markup. Anything stored escaped in a database will eventually be escaped again by whatever renders it.

Named entities are an HTML feature, not a text feature

HTML5 defines more than two thousand named entities, from the familiar `&nbsp;` and `&copy;` to things like `&bigotimes;`. XML defines exactly five: `&lt;`, `&gt;`, `&amp;`, `&quot;` and `&apos;`. That gap causes a specific and common failure. Put `&nbsp;` into an RSS feed, an SVG file, an XHTML document, an Android layout or a SOAP payload and you get a parse error, because the parser has never heard of it and an undefined entity is fatal in XML rather than merely ignored. The numeric form `&#160;` works everywhere, since it needs no definition. There is a matching trap in the other direction: `&apos;` is one of XML’s five but was not in HTML4, so old HTML documents and some email clients render it as literal text. If a string might travel between formats — and most strings in a modern stack do — numeric references are the safe spelling.

Escaping is not sanitisation, and the difference matters

These two get conflated constantly, and the conflation is where injection bugs live. Escaping takes text and makes it safe to place into a particular context, so that it is displayed rather than interpreted. Sanitisation takes markup that is meant to remain markup and removes the dangerous parts of it. Escaping a comment before printing it is correct; escaping a rich-text field the user is allowed to format destroys the formatting, and the usual response — allowing the HTML through unescaped — is what actually opens the hole. The sharpest example of the difference is a URL: entity-encode a link and `javascript:alert(1)` survives completely intact, because entity decoding happens before the URL scheme is checked, so `&#106;avascript:` becomes `javascript:` and runs. No amount of HTML escaping protects an `href`; only validating the scheme does. Escaping solves exactly one problem, and knowing which one is the point.

Why converting locally matters for this particular job

The strings people bring to an entity encoder are unusually sensitive, because of what the job is. You escape text when it came from somewhere you do not control: a support ticket, a customer name, a form submission, a comment, an imported product feed, an error message containing part of a request. Testing an encoder means pasting a real example of exactly that — the message that broke, with the customer’s apostrophe and the customer’s name still in it. Pasting it into a hosted encoder means uploading the untrusted user data you were trying to handle carefully, to a third party, for a transformation your browser can do in a single pass. This page converts the text in JavaScript and issues no request while it does; the same developer tools you would use to debug the escaping will confirm it.

Common mistakes to avoid

  • Using one escape function everywhere. Text content, attribute values and script blocks end on different characters, so a single helper over-escapes in one place and under-escapes in another.
  • Escaping the same string twice. Escaping is not idempotent — `&` becomes `&amp;` and then `&amp;amp;`, which is why page titles end up reading “Tom &amp; Jerry”.
  • Putting named entities into XML. Only five are defined there, so `&nbsp;` is a fatal parse error in a feed, an SVG or an XHTML document; `&#160;` works everywhere.
  • Escaping accented or non-Latin characters. In a UTF-8 document they need no escaping at all — converting `café` to `caf&eacute;` only makes the file bigger and harder to search.
  • Trusting entity encoding to make a URL safe. Entities are decoded before the scheme is checked, so `&#106;avascript:` becomes `javascript:` and runs; only validating the scheme helps.

How it compares

AspectThis toolOnline encodersA language library
Text sent to a serverNeverUsually yesNo
Lets you pick the contextYesRarelyUsually
Warns about double encodingYesNoNo
Numeric output for XMLYesSometimesConfigurable
Decodes the full HTML5 named setYesPartiallyUsually
PriceFreeFree / paid tiersFree

Features

Encode and decode

Both directions, so you can check what a system produced as easily as prepare what you are about to send.

Minimal or full encoding

Escape only the characters the context requires, or every non-ASCII character, depending on where the text is going.

Named entity support

The full HTML5 named set is recognised when decoding, including the long tail almost no one types by hand.

Hexadecimal and decimal

Numeric references are read and written in both spellings, since real documents contain both.

Double-encoding detection

Existing entities in the input are highlighted before you encode them a second time.

Large inputs supported

A whole template or a long export converts without an upload or a size ceiling.

Nothing to install

No build tool, no runtime, no dependencies — it runs in the web page.

Arabic and RTL ready

The full interface in eight languages, including right-to-left Arabic.

Secure by default

Served over HTTPS, with no content tracking and no third-party upload.

Who uses it

Web developers

Checking how a string will behave once it is inside an attribute value.

Email developers

Preparing subject lines and body text for clients that parse strictly.

Technical writers

Showing code samples in a page without the browser trying to run them.

Anyone debugging mojibake

Decoding a string that arrived with `&amp;amp;` in the middle of it.

Frequently Asked Questions

No. Everything runs locally in your browser — your text is never uploaded, stored, or shared.

Yes — completely free, with no account and no limits.