YAML Cheat Sheet
YAML syntax on one page: lists, maps, quotes, multi-line strings, anchors, and real Docker Compose, GitHub Actions and Kubernetes files. Paste your own YAML into the checker to see what it really means and catch values that change on the way.
29 entries
Key and value
key: valuename: my-app replicas: 3
The space after the colon is required. Keys are case-sensitive, so Name and name are two different keys.
Comments
# comment# Settings for production port: 8080 # after a value
Everything after # to the end of the line is ignored. After a value, the # needs a space before it. There are no block comments, so put # on every line.
Nesting with indentation
parent:
child: valueserver: host: localhost port: 8080
Indent with spaces, never tabs. Two spaces is the habit, but any number works as long as keys at the same level line up exactly.
Several documents in one file
------ kind: Service --- kind: Deployment
Three dashes start a new document. Kubernetes uses this to keep several objects in one file. The --- before the first document is optional.
List
- itemfruits: - apple - banana
A dash and a space start each item. The dashes may also sit level with the parent key instead of indented; both are valid.
List of maps
- key: value
key: valueusers:
- name: Ada
role: admin
- name: Lin
role: devEach dash starts a new item. The item’s other keys line up with the first key after the dash, not with the dash.
Inline list
[a, b]ports: [80, 443] branches: [main, develop]
Flow style, written like JSON. Handy for short lists; switch to dashes once it gets long.
Inline map
{a: 1, b: 2}limits: {cpu: 500m, memory: 128Mi}Flow style for small maps. Any JSON object is also valid YAML, so {"a": 1} works too.
Nested lists
- - amatrix:
- [1, 2]
- [3, 4]
grid:
- - a
- bA list inside a list, either inline or with a second dash. The inline form is easier to read.
Empty list and empty map
[] {}tags: []
labels: {}Use these when the key must exist but hold nothing. A key with nothing after it is null, not an empty list.
Plain (unquoted) string
key: plain texttitle: Hello world url: https://example.com/path
Most text needs no quotes, even with spaces or a colon that is not followed by a space. Quote it when it looks like a number, true/false or null, or starts with a special character.
Double-quoted string
"double quotes"message: "Line one\nLine two" color: "#ff6600"
The only style where escapes such as \n, \t and \" work. Without quotes, " #" would start a comment and ": " a new key.
Single-quoted string
'single quotes'path: 'C:\Users\me' note: 'It''s fine'
Everything is taken literally, backslashes included, which suits Windows paths and regular expressions. Write a single quote as two: ''.
Text that looks like something else
key: "3.10"python: "3.10" zip: "02134" answer: "yes" port: "22:22"
Unquoted, 3.10 becomes 3.1 and 02134 loses its zero, and older parsers read yes as true and 22:22 as 1342. Quotes keep each one exactly as typed.
Literal block (keep line breaks)
key: |script: | npm ci npm test
Every line break is kept and one newline is added at the end. The usual choice for shell scripts, certificates and SQL.
Folded block (join lines)
key: >description: > This long sentence is wrapped in the file.
Lines are joined with spaces into one paragraph, with one newline at the end. A blank line inside the block becomes a real line break.
Drop the final newline
|- >-key: |- -----BEGIN KEY----- abc123 -----END KEY-----
The minus strips the newline at the end. Use it when a trailing \n would break the value, such as a token or a key.
Keep trailing blank lines
|+ >+footer: |+ Thanks, The team next: value
The plus keeps every blank line at the end of the block. Rarely needed.
Numbers
42 9.99 1e6count: 42 price: 9.99 big: 1e6 hex: 0x1F forever: .inf
Unquoted digits are numbers. 0x1F is 31, .inf is infinity and .nan is not-a-number. Quote anything that must stay text, such as phone numbers.
Booleans
true falseenabled: true debug: False
true and false in lower, Title or UPPER case. YAML 1.1 parsers (PyYAML, older Kubernetes tools) also treat yes, no, on and off as booleans.
Null (empty)
null ~owner: null backup: ~ notes:
All three are null. A key with nothing after it is null too, which is easy to do by accident.
Dates
2024-03-15released: 2024-03-15 updated: 2024-03-15T09:30:00Z
YAML 1.2 keeps these as text. PyYAML, Ruby and other YAML 1.1 parsers turn them into date objects, so quote dates if the value must stay a string.
Force a type with a tag
!!str !!intport: !!str 8080 count: !!int "42"
A tag overrides the guess. Quotes are simpler for making text; tags are mainly seen in older files.
Anchor and alias
&name *namebase_image: &img node:22 build: image: *img test: image: *img
&name labels a value and *name repeats it. The anchor must come first in the file.
Merge keys from an anchor
<<: *namedefaults: &defaults retries: 3 timeout: 30 prod: <<: *defaults timeout: 60
Copies every key from the anchored map, then your own keys override them, so prod gets retries 3 and timeout 60. Docker Compose, GitLab CI and PyYAML support it; it is not part of YAML 1.2, so check your tool.
Docker Compose extension fields
x-name: &namex-logging: &logging
driver: json-file
services:
web:
logging: *logging
worker:
logging: *loggingCompose ignores top-level keys that start with x-, which makes them a safe place to keep anchors.
Docker Compose file
services:services:
web:
image: nginx:1.27
ports:
- "8080:80"
environment:
- TZ=Europe/London
restart: unless-stoppedPorts are quoted on purpose: short values such as 22:22 could be read as a number by older parsers.
GitHub Actions workflow
on: jobs:name: CI
on:
push:
branches: [main]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npm ci
- run: npm testEach step starts with a dash. Quote versions in a matrix ("3.10"), or 3.10 is read as 3.1.
Kubernetes Deployment
apiVersion: kind:apiVersion: apps/v1
kind: Deployment
metadata:
name: web
spec:
replicas: 2
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
spec:
containers:
- name: web
image: nginx:1.27containers is a list of maps, so it needs the dash. Labels under selector and template must match.
YAML Syntax Rules
YAML is built from two things: maps (key: value pairs) and lists (lines starting with - ). Indentation shows what belongs to what, the way brackets do in JSON. Almost every broken YAML file breaks one of these rules:
| Rule | Right | Wrong |
|---|---|---|
| A space after every colon | port: 8080 | port:8080 |
| A space after every list dash | - apple | -apple |
| Indent with spaces only | spaces | a tab character |
| Keys at the same level line up | same number of spaces | one key a space further in |
| Each key once per map | one port: key | two port: keys |
| A space before a trailing comment | port: 80 # web | port: 80# web |
Keys and values are case-sensitive, and the file can be called .yaml or .yml. Any JSON is also valid YAML, so {"port": 8080} works anywhere YAML is expected.
Multi-line Strings: | vs >
Put | or > after the colon and indent the text on the lines below. The pipe keeps your line breaks; the greater-than sign joins the lines into one. A - or + after either one decides what happens to the newline at the very end. Here is the same two-line block with each marker:
text: |
line one
line two| Marker | Result | Use it for |
|---|---|---|
| | | "line one\nline two\n" | Scripts, certificates, SQL |
| |- | "line one\nline two" | Keys and tokens that must not end in \n |
| |+ | Like |, plus any blank lines after the block | Text where trailing blank lines matter |
| > | "line one line two\n" | Long descriptions wrapped in the file |
| >- | "line one line two" | One long line, such as a long command |
The block ends at the first line that is indented less than the text. Inside a block, #, quotes and colons are just text, which is why | is the easy way to paste a shell script or a private key into YAML.
When Do You Need Quotes?
Most strings need no quotes. You need them when the text would otherwise be read as something else: a number, a boolean, null, a comment or a new key. These are the values that cause trouble:
| You write | It is read as | Write instead |
|---|---|---|
| version: 3.10 | the number 3.1 | version: "3.10" |
| zip: 02134 | the number 2134 | zip: "02134" |
| country: NO | false in YAML 1.1 parsers (the “Norway problem”) | country: "NO" |
| port: 22:22 | 1342 in YAML 1.1 parsers (base 60) | port: "22:22" |
| color: #fff | null, because # starts a comment | color: "#fff" |
| title: Note: read me | an error: a second “: ” | title: "Note: read me" |
| user: @admin | an error: @ and ` cannot start a value | user: "@admin" |
| value: null | null, not the word | value: "null" |
Double quotes understand escapes such as \n and \". Single quotes take everything literally, so 'C:\Users' stays as typed; write a single quote inside them as two ('It''s'). If you are not sure whether a value needs quotes, quoting it is always safe.
Worked Example: the Python Version That Became 3.1
A GitHub Actions workflow tests three Python versions, and the 3.10 job fails because it cannot find Python 3.1:
strategy:
matrix:
python-version: [3.9, 3.10, 3.11]3.10has no quotes and looks like a number, so YAML reads it as a number.- As a number, 3.10 is the same as 3.1. The trailing zero is gone before GitHub ever sees the file.
- The setup step is asked for Python 3.1, which does not exist.
3.9and3.11survive only because they have no trailing zero.
The fix is to quote every version, so all three stay text:
python-version: ["3.9", "3.10", "3.11"]Press Example in Check YAML mode to see the checker catch this along with four other values that change without warning. The same thing happens to Node versions such as 20.10 and to any version number ending in zero.
Common YAML Errors and What They Mean
Error messages differ between tools. These are the ones from PyYAML (Python, Ansible) and similar parsers that people search for most, and the usual cause of each:
| Error | Usual cause |
|---|---|
| mapping values are not allowed here | A value contains “: ”, or a line is indented too far. Quote the value or fix the indent. |
| found character '\t' that cannot start any token | A tab is used for indentation. Replace it with spaces. |
| did not find expected key | A line is out of line with its siblings, or a quote was opened and never closed. |
| could not find expected ':' | A line of text with no key, often the second line of a value that needed |. |
| found character '@' that cannot start any token | A value starts with @ or `. Quote it. |
| found undefined alias | A *name is used before its &name anchor, or the names differ. |
| duplicated mapping key | The same key appears twice in one map. PyYAML silently keeps the last one instead of failing. |
The line number in the message is where the parser gave up, which can be a line or two after the real mistake. Look at the line above as well, and paste the file into the checker to get the exact line and column.
Frequently asked questions
What is the difference between .yaml and .yml?
None. Both are the same format and every tool reads both. The YAML project recommends .yaml, but some tools look for one name specifically, such as docker-compose.yml or .github/workflows/*.yml, and accept either.
Can YAML use tabs?
Not for indentation. A tab at the start of a line is an error, so use spaces. Tabs are fine inside a value, such as inside quotes or a | block.
How do I comment out several lines in YAML?
YAML has no block comments, so put # at the start of each line. Most editors do this for you: select the lines and press Ctrl+/ (Cmd+/ on a Mac).
Is YAML a superset of JSON?
For practical purposes, yes. Since YAML 1.2, any JSON file is valid YAML, so you can paste JSON into a YAML file or mix the styles, such as ports: [80, 443] inside an indented file.
Sources
- YAML Ain’t Markup Language, version 1.2.2: syntax, block scalars, quoting and the core schema
- YAML 1.1 boolean type: yes, no, on and off as booleans
- YAML 1.1 merge key: the << key
- YAML FAQ: the .yaml file extension
- Docker Docs: Compose services, ports: why port mappings are quoted
- actions/setup-python: quoting Python versions in workflows
- PyYAML documentation: YAML 1.1 parsing and error messages
Related Tools
Build and preview Valorant crosshair settings.
Search common Vim commands.
Turn JSON rows into bar, line, or pie charts.
Convert WebP files and Base64 data in both directions.
Convert GIF files and Base64 data in both directions.
Save any GIF frame, or all frames, as JPG.