Escape sequences
Almost every escaping bug is a context error rather than a syntax error. The character is known — a quote, a backslash, an ampersand — and what is unclear is which of six conflicting rules applies where the string is about to land.
So this table is organised by context, not by character. The same quote is doubled in a CSV cell, backslash-escaped in JSON, turned into " in HTML and left completely alone inside single quotes in a shell. Four rows, four rules, one character.
The rule that matters most is the one people reach for last: escape at the boundary the value is crossing, and escape it once. Text that is escaped twice — a & in the page source, a \\n in the output file — is the signature of a value that passed through two encoders that each assumed they were first.
JSON strings
10JSON allows exactly these escapes. A literal newline or tab inside a string is invalid.
| Escape | Means | When you need it | In context |
|---|---|---|---|
| \" | " | A double quote inside a string | "say \"hi\"" |
| \\ | \ | A literal backslashThe reason Windows paths break JSON. | "C:\\dir" |
| \/ | / | A forward slash — optionalLegal but unnecessary; a habit from embedding JSON in <script> tags. | "a\/b" |
| \n | U+000A | A line feed | "line\nline" |
| \r | U+000D | A carriage return | |
| \t | U+0009 | A tab | |
| \b | U+0008 | A backspace | |
| \f | U+000C | A form feed | |
| \u00e9 | é | Any character by its four-digit code point | "caf\u00e9" |
| \ud83d\ude00 | 😀 | A character above U+FFFF, as a surrogate pairJSON has no \u{…} form, so astral characters take two escapes. |
JavaScript strings
10A superset of JSON's, plus the template-literal escapes.
| Escape | Means | When you need it | In context |
|---|---|---|---|
| \' | ' | A single quote inside a single-quoted string | |
| \" | " | A double quote inside a double-quoted string | |
| \` | ` | A backtick inside a template literal | |
| \${ | ${ | A literal ${ inside a template literalWithout the backslash it starts an interpolation. | |
| \n | U+000A | A line feed | |
| \xe9 | é | A character by two hex digits, up to U+00FF | |
| \u00e9 | é | A character by four hex digits | |
| \u{1f600} | 😀 | Any code point, however longNeeds no surrogate pair, unlike the four-digit form. | |
| \0 | U+0000 | A null character | |
| \u2028 | U+2028 | Line separatorValid in a JS string but not in JSON — a classic JSONP breakage. |
HTML text and attributes
8Only & and < strictly must be escaped in text; quotes matter inside attributes.
| Escape | Means | When you need it | In context |
|---|---|---|---|
| & | & | An ampersandEscape this one first, or every other escape doubles. | |
| < | < | A less-than sign, so it does not start a tag | |
| > | > | A greater-than sign | |
| " | " | A double quote inside an attribute | |
| ' | ' | A single quote inside an attribute' also works in HTML5, but the numeric form is safe everywhere. | |
| | U+00A0 | A non-breaking space | |
| é | é | Any character by decimal code point | |
| é | é | Any character by hex code point |
URLs (percent-encoding)
9Which characters need escaping depends on the part of the URL they sit in.
| Escape | Means | When you need it | In context |
|---|---|---|---|
| %20 | A space, valid anywhere in a URL | ||
| + | A space, but only in a form-encoded query stringIn a path segment this is a literal plus sign. | ||
| %25 | % | A literal percent signMiss this and the value decodes twice. | |
| %2F | / | A slash inside a single path segment | |
| %3F | ? | A question mark inside a value | |
| %26 | & | An ampersand inside a parameter value | |
| %3D | = | An equals sign inside a parameter value | |
| %23 | # | A hash, so it does not start the fragment | |
| %C3%A9 | é | A non-ASCII character, as its UTF-8 bytesOne character can become two, three or four percent groups. |
CSV fields
5RFC 4180: quote the field, then double any quote inside it. Backslashes mean nothing.
| Escape | Means | When you need it | In context |
|---|---|---|---|
| "" | " | A quote inside a quoted field — double it | "say ""hi""" |
| "a,b" | , | A field containing the delimiter — quote the field | |
| "a b" | U+000A | A field containing a line break — quote the field | |
| " a" | Preserve leading or trailing spacesUnquoted, many parsers trim them. | ||
| '=SUM(A1) | = | Stop a spreadsheet executing the cell as a formulaApplies to values starting =, +, - or @. This is formula injection. |
SQL literals and identifiers
6Read these; do not write them. Use parameterised queries instead.
| Escape | Means | When you need it | In context |
|---|---|---|---|
| '' | ' | A quote inside a string literal — double it | 'O''Brien' |
| "order" | order | A reserved word used as a column nameDouble quotes are the standard; SQL Server uses [brackets]. | |
| `order` | order | The same in MySQL and MariaDB | |
| \% | % | A literal % inside a LIKE pattern | |
| \_ | _ | A literal _ inside a LIKE pattern | |
| $tag$ … $tag$ | ' | PostgreSQL dollar quoting — no escaping inside at allUseful for bodies of code, where doubling every quote is unreadable. |
Shell arguments
6Single quotes are literal, double quotes still expand variables.
| Escape | Means | When you need it | In context |
|---|---|---|---|
| '…' | $ ` \ | Everything inside is literalThe safest quoting there is — but it cannot contain a single quote. | |
| "…" | * ? space | Globs and spaces are safe, variables still expandAlways quote variables: "$var", never bare $var. | |
| \ | A space in an unquoted filename | ||
| \$ | $ | A literal dollar sign inside double quotes | |
| \` | ` | A literal backtick, not a command substitution | |
| '\'' | ' | A single quote inside single quotesClose, escape, reopen — there is no way to nest it directly. |