Escape / Unescape
Python Escape / Unescape
Turn any text into a Python string literal body — plain UTF-8, ASCII-only with \u/\U escapes, or a bytes literal — and decode repr() output back.
In short
Escape and unescape Python string literals online: \n, \t, \xNN, \uXXXX and \UXXXXXXXX escapes, ASCII-only and bytes modes, repr() output decoded. Free.
By NaveenKumar T · Updated
- Escape & unescape in one tool
- Handles every special character
- Instant as you switch modes
Runs entirely in your browser — nothing you paste or open here is uploaded, logged, or stored.How we handle data →
Example
Python Escape: input and output
A Windows path, a tab, a quoted word and a line of mixed CJK and emoji — escaped in ASCII-only style, the mode that has to handle every character in the input.
Path: C:\Users\Zoë\notes.txt "quoted" — 日本語 😀Path: C:\\Users\\Zo\xeb\\notes.txt\t\"quoted\" \u2014 \u65e5\u672c\u8a9e \U0001f600Every backslash doubled and the tab and quote gained their named escapes; ë became \xeb, the em dash \u2014, 日本語 three \uXXXX escapes, and the single emoji one eight-digit \U0001f600 — not a surrogate pair.
Learn more
Python escaping rules
A Python 3 str is a sequence of Unicode code points, and its double-quoted literal form needs backslashes only for the characters that would otherwise end the literal or aren't printable: \" for the quote, \\ for the backslash itself, \n \r \t \a \b \f \v for the named control characters, and \xNN for any other byte below U+0020. Because Python 3 source files are UTF-8, everything else — accented letters, CJK text, emoji — is written as the literal character; there is no requirement to escape non-ASCII the way older C-family literals do. That is the "str" style this tool defaults to, and it is what you want for source code you intend to keep readable.
The "ASCII-only" style instead reproduces what Python's own ascii() and repr() functions do to a string containing non-ASCII: every code point from U+007F upward is escaped, using the narrowest form that fits it — \xNN for U+0080–U+00FF, \uXXXX for the rest of the Basic Multilingual Plane, and \UXXXXXXXX (eight hex digits, one escape per code point) for anything above U+FFFF. That last point is the detail that trips people coming from JavaScript, Java or C#: Python never splits an astral character into a UTF-16 surrogate pair, because Python strings were never UTF-16 to begin with. The "bytes" style is different again — it assumes you are building a b"..." literal, so it UTF-8-encodes every non-ASCII character first and then writes each resulting byte as its own \xNN escape, which is why a single accented letter can expand into two or three escapes.
Python escape sequences
The named escapes below work in every Python string literal regardless of style; \xhh, \uXXXX and \UXXXXXXXX are shown here as this tool emits them, and a raw string (r"...") disables all of them except that a backslash still can't be the last character.
| Escape | Meaning |
|---|---|
| \\ | Backslash |
| \' · \" | Single or double quote |
| \n · \r · \t | Newline, carriage return, tab |
| \a · \b · \f · \v | Bell, backspace, form feed, vertical tab |
| \0 | Null character |
| \ooo | Character named by 1–3 octal digits |
| \xhh | Character named by exactly 2 hex digits (U+0000–U+00FF) |
| \uXXXX | Character named by exactly 4 hex digits (BMP) |
| \UXXXXXXXX | Character named by exactly 8 hex digits (any code point) |
| \N{NAME} | Character by its Unicode name — not decoded here, see the FAQ |
| \<newline> | Line continuation — backslash and the newline are both removed |
Python vs JavaScript vs Java string escapes
The four languages agree on the basics — \\, \", \n, \t — and disagree everywhere Unicode is involved, which is exactly where a hand-ported string tends to break.
| Behavior | Python | JavaScript | Java |
|---|---|---|---|
| Code point above U+FFFF | One \UXXXXXXXX escape | Surrogate pair: two \uXXXX escapes | Surrogate pair: two \uXXXX escapes |
| \x meaning | A code point, U+0000–U+00FF, 2 hex digits | A code point, U+0000–U+00FF, 2 hex digits | Not a recognized escape in a string literal |
| Octal escapes | \ooo (1–3 digits) | Not in strict/module mode | Not supported |
| Named Unicode escape | \N{NAME} | Not supported | Not supported |
| Unknown escape (e.g. \d) | Kept as backslash + character (warns since 3.12) | Kept as the character alone in most engines | Compile error |
Help
Frequently asked questions
Everything you need to know about the Python Escape.
01How do I escape or unescape Python here?
Choose Escape or Unescape, then a style — str for ordinary Python 3 source, ASCII-only for output that must be pure ASCII (config files, some CI logs), or bytes for a b"..." literal — and press Convert. The output is the literal's body: wrap it yourself in the quote character your code uses.
02Why does Python write é as \xe9 but 😀 as \U0001f600 — no surrogate pairs?
Because Python indexes strings by code point, not by UTF-16 code unit, so there is nothing to pair: 😀 is one code point (U+1F600) and gets exactly one escape, eight hex digits wide, capital U. Compare that with JavaScript or Java, whose strings are UTF-16 internally — a code point above U+FFFF has no single 16-bit slot, so those languages write it as two \u escapes representing a high and low surrogate. \xe9 for é follows a different rule: \x is always exactly two hex digits, so it only covers U+0000–U+00FF, and é (U+00E9) fits inside that range with room to spare.
03What is the difference between the str, ASCII-only and bytes styles?
str assumes your source file is UTF-8 (the Python 3 default) and only escapes the characters a literal actually needs escaped — quotes, backslashes and control characters — leaving accented letters and emoji untouched, so the output stays human-readable. ASCII-only reproduces what repr() shows you in a terminal that can't render Unicode, or what you'd want in a file a strict ASCII-only tool has to parse: everything above U+007E becomes an escape. bytes targets a b"..." literal specifically, where the content is raw bytes rather than text, so a non-ASCII character has to become the UTF-8 bytes that would actually be stored — each one written as its own \xNN.
04How do I unescape a string copied from a traceback or repr()?
Paste it as-is — the tool detects and strips one layer of surrounding quotes, plus an optional b/r prefix, so 'don\'t' and b'hi\\x41' both unescape correctly on their own. repr() of a single-quoted string escapes an embedded single quote as \', which this tool decodes like any other named escape. If your text is meant to be used as a regular-expression pattern afterward, remember that a raw string (r"...") disables backslash processing entirely on the Python side — escape it here only if the string you're building is NOT a raw string.
05Why is \d kept instead of failing?
Because that is what CPython itself does: an escape sequence it doesn't recognize (\d, \q, and similar) is left in the string unchanged — both the backslash and the character survive — rather than raising an error. Since Python 3.6 this has emitted a DeprecationWarning, and 3.12 upgraded it to a SyntaxWarning, but the string still parses. This tool mirrors that behavior exactly and reports how many unrecognized escapes it kept, so you can tell a genuine typo from an intentional regex pattern that was never meant to be unescaped — regex patterns belong in a raw string, or through the [Regex Escape](/regex-escape) tool instead.
Keep working
Related tools
JavaScript Escape
Escape / Unescape
JSON Escape
Escape / Unescape
Java Escape
Escape / Unescape
Regex Escape
Escape / Unescape
JSON to String
Turn a JSON document into a complete, ready-to-paste string literal for the language you're actually writing — quotes and delimiters included, not just an escaped body.
HTML Escape
Escape / Unescape