File types · Explainer

The YAML file (.yaml, .yml)

A YAML file is a plain-text file that stores settings and structured data using indentation instead of brackets, so people can read and edit it easily. This guide explains the syntax, the typing surprises that catch everyone out, how to load it safely, and has free sample YAML files to download for testing.

At a glance

Full name
YAML Ain't Markup Language
Extensions
.yaml (preferred by RFC 9512) and .yml
MIME type
application/yaml (RFC 9512, 2024); text/yaml, text/x-yaml and application/x-yaml are older, unregistered names
Kind
Plain text (structured data)
Encoding
UTF-8 recommended; parsers must also read UTF-16, and UTF-32 for JSON compatibility
Standard
YAML 1.2.2 (2021), from the YAML Language Development Team
First released
YAML 1.0 in 2004, by Clark Evans, Oren Ben-Kiki and Ingy döt Net; work began in 2001
Data types
Mappings, sequences and scalars (strings, numbers, booleans, null), plus tags for others
Comments
Yes, from # to the end of the line
Opens with
Any text editor or code editor
Magic number
None; a file may start with --- or a %YAML 1.2 directive

The basics

What is a YAML file?

A YAML file stores data as text that reads almost like a set of notes: a key, a colon and a value on each line, with indentation for anything nested and dashes for lists. It holds the same kinds of data as JSON (objects, lists, text, numbers, booleans and null) but adds comments, multi-line text and a way to reuse parts of the file.

It's mostly used for configuration that people edit by hand: Docker Compose files, Kubernetes manifests, CI pipelines such as GitHub Actions and GitLab CI, Ansible playbooks, OpenAPI descriptions, and the front matter at the top of Markdown pages in static site generators.

Three things YAML is not:

  • Not markup. It has no tags around text, and its name says so: YAML Ain't Markup Language.
  • Not forgiving about whitespace. Indentation is the structure. One space too many or too few changes the data or stops the file from loading.
  • Not a schema. A YAML file doesn't say which keys are required or what they mean. Each tool that reads it decides that, and editors can check it with a JSON Schema.

Anatomy

What's inside a YAML file

YAML has three building blocks: mappings (key: value pairs), sequences (lists) and scalars (single values such as text or numbers). Indentation shows what belongs inside what. Here is a small but complete file, part by part.

config.yaml
# Settings for a small web app
name: Sample app
version: "2.10"
debug: false
port: 8080
owner: ~
database:
  host: db.example.internal
  ports: [5432, 5433]
servers:
  - name: web-1
    region: eu-west
  - name: web-2
    region: us-east
defaults: &defaults
  retries: 3
worker:
  <<: *defaults
  timeout: 30
motd: |
  Line one
  Line two
  1. 1# Settings for a small web app

    A comment

    Everything from # to the end of the line is ignored. The # must be at the start of a line or after a space: color: #fff is a comment too, so color ends up empty.

  2. 2name: Sample app

    A key and a value

    A key, a colon, a space, then the value. The space after the colon is required. Text needs no quotes unless it could be read as something else.

  3. 3version: "2.10"

    A quoted string

    Unquoted, 2.10 would load as the number 2.1. Quotes keep version numbers, postcodes and IDs with leading zeros as text.

  4. 4debug: false

    A boolean

    true or false. In the older YAML 1.1 rules, yes, no, on and off are booleans as well; see the Norway problem below.

  5. 5port: 8080

    A number

    Plain digits load as an integer, 0.75 as a float. YAML 1.2 also reads 0o14 as octal and 0x1F as hexadecimal.

  6. 6owner: ~

    Null

    ~, null or nothing at all after the colon all mean an empty value.

  7. 7database: host: …

    A nested mapping

    Indented lines belong to the key above them. Use spaces only: YAML forbids tabs in indentation. Two spaces per level is the usual style, but any consistent number works.

  8. 8ports: [5432, 5433]

    A flow sequence

    A list in square brackets, as in JSON. Mappings can be written in braces the same way: {host: db, port: 5432}.

  9. 9- name: web-1 region: eu-west

    A block sequence of mappings

    Each - starts a list item. Here each item is itself a mapping, the usual shape for lists of servers, users or build steps.

  10. 10&defaults … <<: *defaults

    An anchor, an alias and a merge key

    &defaults names a node and *defaults refers back to it. The << merge key copies its keys into worker, which then adds its own. Merge keys come from YAML 1.1; most parsers still support them.

  11. 11motd: |

    A block scalar

    | keeps the line breaks of the indented text below it; > folds them into spaces. Useful for messages, scripts and certificates.

Under the hood

Quoting and types: how YAML decides what a value is

An unquoted value is a plain scalar, and the parser guesses its type from what it looks like: 42 becomes a number, true a boolean, null empty, everything else text. That guessing makes YAML pleasant to write and is also the source of most of its surprises. Quoting a value always makes it a string.

Written asLoads as (YAML 1.2)Note
port: 8080Integer 8080
version: 3.10Float 3.1The trailing zero is lost. Write "3.10".
zip: 01234Integer 1234Leading zero dropped.
released: 2026-10-27Text in the core schema; a date in PyYAML, js-yaml and ruamel.yamlMany loaders still add the YAML 1.1 timestamp type.
path: 'C:\Users\ada'Text, backslashes keptIn single quotes nothing is escaped; write '' for a quote.
msg: "a\tb"Text with a tabDouble quotes allow escapes such as \t, \n and \u00e9.
title: Note: read meErrorA second colon and space starts another mapping. Quote the value.
color: #fffNull# after a space starts a comment. Quote it.
key: @adminError@ and the backtick are reserved and can't start a plain value.

When in doubt, quote it

Values that start with *, &, !, %, @, {, [, |, >, # or a quote, values that contain : or #, and anything that looks like a number, date or boolean but should stay text: put them in quotes.

Versions

The Norway problem: YAML 1.1 vs YAML 1.2

YAML 1.1 (2005) recognised many more booleans and number formats than you'd expect. A list of country codes containing NO, for Norway, loads as false. YAML 1.2 (2009) cut the implicit types down to a small core schema, mainly to make YAML a superset of JSON, but many popular parsers still follow the 1.1 rules. The result: the same file can produce different data in different tools.

What `sample-norway-problem.yaml` loads as, tested with PyYAML 6.0 and js-yaml 4.1 / ruamel.yaml 0.19
Written asYAML 1.1 (PyYAML)YAML 1.2 (js-yaml, ruamel.yaml)
NOfalse"NO"
yes, no, on, offtrue, falseText
On (as in light: On)true"On"
0755493 (octal)755
0o755"0o755" (text)493
0123455349 (octal)12345
1:3090 (base 60)"1:30"
1e3"1e3" (text)1000
on: as a keyThe boolean true"on"

The YAML 1.1 boolean type also lists y and n, but PyYAML doesn't apply that rule, so it reads them as text. The last row matters for CI files: a GitHub Actions workflow starts with on:, which PyYAML loads as the key True. Try it with sample-workflow.yml.

How to avoid it

Quote values that must stay text, especially country codes, versions, postcodes, times and IDs. If you choose the parser, prefer one that follows YAML 1.2. A %YAML 1.2 line at the top documents the intent, though not every parser changes its behaviour because of it.

Features

Anchors, aliases and multiple documents

Anchors and aliases avoid repetition. &name marks a value and *name reuses it later in the same file. With the << merge key, a mapping can copy another mapping's keys and override some of them, which is how Docker Compose and CI files share settings between services or jobs.

anchors.yaml
base: &base
  timeout: 30
  retries: 3
service:
  <<: *base
  timeout: 5     # overrides the merged value

When a loader reads this, service simply contains timeout: 5 and retries: 3. The anchor itself disappears: converting the file to JSON writes the values out in full.

Multiple documents can share one file, separated by a line with ---. A line with ... marks the end of a document. Kubernetes uses this to put several resources in one manifest. Most libraries have a separate function for it, such as yaml.safe_load_all in Python or loadAll in js-yaml; the single-document function raises an error when it finds a second document.

Comparison

YAML vs JSON, TOML and XML

YAMLJSONTOMLXML
Structure fromIndentationBrackets and braces[sections] and key = valueTags
CommentsYes, #NoYes, #Yes, <!-- -->
Implicit typesMany, version-dependentFew and strictFew and strictNone: everything is text
Reuse within a fileAnchors and aliasesNoNoEntities
Several documents per fileYes, ---No (JSON Lines is one per line)NoNo
Typical useConfig people edit: CI, Kubernetes, ComposeAPIs, data exchange, generated configApp config: pyproject.toml, Cargo.tomlDocuments, older enterprise formats

YAML 1.2 was designed so that a JSON document is also valid YAML: a YAML parser reads {"a": [1, 2]} as it is. The reverse isn't true, and converting YAML to JSON drops comments and writes anchors out in full.

Troubleshooting

Why won't my YAML load?

  • A tab in the indentation. PyYAML reports found character '\t' that cannot start any token. Set your editor to insert spaces in YAML files.
  • Inconsistent indentation. Sibling keys must start in the same column. Errors such as while parsing a block mapping or bad indentation of a mapping entry usually point at the line after the real mistake.
  • mapping values are not allowed here. A value contains a colon followed by a space, as in title: Note: read me. Quote the value.
  • found undefined alias. A value starts with * but isn't an alias. Quote it, or define the anchor before it is used.
  • Template braces. name: {{ project }} from a templating tool is read as a flow mapping and fails. Quote it: name: "{{ project }}".
  • Duplicate keys. The spec says keys must be unique, but parsers differ: PyYAML silently keeps the last value, js-yaml stops with duplicated mapping key.
  • The data is wrong but there's no error. Check the Norway problem table above: an unquoted NO, 3.10 or 0755 is the usual cause.

To find problems before a tool does, run yamllint file.yaml, which checks syntax, indentation, duplicate keys and style, or open the file in VS Code with a YAML extension that validates against the tool's JSON Schema.

How to

How to open, edit and convert a YAML file

  • Open and edit it: any text editor works. A code editor such as VS Code, with a YAML extension, adds syntax highlighting, indentation guides and validation. Avoid word processors, which change quotes and may insert tabs.
  • View it in a browser: browsers show a YAML file as plain text when it's served as text; some download it instead, depending on the type the server sends.
  • Convert to JSON: yq -o=json file.yaml with the Go version of yq, or in Python json.dumps(yaml.safe_load(open('file.yaml'))). Comments are lost.
  • Convert JSON to YAML: yq -p json -o yaml file.json. Because YAML 1.2 accepts JSON, you can also rename a .json file to .yaml and it still loads.
  • Query or change values from the command line: yq '.database.host' config.yaml reads one value; yq -i '.port = 9090' config.yaml edits it in place.
  • .yaml or .yml: the content is identical. RFC 9512 prefers .yaml; some tools look for one spelling only, such as docker-compose.yml or .github/workflows/*.yml, so match what the tool documents.

Security

Is YAML safe? Unsafe loading and alias bombs

YAML tags such as !!python/object/apply ask the parser to build objects of a given type. A loader that honours them for any type can be made to run code just by reading a file. This has caused real vulnerabilities:

  • PyYAML before 5.1 ran such tags through the default yaml.load() (CVE-2017-18342). Since 6.0, yaml.load() requires an explicit Loader. Use yaml.safe_load() for anything from outside, and never yaml.unsafe_load().
  • SnakeYAML (Java) let its default Constructor build any class on the classpath until version 2.0, released in 2023 (CVE-2022-1471). Upgrade, or use SafeConstructor on older versions.
  • Ruby's Psych made YAML.load safe by default in version 4, which ships with Ruby 3.1.

Even a safe loader can be overwhelmed. Aliases that point to sequences of aliases, nine levels deep, expand a file of a few hundred bytes into hundreds of millions of values: the YAML version of the XML "billion laughs" attack. RFC 9512 recommends limiting alias expansion and validating untrusted input. Set size and alias limits where your library allows them; some, such as SnakeYAML, cap the number of aliases by default.

Configuration files often end up holding passwords and API keys. Keep secrets out of YAML that is committed to a repository or shared as a link; use environment variables or a secrets manager, and reference them from the file.

Free downloads

Sample YAML files to download

Free sample YAML files for testing parsers, config loaders, CI tools and upload limits. Each one loads without errors in PyYAML, ruamel.yaml, js-yaml and the yaml package for JavaScript.

sample-config.yaml · 2.0 KBDownloadOpen
Loading…

What's inside sample-config.yaml

The file is commented: each numbered comment marks one of these parts.

  1. Comments 1 and 15: document markers

    --- starts the document and ... ends it. Both are optional in a single-document file, but some tools write them.

  2. Comments 2 to 7: scalars

    Plain text, a quoted version number, a boolean, integers, a float, a null and a date that most loaders turn into a date object.

  3. Comment 8: nesting

    A database mapping with an options mapping inside it, indented with two spaces per level.

  4. Comments 9 to 11: lists

    A block sequence, a flow sequence and a flow mapping in JSON-like brackets, and a list of mappings.

  5. Comment 12: anchor, alias and merge

    worker merges the keys of defaults and overrides log_level, so it loads as retries: 3, log_level: debug.

  6. Comment 13: multi-line text

    A literal block (|) that keeps its line breaks and a folded block (>) that joins its lines with spaces.

  7. Comment 14: quoting

    A quoted "NO", a Windows path in single quotes, escapes in double quotes, a value with a colon, and text in German, Japanese and Arabic with an emoji.

All sample YAML files

  • Commented config file

    sample-config.yaml · 2.0 KB (2,041 bytes)

    An app configuration with 15 numbered comments covering scalars, nesting, both list styles, an anchor with a merge key, block scalars, quoting and Unicode.

    • Teaching the parts of a YAML file
    • Testing config loaders and syntax highlighting
  • YAML 1.1 vs 1.2 differences

    sample-norway-problem.yaml · 549 bytes

    Values that load differently under the 1.1 and 1.2 rules: NO, yes/no/on/off, y/n, 3.10, 0755, 0o755, 012345, 1:30, 1e3, .nan and -.inf.

    • Finding out which rules your parser follows
    • Comparing parsers and languages
  • Anchors, aliases and merge keys

    sample-anchors.yaml · 783 bytes

    A reused scalar, mapping and sequence, a merge with an override, and a merge of two mappings where the first one wins.

    • Testing alias and merge-key support
    • Checking YAML-to-JSON conversion
  • Three documents in one file

    sample-multi-document.yaml · 896 bytes

    A ConfigMap, a Deployment and a Service in the style of a Kubernetes manifest, separated by --- and ended with .... All names are fictional.

    • Testing multi-document loading
    • Checking tools that split or merge manifests
  • CI workflow (.yml)

    sample-workflow.yml · 687 bytes

    A test-and-build workflow in the style GitHub Actions uses, with the .yml extension, a matrix, ${{ }} expressions and an on: key that YAML 1.1 loaders turn into true.

    • Testing `.yml` uploads and content-type handling
    • Showing the `on:` key problem
  • 1 MB YAML file

    sample-1mb.yaml · 1 MB (1,048,576 bytes)

    A list of 8,783 fictional records, padded with a final comment to exactly 1,048,576 bytes (1 MiB).

    • Upload and request-size limits
    • Parser performance

Ways to test with them

  • Which rules your parser follows: load sample-norway-problem.yaml and look at countries. ["GB", false, "SE"] means YAML 1.1 rules; ["GB", "NO", "SE"] means YAML 1.2.
  • Multi-document support: a single-document loader should report an error on sample-multi-document.yaml; a multi-document loader should return three documents.
  • Merge keys: service in sample-anchors.yaml should load as timeout: 5, retries: 3, name: search.
  • Upload limits and .yml: sample-1mb.yaml is exactly 1,048,576 bytes, and sample-workflow.yml checks that both extensions are accepted and served as text.

Free to use for testing, teaching and demos, commercially or not, with no attribution needed. A link back to this page is always appreciated.

Put it online

Have a YAML file? Give it a link.

Drop a YAML file on 99helpers and it gets its own web address, for a config example, an OpenAPI description or a test fixture. Visitors can read it in the browser or download it, and scripts can fetch it from the link.

Questions

YAML files, frequently asked

What does YAML stand for?

YAML Ain't Markup Language, a recursive name that stresses it is for data, not for marking up documents.

What's the difference between .yaml and .yml?

None in the content. RFC 9512 prefers .yaml, and .yml is common too. Some tools only look for one spelling, so use whichever the tool's documentation shows.

How do I open a YAML file?

With any text editor, such as Notepad, TextEdit in plain-text mode or VS Code. A code editor with a YAML extension highlights the structure and flags indentation errors.

Can YAML use tabs?

Not for indentation: the spec forbids it, and parsers stop with an error. Tabs are allowed inside quoted text. Configure your editor to insert spaces in YAML files.

What is the Norway problem?

Under the YAML 1.1 rules, the unquoted country code NO loads as the boolean false, along with yes, no, on and off. YAML 1.2 fixed it, but many parsers still use 1.1 rules, so quote such values.

Is JSON valid YAML?

Yes, under YAML 1.2, which was designed as a superset of JSON. A YAML 1.2 parser reads a JSON file and returns the same data.

How do I convert YAML to JSON?

Use yq -o=json file.yaml, or load it with a YAML library and write it out with a JSON library. Comments disappear and anchors are written out in full.

Is it safe to load a YAML file?

With a safe loader, yes. Unsafe loaders can build arbitrary objects and run code from a crafted file, so use functions like Python's yaml.safe_load(), and limit size and aliases for untrusted input.

Related formats

Other file types explained

Keep going

Related

Sources

Last reviewed 27 October 2026.