🪢 String Escape / Unescape
Convert strings between HTML entities, JavaScript strings, JSON strings, Unicode escapes (\uXXXX), and URL encoding.
📖 Examples
| Format | Raw | Escaped |
|---|---|---|
| HTML | <a> | <a> |
| JS | It's 'ok' | It\'s \'ok\' |
| JSON | tab here | tab\there |
| Unicode | 日本語 | \u65e5\u672c\u8a9e |
| URL | a b&c | a%20b%26c |
🔗 Related Tools
📖 Where people get stuck
Escapes and unescapes strings in fourteen formats: HTML entities, JavaScript strings, JSON, Unicode (\uXXXX), URL, CSV, SQL, regular expressions, shell and more. Everything runs in the browser. Escaping, though, is not "transforming a string" but "conforming to the grammar of the destination" — this tool does not know your destination, so it cannot decide which format you should pick. And applying the wrong format produces a worse outcome than doing nothing, because it feels safe while protecting nothing.
| Case | What happens | What to do |
|---|---|---|
| A different context needs a different escape | The same value needs different handling depending on where it lands. Inside a <div>, entity encoding is enough; inside href="..." it must also be valid as a URL; and inside onclick="..." it has to satisfy both the JavaScript and the HTML layer at once. There are also contexts where HTML escaping does nothing at all — a value beginning with javascript: in an href still executes after entity encoding, and inside <style> or <script>, < is treated as literal text while the syntax stays open. In other words, there are places where "HTML-escape it and move on" simply does not apply. |
Escape at the moment of output, and let the templating engine do it. The correct approach is to use a mechanism where you can name the context: |e('html_attr'), |e('js') and |e('url') in Twig, JSX in React, html/template in Go. Abandon any design that escapes on input and stores the escaped form — a stored value rarely has a single destination; it flows into email bodies, CSV exports and API JSON alike. Always store the raw value and escape it for the local context every time you output it. That single principle removes almost everything listed above. Use this tool as the place to eyeball whether the result is right. |
Double escaping (&lt; shows up on screen) |
This is when <strong> or a bare & is visible on screen. The cause is almost always that the value was escaped twice, classically by the application escaping on save and the template engine escaping again on display. What makes it nasty is how quietly it hides — nothing happens for data made of letters and digits, and only the rows containing an apostrophe or an & in a name come out broken. Worse, the corrupted data is already in the database, so fixing the display side does not fix it. The reverse accident exists too: a \n in JSON is escaped a second time into \\n, so what should be a line break arrives as two visible characters instead. |
First, work out which side is doubling. Paste the raw database value here and select the unescape direction with HTML. If the value changes, it was already escaped when it was stored — the cause is on the input side. If it does not change, the doubling is happening at display time. Repair it with a one-shot migration, and always scope the target (WHERE body LIKE '%&%'). Running html_entity_decode unconditionally over every row will corrupt the rows that legitimately wanted to say &. Take a backup and count the affected rows before you run it. |
| Escaping is not sanitizing | HTML escaping is a procedure for displaying something safely as text, not a procedure for safely rendering HTML that a user wrote. Where you do want to allow tags, as in rich-text posts, you need a sanitizer with an explicit allowlist of tags and attributes. The same misunderstanding recurs elsewhere. Escaping an SQL string ('') is no substitute for placeholders — table and column names, the direction in ORDER BY, and the LIKE wildcards % and _ all fall outside what string escaping covers. Shell quoting is the same: quotes cannot stop a value like -rf from being interpreted as an option. |
Change the tool according to the purpose. If you allow tags, use a dedicated sanitizer (HTML Purifier in PHP, DOMPurify in JS), and do not try to strip tags with a regular expression of your own — homemade attempts in that direction are broken without exception. Always use placeholders for SQL, and for the parts you cannot bind, such as table names or sort order, match against an allowlist (accept only values present in ['name','created_at']). For the shell, use an API that passes arguments as an array (the execve family, or subprocess.run([...]) in Python), and place -- before user input to end option parsing. |
Unicode escapes hide a trap outside the BMP. \uXXXX can only express sixteen bits, so emoji and some Han characters split into a surrogate pair — one emoji becomes the two units \ud83d\ude00. Counting characters or truncating at that point splits a character in half and corrupts it. From ES6 onward you can use the single form \u{1f600}. There is a second consequence: this habit of turning non-ASCII into \uXXXX obstructs verification — this very site twice concluded a deploy had failed because it grepped for Japanese text that the template had escaped for JS. The correct procedure is to decode \uXXXX before searching. One last rule to keep: never hand an unescaped string to any execution path other than JSON.parse, and never to eval. Decoding is an operation for inspection, not for execution.
📖 How to Use
-
1
Choose format and directionSelect the format (HTML, JavaScript, JSON, Unicode, URL, etc.) and direction (escape or unescape).
-
2
Enter your textPaste or type text in the left input field. The conversion happens in real time.
-
3
Copy or swap the resultCopy the output on the right, or click the swap button to reverse input/output and convert in the opposite direction.
❓ Frequently Asked Questions
What is the difference between HTML escape and URL encoding?
Can it escape non-ASCII characters like Japanese?
Can this be used to prevent SQL injection?
🐛 Found a bug or issue with this tool?
Free to use, no signup. Even just the steps to reproduce are helpful. Reports go directly to the operator and help us fix issues.
Thanks for your report!
Your report has been delivered to the operator and will be used to improve the tool.