Quotes mark where a string begins and ends so the code around it is not mistaken for text. Single quotes and double quotes both create strings in most languages; the practical difference is how each treats the other quote character and escape sequences inside the text. In JavaScript, Python, PHP, and Bash, either works until the string contains an apostrophe, an embedded quote, or an interpolation marker. The character you pick is usually the one that lets you type the fewest backslashes.
Understanding that single rule explains almost every style debate you will encounter. The rest is language-specific detail, and detail matters more than most tutorials admit.
What the delimiters actually do
A string literal is a run of characters the compiler or interpreter must not treat as syntax. When the parser reaches the opening quote, it stops interpreting identifiers, operators, and keywords. It reads forward until it finds a matching closing quote that is not escaped or doubled. Everything between the pair becomes raw data. Remove the delimiters and the parser tries to read your text as code, which is why hello world is a syntax error in nearly every language.
The quote character therefore does double duty: it is a boundary marker and a type marker. In JavaScript, 42 is a number and "42" is a string, and "42" - 7 returns 35 while "42" + 7 returns "427". That coercion behavior is defined in the ECMAScript specification and is the single most common source of beginner bugs.
A subtler point is that the delimiter is consumed, not stored. The string value contains the characters between the quotes, never the quotes themselves. To keep a literal quote inside a string you must escape it or wrap it in the other quote type.
Two quote characters, one string type
In JavaScript, Python, Ruby, PHP, and Bash, single and double quotes produce the same string type. The language does not treat 'text' as a different data type from "text". That is a design choice, not a universal law: in C, C++, Java, and C#, single quotes denote a single character and double quotes denote a string, so 'a' and "a" are different types and mixing them fails to compile.
The real divergence is in escape handling and interpolation. JavaScript gives both quote characters identical escape processing, so \n means newline inside either. Python is nearly identical. Bash and PHP are not: in Bash, single quotes are fully literal, so '\n' is a backslash followed by an n, while "\n" is not special either but "$VAR" expands. In PHP, double-quoted strings interpolate variables like "$name" and interpret \n, while single-quoted strings do neither.
That distinction has cost real bugs. A shell script that builds a path with '$HOME/data' passes the literal text $HOME to the program, not the expanded path. A PHP query built with single quotes around a variable fails silently rather than interpolating, which is sometimes the safer outcome and sometimes a logic error.
Where the difference changes behavior
The differences cluster into three mechanisms: escaping, interpolation, and multiline handling. Escaping is the backslash convention. Every language with escapes accepts ' and " inside strings, and a backslash before the delimiter tells the parser the delimiter is data. The counterintuitive detail is that in Python a backslash at the end of a string literal is a line-continuation marker, so "abc\ followed by a newline joins the next line into the same string. That surprises people who expect a raw backslash.
Interpolation is the substitution of variables into a string. JavaScript does not interpolate with either quote type, which is why template literals using backticks exist. PHP and Bash do interpolate, and only in double-quoted strings. That is the single most important single-versus-double difference for anyone writing shell scripts or legacy PHP.
Multiline strings separate the two in most languages. In JavaScript, Python, and Ruby, a string literal may not span a raw newline unless you use a triple-quote (Python), backtick (JavaScript), or heredoc (Ruby, Bash, PHP). A newline inside ordinary single or double quotes is a syntax error. The practical workaround is concatenation or an explicit \n.
A backslash inside a Windows path such as C:\Users must be escaped or doubled, and in regex strings the trailing backslash can break the literal. An apostrophe inside a single-quoted string ends the string early: 'don't' is a syntax error, not a word. Interpolation only happens in double quotes in PHP and Bash, so '$user' and "$user" are different values. In C-family languages, 'x' is a character code and "x" is a string, so assignment fails at compile time. Mixing quote types in a diff is a red flag in code review, because reviewers cannot tell style from intent.
A comparison across languages
The table below summarizes the behaviors that matter in everyday code. Read it as a decision aid, not a specification.
| Language | Single quote | Double quote | Interpolation | Escape \n |
|---|---|---|---|---|
| JavaScript | String | String | Neither (use backticks) | Yes in both |
| Python | String | String | Neither (f-strings use either) | Yes in both |
| PHP | String, no interpolation | String, interpolates $var | Double only | Double only |
| Bash | Fully literal | Expands $var, backticks | Double only | Neither by default |
| Ruby | String, no interpolation | String, interpolates #{} | Double only | Double only |
| Java | char type | String type | Neither | Yes in both |
| C / C++ | char (integer) | char* / string | Neither | Yes in both |
The pattern is that compiled, statically typed languages tend to treat the single quote as a character type, while dynamic scripting languages treat it as an alternate string delimiter. If you switch between JavaScript and C# in the same day, that difference will bite you.
Why style guides disagree
Style guides fix a default, and the default is arbitrary. Google's JavaScript style guide says use single quotes for strings, with template literals for interpolation. Airbnb's JavaScript style guide says the same, and allows double quotes only when the string itself contains a single quote, to avoid escape characters. Python's PEP 8 says pick either and use it consistently, and the Black formatter normalizes to double quotes.
The guides agree on the mechanism: consistency reduces diff noise, and a formatter or linter enforces the rule so humans do not argue. Prettier defaults to double quotes for JavaScript and rewrites every file that disagrees, which is why a repository-level configuration setting matters more than which quote you personally prefer.
The history behind the preference is mostly tooling. JSON requires double quotes, so JSON-adjacent codebases gravitate toward double quotes. HTML attributes accept either, but the habit of double quotes in HTML has leaked into adjacent JavaScript. Nothing in the runtime rewards one over the other.
The escape-avoidance rule in practice
The practical rule is to choose the delimiter that avoids escapes in the specific string. If the text contains apostrophes, use double quotes: "It's ready" needs no escaping. If the text contains quotation marks, use single quotes: 'She said "go"' is clean. If it contains both, one style is easier than the other depending on which appears more often.
The second rule is to switch delimiters rather than stack backslashes. When you find yourself writing three or four consecutive backslashes, the string has outgrown its delimiter and should be a template literal, a triple-quoted string, or a raw string. Python's r"..." prefix disables escape processing entirely, which is the right tool for regex patterns and Windows paths. JavaScript's String.raw tag does the same job. Bash's heredoc syntax with a quoted delimiter, <<'EOF', disables all expansion and is the clean way to embed a block of literal text.
The third rule: never build SQL, HTML, or shell commands by concatenating quoted strings. The correct action is a parameterized query, an escaping library, or a templating system, because a quote character in user input is exactly how injection attacks begin. The quote debate is a style question; the injection problem is a security question, and no delimiter choice solves it.
Edge cases that break beginners
The apostrophe-in-a-word case is the most common beginner error. 'don't' fails because the parser closes the string at the apostrophe. The fix is "don't" or 'don't', and the first is cleaner.
The nested-quote case appears in generated code. When one string must contain another literal, alternate the delimiter at each nesting level, and stop nesting after two levels. If you need three, you need a proper escaping library.
The multiline case appears in configuration files and code generators. A raw newline inside an ordinary quoted string is a syntax error in JavaScript and Python, so use the language's dedicated multiline form.
The invisible-character case is the professional caveat. Copying a string from a formatted document can insert a typographic quote (U+2018, U+2019, U+201C, U+201D) instead of the ASCII quote (U+0027, U+0022). The parser rejects the typographic character, and the error message looks identical to a missing-quote error. Smart-quote substitution has broken more code snippets than any other formatting feature. Turn off auto-substitution in your editor.
Practical actions
Configure a formatter to enforce one quote style per language, and let it rewrite files on save. Default to single quotes in JavaScript and Python unless the formatter dictates otherwise, and default to double quotes in JSON. In PHP and Bash, treat double quotes as the "interpolating" form and single quotes as the "literal" form, and name that distinction in code comments. Reach for a raw string, template literal, or heredoc before adding a third backslash. Disable typographic quote substitution in every editor and document tool used for code. Treat quote characters in user input as untrusted data, and route them through an escaping library rather than manual string building.
Limits of the rule
The escape-avoidance rule does not extend across languages. Ruby and PHP interpolate in double quotes but not single quotes, so the same file migrated between them will change behavior. Languages with different quote mechanisms, such as C, Java, and C#, do not have a "two string quote" choice at all. SQL uses single quotes for string literals and double quotes for identifiers, and swapping them changes meaning rather than style.
Linters, formatters, and specification documents are the authoritative sources for a given language, and they change over time. This article describes stable mechanics, not the current default of any specific tool. Where your project's configuration disagrees with a general style guide, the project configuration governs.
The safe reading is that quote characters are delimiters, the choice between single and double is a per-language convention, and the only universal rule is to match the delimiter to the content and let a tool enforce consistency.