HTML Context Escaper
Escape a string for the HTML element, attribute, JavaScript or URL context — OWASP output-encoding rules applied per sink, entirely on this device.
Escaped output goes in element body text: <p>HERE</p>
Press ? for shortcuts
Do it offline:$ jq -Rsr @html file.txt
How to use it
- Pick the destination — HTML element body, HTML attribute value, JavaScript string or URL component; each option shows a placement hint.
- Paste the text. The result updates as you type; big inputs run in a background worker.
- Switch context at will — the same input is re-escaped in place, and chips name the rule and count its rewrites.
- Copy or download the result; Share makes a link of input plus context, asking first if it looks like a credential.
Where a string lands decides how to escape it: an HTML element body, an attribute value, a JavaScript string and a URL component each reserve different characters. Pick the destination and the matching OWASP output-encoding rule runs as you type — named references, &#xHH; references, \xHH escapes or %HH bytes — with chips counting every rewrite. Nothing you paste leaves this device.
Examples
5 > 3 && "it's"5 > 3 && "it's"The narrowest rule of the four: exactly five characters — & < > " ' — become named references, 6 of 15 here per the count chip; everything else passes untouched (OWASP rule 1).
" onmouseover="alert(1)" onmouseover="alert(1)A quote closes the value, a space starts a new attribute, an equals sign gives it one. Every non-alphanumeric code point below U+0100 becomes &#xHH; — all six syntax characters land inert (OWASP rule 2).
</script>\x3C\x2Fscript\x3EThe HTML parser ends a script element at the first </script>, string literal or not; spelled \x3C\x2Fscript\x3E, no tag exists, yet the lexer reads the same nine characters (OWASP rule 3).
I ♥ 😀I\x20\u2665\x20\uD83D\uDE00Output stays pure ASCII: the heart is one \u2665 escape, and the emoji above U+FFFF is written as its two UTF-16 units, \uD83D\uDE00 — a chip names the surrogate rewrite.
O'Brien & Sons/50%O%27Brien%20%26%20Sons%2F50%25Only RFC 3986's unreserved characters survive: space, ampersand, slash and percent each cost one %HH byte, and the apostrophe is escaped too, unlike encodeURIComponent — jq's @uri prints this exact string.
Every example on this page is executed against the same engine that powers the tool, on every build.
Gotchas worth knowing
Unquoted attributes end at more than a quote
HTML bars an unquoted attribute value from containing spaces, quotes, equals signs, angle brackets or backticks. Rule 2's blanket scope covers that set — one output, safe double-quoted, single-quoted or bare.
A JavaScript string cannot hide </script>
The tokenizer scanning a script element looks only for its closing tag, blind to string boundaries — a literal </script> inside quoted code still ends the block. Escaped, the tag shape never appears.
' and ' are the same escape
The OWASP table spells the apostrophe '; this page emits ' — in HTML since HTML5, the identical U+0027 everywhere, and native to XML.
Five characters stricter than encodeURIComponent
The url context also escapes ! * ' ( ) — which encodeURIComponent leaves raw — because RFC 3986 §2.3 grants unreserved status only to letters, digits and -._~ (OWASP rule 5).
One emoji, four spellings
😀 passes the element and attribute contexts raw — an attribute chip counts it — becomes the two escapes \uD83D\uDE00 in a JavaScript string, and spends four %HH bytes, %F0%9F%98%80, in a URL.
Past the 1 MB line, nothing is escaped
An oversized input is refused whole, because a partial escape of markup-bound text would read as finished. The banner prints the limit and the jq line; @html covers the same five element-context characters.
Common errors
Input is larger than the 1 MB limit for this tool. For bigger payloads use the CLI: jq -Rsr @html file.txt- The page escapes all of the input or none of it; your paste stays in the pane. The named command handles the element context at any size — jq's @uri filter is the url-context equivalent.
input contains an unpaired surrogate; it was encoded as U+FFFD- Half of a two-unit character arrived alone — text clipped mid-emoji by a length limit or byte-level splice upstream. The engine substitutes U+FFFD so every context emits well-formed output, and warns once.
input already contains HTML character references — escaping it again will double-escape them- An informational chip, never a refusal: the transform runs verbatim, so & in element context becomes &amp;. If the text is already escaped for this sink, escape the raw original instead.
FAQ
Why does one page need four escape rules?
Each destination parses by a different grammar: an element body reserves only markup characters, an attribute may be unquoted, and scripts and URLs add syntax of their own. OWASP numbers these output-encoding rules 1, 2, 3 and 5 — rule 4, the CSS string context, is deliberately absent.
Is escaping the same thing as sanitizing?
No. Escaping rewrites characters so a string reads as inert data in the context you chose — it parses nothing and removes nothing. Rendering untrusted HTML as live HTML is a sanitizer's job, a parser that filters a document tree. This page escapes strings; it promises nothing wider about your site.
Why does the attribute output escape spaces and equals signs?
An unquoted value ends at its first space, and HTML bars it from carrying quotes, equals signs, angle brackets or backticks. Rewriting the whole sub-U+0100 punctuation set as &#xHH; references makes one output safe however the attribute ends up quoted at its destination.
Why \x3C rather than a backslash-quote shortcut?
The string crosses two parsers in order — the HTML parser, then the JavaScript lexer — and a backslash protects nothing at the HTML layer: \" still leaves a live quote that can end an attribute early. \xHH and \uXXXX escapes put only a backslash, letters and digits in the markup (OWASP rule 3).
Keyboard shortcuts
- ⌘/Ctrl + Enter
- Re-run the escape at any input size.
- ⌘/Ctrl + S
- Download the output as a .txt file (this saves the text, not the page).
- ⌘/Ctrl + C
- Copy the full escaped output when the selection is empty.
- ⌘/Ctrl + Shift + C
- Force-copy the escaped output even mid-selection.
- t
- Advance the color theme (inert while typing or composing).
- ? or ⌘/Ctrl + /
- Show keyboard help, browser-conflict notes included.
- Esc
- Dismiss the topmost overlay — pasted text stays put.