JSON Escape / Unescape
Escape raw text or a whole file into a JSON-safe string, unescape a JSON string back to plain text, or force ASCII-only output. Everything runs in your browser.
- Free, no account
- No watermark
- No usage limit
About the JSON Escape / Unescape
Most JSON escapers hand you a text box and stop there. This one takes a whole file. Drop a private key, a certificate, a SQL dump, or a messy log straight into the box and get back a JSON-safe string with every quote, backslash, and real line break already turned into \", \\, and \n. The file is read right here in your browser and never sent anywhere, so escaping a .pem key or an access token is safe in a way that pasting it into a random online tool never is. Escape goes one way, unescape brings it back, and there is an ASCII-only mode for the systems that still demand it.
The whole job happens at the string layer. Escape adds the backslashes JSON needs so your text slots inside a {"...": "..."} without breaking the parser, and Unescape takes them back out again. Hand it He said \"hi\"\nbye and you get the original text back, real line break and all.
How to use
- Pick a mode. Leave it on Escape to turn raw text into a JSON-safe string. Switch to Unescape to decode an already-escaped string back to plain text.
- Get your input in. Type it, paste it, or click Open a file. Dragging a file onto the box works too, and so does pasting a copied file. A whole file lands in the box as text, ready to escape.
- Set your options (escape mode). Tick Wrap in double quotes for a complete
"value"you can drop in as is. Tick escape the forward slash if the JSON is heading into an HTML page. Tick ASCII-only to force every accented letter, CJK character, and emoji into a\uXXXXescape. - Read the result. It updates live as you type or change an option, no button to press. A small counter shows the input size and the output size in characters and bytes, useful when a field has a length cap.
- Take it with you. Copy the result, or hit Download .txt for a large escaped file. Swap moves the result up into the input and flips the mode, so you can round-trip a string and confirm it survives.
- Clear wipes the input when you are done.
If you are unescaping and the input has a broken escape, a lone backslash or a \u without four hex digits after it, the result clears and a short message tells you what is wrong and roughly where, so nothing gets silently corrupted.
Escape a whole file, keys and certs included
This is the part the other tools skip. Private keys, TLS certificates, and service-account files are exactly the things you need as a JSON string value (a Kubernetes secret, a CI variable, a Terraform input), and they are also exactly the things you must never paste into a website that uploads what you give it. A .pem file is a stack of base64 lines wrapped in -----BEGIN----- markers, and JSON wants that as one string with each line break written as \n. Drop the file here and you get that string in a single step, with the file itself staying on your machine the whole time.
The same goes for a big SQL query, an HTML email template, or a multi-line log entry you are stuffing into a webhook payload. Anything with real newlines cannot sit raw inside a JSON string, and fixing every line by hand is miserable and error-prone. Hand it the file and move on.
Which characters actually need escaping
Inside a JSON string, RFC 8259 says two characters must always be escaped:
"(double quote) becomes\", because a bare quote ends the string early and the parser throws a syntax error right on that spot.- **
\(backslash)** becomes\\, because the backslash is the escape character itself. A literal backslash in your data has to be doubled.
Then come the control characters, everything below U+0020, which JSON refuses to accept raw. Five of them have short readable forms you will run into constantly: \n (newline), \r (carriage return), \t (tab), \b (backspace), and \f (form feed). Any other control character, a null byte or a vertical tab say, has no shorthand, so JSON writes it as \uXXXX. This tool uses the short form where one exists and falls back to \u for the rest. You rarely type these, but they sneak in from pasted data, exported files, and terminal output, and they are the reason a payload that looks fine still will not parse.
Everything else is left alone. Letters, digits, spaces, punctuation like !@#$%, and Unicode such as café or 你好 all sit inside a JSON string untouched, unless you switch on ASCII-only mode.
The ASCII-only mode, and why anyone needs it
By default the tool keeps your café as café, because modern JSON is Unicode and readable text is easier to work with. But some setups still want plain ASCII: an old parser that chokes on high bytes, a logging pipeline that mangles anything above 127, a diff you want stable across encodings. Tick ASCII-only and every non-ASCII character turns into its \uXXXX escape, so café becomes café and an emoji becomes a surrogate pair like 😀.
If you have ever compared this kind of tool against Python and they disagreed, this is usually the reason. Python's json.dumps escapes non-ASCII characters by default (ensure_ascii=True), so its output is full of \u sequences. Switch on ASCII-only here and you match it byte for byte. With it off, you get the readable form, the same thing json.dumps(..., ensure_ascii=False) and JavaScript's own stringifier produce.
The forward slash gotcha
You will spot / written as \/ in JSON out in the wild, and a lot of people assume it is required, which it never has been. The spec lists \/ as allowed rather than mandatory, and a bare / is perfectly valid, so {"url": "https://example.com"} parses without a hitch. There is one genuine reason to escape it, and that is </script>. If the JSON is embedded directly inside an HTML <script> block, a literal </ can close that tag early and break the page or open an injection hole. Escaping to <\/script> sidesteps that while keeping the JSON valid, which is why some server encoders do it automatically. For ordinary API and config work you do not need it, so the option stays off unless you turn it on.
Escape, unescape, and checking your work
Escaping and unescaping are exact inverses. Escape He said "hi" and you get He said \"hi\". Unescape that and you are back to where you started. After you escape something, hit Swap and unescape it. If you do not get your input back character for character, the trouble is somewhere in your input rather than in the conversion.
One thing to keep straight, escaping is not the same as formatting or validating JSON. Escaping works on the contents of a single string. It does not pretty-print an object, balance your braces, or tell you whether the whole document parses. If your string is valid but the overall JSON still fails, the problem is structural, a missing comma or a stray brace, and the JSON Formatter / Validator is the tool for that. This one stays focused on the string layer underneath.
And when you are writing code, lean on your language instead. JSON.stringify in JavaScript, json.dumps in Python, json_encode in PHP, they all escape correctly, and hand-escaping strings you are about to ship is a mistake waiting to happen. Where this tool actually helps is the in-between work: reading an escaped blob out of a log, hand-building a one-off curl or Postman body, or pasting text into a CI variable or a dashboard field where there is no code around to do it for you.
Frequently asked questions
Can I escape a private key or certificate safely here?
Yes, and it is one of the main reasons to use this over a typical online escaper. The file you drop or open is read in your browser and never uploaded, logged, or stored, so a .pem key, a TLS cert, or a service-account file stays on your machine. You get the whole thing back as one JSON string with the line breaks written as \n, ready to paste into a Kubernetes secret, a CI variable, or a config value. Once the page has loaded you could pull the network connection and it would still work.
Why does my output differ from Python's json.dumps?
Almost always the ASCII setting. Python escapes non-ASCII by default, so café comes out of json.dumps as café. This tool keeps printable Unicode readable by default, so you would see café instead. Switch on the ASCII-only option and the two line up. If you actually want the readable form out of Python, pass ensure_ascii=False on that side.
What file types can I drop in?
Any plain text file. Certificates and keys (.pem, .key, .crt), config and data files (.json, .env, .xml, .yaml, .sql, .csv), or a raw .txt or .log. The tool reads the file as text and escapes its exact contents. It is not built for binary files like images or archives, since those are not text and would not give you anything useful.
Do I need to wrap the result in quotes?
Only when you want a standalone JSON value. By default Escape hands you the body, the characters that live between the quotes, which is what you want when you are inserting into a "..." that already exists. Tick Wrap in double quotes and you get a complete value like "He said \"hi\"" that pastes anywhere a JSON string is expected.
Why did my unescape fail with an invalid-escape message?
Because there is a backslash followed by something JSON does not recognize. The legal escapes are \", \\, \/, \b, \f, \n, \r, \t, and \uXXXX with exactly four hex digits. Anything like \x or \q is undefined, so the tool stops and points at the position rather than guessing. A lone trailing backslash sets off the same error. Nine times out of ten it is a single backslash that should have been doubled.
Can I unescape a string that still has its outer quotes?
Yes. Paste "He said \"hi\"", quotes and all, and the tool strips one matching outer pair before it decodes. If there are no outer quotes it just decodes the body. Either way you land on the raw text. It only removes one outer pair, so a real escaped quote sitting at the very start or end is still handled correctly.
Is any of my data sent to a server?
Never. Every escape and unescape runs locally in plain JavaScript, no upload, no request, no logging. That is what makes it fine for secrets, internal payloads, tokens, or anything you would not hand to a random website. Load the page once and it keeps working offline.