How to Escape Special Characters in YAML (Colon, Hyphen, Asterisk)
YAML uses many characters as structural syntax. When those characters appear inside your data, the parser treats them as directives instead of content.
A colon plus space starts a mapping. A hyphen plus space starts a list item. An asterisk starts an alias reference. An ampersand starts an anchor definition. An exclamation mark starts a tag.
This creates a fundamental problem: what if your data naturally contains these characters?
A version string like 1.0.0:beta contains a colon. A room number like Room-5 contains a hyphen. A reference like Order #123 contains a hash. Each of these will either trigger a parse error or silently produce wrong data.
This guide covers every special character in YAML, how to escape it, and which approach works best for each situation.
Characters That YAML Treats as Syntax
Here is the complete list of characters YAML uses as structural syntax:
| Character | YAML Meaning |
|---|---|
: (followed by space) | Mapping key-value separator |
- (followed by space) | List item indicator |
# | Comment (rest of line ignored) |
& | Anchor definition |
* | Alias reference |
! | Tag prefix |
| ` | ` |
> | Folded block scalar |
[ ] | Flow sequence delimiters |
{ } | Flow mapping delimiters |
, | Flow collection separator |
? | Complex mapping key |
@ | Reserved for future use |
` | Reserved for future use |
% | Directive indicator |
--- | Document start |
... | Document end |
' " | String delimiters |
Every one of these characters requires escaping or quoting if it appears as literal content in a position where YAML interprets it as syntax.
Escaping Colons
The colon is the most commonly problematic character because it is ubiquitous in data.
The Problem
# YAML sees this as key: "value"
description: Error: something failed
# YAML sees "Error:" as a key and then fails on "something"
The first colon after description: is the mapping separator. YAML expects a value. Instead it finds another colon, which it interprets as starting a new mapping. This causes a parse error.
The Fix: Single Quotes
description: 'Error: something failed'
Single quotes protect the entire string. The colon inside no longer triggers mapping detection.
The Fix: Double Quotes
description: "Error: something failed"
Double quotes also work. Use them if you also need escape sequences.
The Fix: Quoted Suffix
If you cannot quote the whole value, quote the problematic suffix:
description: Error: "something failed"
This is ugly but sometimes necessary when the first part of the value is a valid unquoted string.
Escaping Hyphens
Hyphens at the start of a line or after a space trigger list interpretation.
The Problem
# YAML interprets "list:" as a mapping and then "- item" as a list
list: - item
Actually, YAML handles this correctly in flow context:
list:
- item # valid list
The problem arises when you want a hyphen in a value:
title: Best - Practices # This works fine - hyphen in middle is safe
But at the start of a value:
output: -1 # YAML interprets as list item
The Fix
output: "-1"
output: '-1'
Any quoting approach works. The key is preventing YAML from seeing the hyphen at the start of the value position.
Escaping Hashes
Hashes introduce comments. Everything after # until the end of the line is ignored.
The Problem
description: This is item #42
YAML sees description: This is item and ignores #42 as a comment.
The Fix
description: "This is item #42"
description: 'This is item #42'
Both quoting styles prevent the hash from being interpreted as a comment start.
Edge Case: Hashes in the Middle of Unquoted Strings
values:
- item #1
- item #2
Each list item becomes "item " — everything after the hash is lost. This is a common source of silent data loss. Quote list items containing hashes.
Escaping Asterisks and Ampersands
Asterisks start alias references. Ampersands start anchor definitions.
The Problem
description: *important note*
YAML looks for an anchor named important note* and fails because it cannot find it.
The Fix
description: "*important note*"
description: '*important note*'
Always quote values containing * or & at any position.
Escaping Exclamation Marks
Exclamation marks start YAML tags.
The Problem
command: !important
YAML interprets !important as a tag transformation, not a string value.
The Fix
command: "!important"
command: '!important'
If you use an unquoted exclamation mark followed by alphanumeric characters, YAML treats it as a tag. Some parsers silently strip the tag and return the value — others crash.
Escaping Block Scalar Indicators
A pipe | or greater-than > at the start of a value triggers block scalar mode.
The Problem
command: | grep error
YAML starts a literal block scalar and reads everything after | as content lines instead of parsing | as the value.
The Fix
command: "| grep error"
command: '| grep error'
Quote the value to prevent YAML from interpreting the pipe as a block scalar indicator.
Escaping Flow Collection Characters
Square brackets, curly braces, and commas inside flow collections need protection.
The Problem
data: [1, 2, 3] # valid flow sequence
name: Smith, Jones # valid - comma is safe in block mapping
But inside a flow collection:
items: [ "a", "b, c" ] # comma inside quoted string is fine
The problem arises when flow delimiters appear unexpectedly:
path: /api/[id] # YAML may try to parse [id] as a flow sequence
The Fix
path: "/api/[id]"
path: '/api/[id]'
Escaping Multiple Special Characters
When a value contains several special characters, quoting the entire value is the only practical approach.
# Contains colon, hash, and exclamation mark
problem: "Error #3: failed! Check the logs"
A single pair of quotes protects everything inside:
complex_value: "Path: C:\\Users\\admin\\config.yml #v2.1!important"
Escaping in Different Contexts
In Block Mappings
key: "value with : colon"
In Block Sequences
items:
- "item #1"
- "item: value"
In Flow Mappings
config: { key: "value: with colon", name: "item #1" }
In Flow Sequences
tags: ["tag:one", "tag#two", "tag!three"]
Common Real-World Examples
URL with Query Parameters
url: "https://api.example.com/v2/users?id=42&status=active"
The colon (https:) needs quoting because it is followed by content that could be misinterpreted.
Version Strings
version: "1.0.0-beta.3+sha.abc123"
The plus sign is not special in YAML, but the combination of dots, hyphens, and pluses can confuse some parsers. Quote version strings.
Shell Commands
command: "grep 'error:' /var/log/app.log | wc -l"
Contains colon, pipe, and hyphens. The entire command must be quoted.
Regular Expressions
pattern: "\\d+\\.\\d+\\.\\d+"
regex: '[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}'
Backslashes in double-quoted strings need escaping (\\). Single quotes preserve backslashes literally.
Windows Paths
path: 'C:\Users\deploy\config.yaml'
Use single quotes to preserve backslashes. Double quotes would require C:\\Users\\....
Quick Escaping Cheat Sheet
| Character | Escape Method |
|---|---|
: (with space) | Quote the value |
- at start | Quote the value |
# anywhere | Quote the value |
* anywhere | Quote the value |
& anywhere | Quote the value |
! at start | Quote the value |
| ` | >` at start |
[ ] { } | Quote the value |
\ in double quotes | Use \\ |
' in single quotes | Use '' |
" in double quotes | Use \" |
| Multiple characters | Quote the whole value |
Testing Escaped Values
Always verify that your escaped values are parsed correctly:
import yaml
data = """
url: "https://api.example.com/v2/users?id=42"
command: "grep 'error:' /var/log/app.log"
description: 'Item #3: complete'
"""
parsed = yaml.safe_load(data)
for key, value in parsed.items():
print(f"{key}: {value}")
If any value is truncated, empty, or produces a parse error, you missed a special character that needs quoting.
FAQ
How do I escape a colon in YAML?
Quote the entire value containing the colon. Use single quotes ('Error: something') to preserve the colon literally, or double quotes ("Error: something") if you also need escape sequences. An unquoted colon followed by a space is always interpreted as a key-value mapping separator by the YAML parser. If only part of the value contains a problematic colon, you can quote just that portion: description: Error: "something failed" — but quoting the whole value is cleaner.
How do I include a hash # in a YAML string?
The hash character introduces a comment in YAML — everything from # to the end of the line is ignored by the parser. To include a literal hash, quote the string: description: "Item #42" or description: 'Item #42'. The quotes prevent the parser from treating the hash as a comment indicator. Be especially careful with list items containing hashes: - "item #1" — without quotes, - item #1 loses the #1 portion.
Does YAML support backslash escape sequences?
Yes, but only inside double-quoted strings. YAML double-quoted strings support \\ (backslash), \n (newline), \t (tab), \r (carriage return), \" (double quote), and \xNN (hexadecimal Unicode). Single-quoted strings do NOT interpret backslash escapes — \n in a single-quoted string remains the literal characters \ and n. Plain (unquoted) strings also do not support escape sequences. If you need escape sequences, always use double quotes.
How do I escape special characters in YAML without using quotes?
There are very limited options for escaping special characters without quotes. You can use a block scalar (| or >) to avoid the colon-space problem in multiline values. You can use flow style ({ } and [ ]) in some cases. You can use YAML's quoted key syntax (? "key with colon"). But in practice, quoting the value is the only reliable approach. YAML deliberately avoids escape-based workarounds because they complicate parsing — quotes are the intended solution.
What happens if I forget to escape a special character in YAML?
The behavior depends on the character and context. An unescaped colon may cause a parse error (mapping values are not allowed here). An unescaped hash silently truncates the value — everything after # disappears with no error message. An unescaped asterisk triggers an "unknown anchor" error. An unescaped pipe starts a block scalar and consumes subsequent lines as content, corrupting the entire document structure. Unescaped special characters produce failures ranging from silent data loss to hard parse errors, and the actual error location is often far from the problematic character.
Final Thoughts
YAML's special character handling is one of those things that seems simple until it silently corrupts your data.
The consistent approach is simple: if a value contains any character that YAML uses as syntax, quote the entire value. Single quotes for literal content, double quotes if you need escape sequences.
Most YAML parse errors caused by special characters are preventable with quoting discipline. The two-minute habit of adding quotes to values with colons, hashes, asterisks, or exclamation marks eliminates an entire category of debugging nightmares.
If an existing YAML file keeps producing confusing errors, paste it into a YAML formatter and validator — seeing exactly where the parser fails will show you which character needs escaping.
For more on parsing pitfalls, see Why Your YAML Is Invalid, How to Fix YAML Indentation Errors, and Do I Need Quotes for Strings in YAML?.