String Escape Tool
Escapes and unescapes text for JSON, JavaScript strings and template literals, HTML text and attributes, XML, URLs, CSV, SQL, regex and shell. Compares every target at once, reports round-trip fidelity, and warns where escaping alone is not safety.
🔒 This tool runs entirely in your browser. Your files are never uploaded to a server.
The same text, every target
Escaping is per-context. Comparing them side by side is the quickest way to see that one is not a substitute for another.
| Target | Result | Round trip |
|---|
Escaped in this page; nothing is uploaded. Escaping is always relative to a destination — text that is safe in one context can be dangerous in another, which is why the target is an explicit choice here rather than a single "escape" button.
How to use it
- Paste your text and choose where it is going — the target is the whole question.
- Read any warning shown under the picker; two targets have real caveats.
- Use the comparison table to see how differently the same text escapes.
- Switch to Unescape to go the other way, on any target but the shell.
Escaping is meaningless without a destination
There is no such thing as an escaped string, only a string escaped for something. The same eleven characters escape completely differently depending on where they are going:
input a & b < c "d" 'e'
HTML text a & b < c "d" 'e' quotes untouched
HTML attribute a & b < c "d" … quotes matter here
JSON a & b < c \"d\" 'e' only the double quote
shell 'a & b < c "d" '\''e'\''' wrap and reopen
Notice that HTML text escaping leaves both quote characters alone. That is correct for text between tags and actively dangerous in an attribute — which is the single most common escaping mistake, and the reason those are separate targets here rather than one "HTML" option.
The attribute trap, demonstrated
This is worth seeing concretely because it is so easy to get wrong. Take a value designed to break out of an attribute:
payload x" onmouseover="alert(1)
text-escaped, in an attribute:
<img alt="x" onmouseover="alert(1)"> ← handler is real
attribute-escaped:
<img alt="x" onmouseover="alert(1)"> ← inert
The text-escaped version passes through the three characters HTML text cares about, keeps the double quote, and the browser
cheerfully reads onmouseover as a genuine attribute. There is also a
case escaping cannot rescue: an unquoted attribute value ends at the first space, so
<img alt=x onmouseover=alert(1)> breaks out with no quote
involved at all. Quote your attributes.
Why the SQL target carries a warning
Doubling single quotes is the correct way to put a literal quote inside a SQL string, and it is not a defence against injection. The distinction is exact and worth stating plainly:
WHERE name = '<value>' doubling contains the quote — fine
WHERE id = <value> no quote to double — 1 OR 1=1 passes
Escaping is a text transformation; injection is a parsing problem. The only reliable fix is to stop the value reaching the parser as SQL at all, which is what a parameterised query does. This target exists for building fixtures, reading logged statements and writing migrations by hand — not for user input.
The shell trick, verified by running it
Single quotes are the strongest quoting a POSIX shell offers: nothing inside them expands — no variables, no command substitution, no globbing. The awkward part is that a single-quoted string cannot contain a single quote at all, not even with a backslash. The idiom is to close the quote, emit an escaped quote, and reopen:
it's fine → 'it'\''s fine'
└'it'┘└\'┘└'s fine'┘
Rather than trust that, the output was executed. Nine values — including $HOME,
a backtick command substitution, rm -rf /; echo pwned, a backslash,
several embedded quotes and an embedded newline — all came back from the shell byte-for-byte unchanged, with no expansion and
nothing run. That is the property you actually want and the only way to be sure of it is to try it.
Round-tripping as a correctness check
An escaper that loses information is worse than none, because the damage is invisible until something downstream breaks. So every reversible target here was escaped and then unescaped and compared against the input, across fourteen samples chosen to be awkward: both quote characters, a backslash, a tab, a CRLF pair, a null byte, emoji, Japanese text, regex metacharacters, a script tag and the empty string. All returned the original exactly.
The single-quoted JavaScript output got an extra check, because deriving it from a double-quoted encoder is the kind of shortcut that produces subtly invalid code: each result was evaluated as actual JavaScript and compared with the original string. The comparison table reports the round-trip status per target live, so you can see it for your own input rather than taking this on trust.
FAQ
Why are there twelve targets instead of one escape button?
Because escaping only means anything relative to a destination. The characters that need protecting in a JSON string, an HTML attribute, a shell argument and a regular expression are different sets, and the escape sequences differ too. A single button would have to pick one silently and would be wrong most of the time. The comparison table shows the same input escaped every way at once, which makes the point faster than any explanation.
Is HTML escaping enough to stop XSS?
Only if you escape for the right context. Text escaping handles the three characters that matter between tags, but it leaves quotes intact — so a value like x" onmouseover="alert(1) placed into alt="..." closes the attribute and the handler becomes real markup. Attribute escaping also handles both quote characters. And no amount of escaping saves an unquoted attribute, because there is no quote to escape and a space alone ends the value.
Can I use the SQL target to make user input safe?
No. Doubling quotes only contains a value that is already inside a quoted literal. In a numeric position there is no quote to double, so 1 OR 1=1 passes through untouched and you get WHERE id = 1 OR 1=1. Use parameterised queries or prepared statements — the database then never parses your value as SQL at all. The SQL target here is for building test fixtures and reading logs, not for handling untrusted input.
Why does the template literal output look shorter?
Because a JavaScript template literal only treats three things as special: the backtick, the backslash and the ${ sequence. Both kinds of quote are ordinary characters inside one, so they are left alone. It is a genuinely different escaping problem from a single or double quoted string, which is why it has its own target.
Does escaping ever change my text?
It should not, and that was checked. Every reversible target was round-tripped — escape, then unescape, then compare — across fourteen awkward samples including both quote characters, a backslash, tabs, a CRLF pair, a null byte, emoji, CJK text, regex metacharacters and the empty string. All returned the original exactly. The single-quoted JavaScript output was additionally evaluated as real JavaScript to confirm it produces the original string.
Why can the shell target not be reversed?
Because many different escaped forms produce the same string, so there is no single correct way back. What matters is that the forward direction is right, and that was verified by executing the output: nine values including $HOME, a backtick command substitution, and rm -rf /; echo pwned all came back byte-for-byte unchanged, with nothing expanded and nothing run.
How we compare
| Feature | Online Tool Store | Single-purpose escapers | A one-line function you wrote |
|---|---|---|---|
| Text never leaves your device | ✓ | ✗ | ✓ |
| Separates HTML text from attribute context | ✓ | Rarely | Usually not |
| Shows the round-trip status live | ✓ | ✗ | ✗ |
| Warns that SQL escaping is not injection safety | ✓ | ✗ | ✗ |
| Compares every target at once | ✓ | ✗ | ✗ |
| Runs inside your own build pipeline | ✗ | ✗ | ✓ |
| Context-aware templating that escapes for you | ✗ | ✗ | ✗ |
Use this for one-off conversions and for settling which escaping a context actually needs. In production code, prefer a templating engine or query builder that knows the context and escapes automatically — hand-escaping is where the mistakes live, and the point of the warnings here is to make that clear rather than to encourage it.