Skip to content

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

10

JSON allows exactly these escapes. A literal newline or tab inside a string is invalid.

EscapeMeansWhen you need itIn 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"
\nU+000AA line feed"line\nline"
\rU+000DA carriage return
\tU+0009A tab
\bU+0008A backspace
\fU+000CA 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

10

A superset of JSON's, plus the template-literal escapes.

EscapeMeansWhen you need itIn 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.
\nU+000AA 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.
\0U+0000A null character
\u2028U+2028Line separatorValid in a JS string but not in JSON — a classic JSONP breakage.

HTML text and attributes

8

Only & and < strictly must be escaped in text; quotes matter inside attributes.

EscapeMeansWhen you need itIn context
&amp;&An ampersandEscape this one first, or every other escape doubles.
&lt;<A less-than sign, so it does not start a tag
&gt;>A greater-than sign
&quot;"A double quote inside an attribute
&#39;'A single quote inside an attribute&apos; also works in HTML5, but the numeric form is safe everywhere.
&nbsp;U+00A0A non-breaking space
&#233;éAny character by decimal code point
&#xE9;éAny character by hex code point

URLs (percent-encoding)

9

Which characters need escaping depends on the part of the URL they sit in.

EscapeMeansWhen you need itIn 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

5

RFC 4180: quote the field, then double any quote inside it. Backslashes mean nothing.

EscapeMeansWhen you need itIn context
"""A quote inside a quoted field — double it"say ""hi"""
"a,b",A field containing the delimiter — quote the field
"a b"U+000AA 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

6

Read these; do not write them. Use parameterised queries instead.

EscapeMeansWhen you need itIn context
'''A quote inside a string literal — double it'O''Brien'
"order"orderA reserved word used as a column nameDouble quotes are the standard; SQL Server uses [brackets].
`order`orderThe 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

6

Single quotes are literal, double quotes still expand variables.

EscapeMeansWhen you need itIn context
'…'$ ` \Everything inside is literalThe safest quoting there is — but it cannot contain a single quote.
"…"* ? spaceGlobs 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.

FAQ

Why does my JSON break on a Windows file path?
Because a backslash starts an escape sequence in a JSON string, so C:\dir is read as C, then an invalid escape. Written correctly the value is "C:\\dir" — two backslashes in the file, one in the parsed string. Forward slashes work on Windows too and avoid the problem entirely.
Is %20 or + correct for a space in a URL?
Both, in different places. %20 is correct anywhere in a URL. The plus sign means a space only inside a query string encoded as application/x-www-form-urlencoded — in a path segment it is a literal plus. Use %20 when you are unsure, because it is right everywhere.
How do I put a quote inside a CSV field?
Wrap the field in quotes and double the inner one: "say ""hi""". That is RFC 4180, and it is why a CSV full of doubled quotes is not corrupted. A backslash means nothing to a conforming CSV parser.
What is the leading apostrophe in the CSV formula row for?
It defuses a formula injection. A cell starting with =, +, - or @ is executed as a formula when the file is opened in a spreadsheet, so a value like =SUM(A1) from an untrusted source becomes code. Prefixing an apostrophe forces the cell to be read as text.
Should I escape SQL by hand?
No. Doubling a quote is documented here because you need to read escaped SQL, not because you should write it — use parameterised queries and let the driver handle the value. Hand-escaping is where SQL injection comes from, and there is no version of it that is safe by inspection.