YAML
The indentation-based text format behind most cloud configuration: Kubernetes manifests, CI workflows and Compose files.
- What it is
- File formats (text and markup)
- Type
- Open source
- Made by
- YAML Language Development Team (open specification at yaml.org)
- License
- Open specification, free to implement; the spec may be freely copied unmodified
- Facts checked
- 6 October 2026
What it is
YAML describes the same data as JSON (mappings, sequences and scalars), but structure comes from indentation and - list markers instead of brackets. Indentation must be spaces; the spec forbids tabs there. Files can carry # comments, multi-line strings and several documents separated by ---. Unquoted values are typed by pattern matching: in YAML 1.2’s recommended core schema, true and false are booleans, null and ~ are null, things that look like numbers are numbers, and everything else is a string. An anchor (&base) names a node and an alias (*base) repeats it, and tags such as !!str or !!binary set a type explicitly. Since 1.2, every JSON document is also valid YAML.
The spec lives at yaml.org. The current text is revision 1.2.2 (October 2021), which made no normative changes to YAML 1.2 from 2009. Parsers don’t all follow it: PyYAML, Python’s widely used library, implements YAML 1.1 from 2005, where yes, no, on and off are booleans and 22:22 is a base-60 integer. There is nothing to buy; YAML is simply the configuration language of Kubernetes manifests, GitHub Actions workflows, Docker Compose files and the Prometheus config file.
Why teams pick it
- Easy for people to read and edit, with comments and clean multi-line strings, which is why so much configuration uses it
- A superset of JSON since 1.2, so tools such as Kubernetes accept either format
- Anchors and aliases remove repetition, and one file can hold several documents
- The default for Kubernetes, GitHub Actions, Compose and Prometheus, so one skill covers many tools
Watch out for
- Unquoted values get guessed types: under YAML 1.1 rules
NO(Norway’s country code) becomesfalseand22:22becomes 1342, and3.10is the float 3.1 in any version; quote strings to be safe - Indentation is syntax: one misplaced space silently moves a key to a different parent instead of causing an error
- Loaders that honour language tags can run code: PyYAML’s
yaml.loadcould call any Python function before 5.1, so usesafe_loadfor anything untrusted - Aliases can make a small file expand into a huge structure; the Kubernetes API server’s CVE-2019-11253 was fixed by capping request size and go-yaml’s alias expansion
- A long spec with versions that disagree, so the same file can load differently in different parsers
Alternatives
What all text and markup have in common →How it fits with other technologies
The Norway problem: PyYAML applies YAML 1.1 typing rules · python
# pip install pyyaml
import yaml
doc = """
country: NO # Norway's ISO code
python: 3.10
ports:
- 22:22
enabled: on
quoted: "NO"
"""
print(yaml.safe_load(doc))
# {'country': False, 'python': 3.1, 'ports': [1342], 'enabled': True, 'quoted': 'NO'}
# since PyYAML 6.0, yaml.load() needs an explicit Loader
yaml.load("a: 1") # TypeError: load() missing 1 required positional argument: 'Loader'
# safe_load refuses tags that construct arbitrary Python objects
yaml.safe_load("!!python/object/new:os.system [echo pwned]") # ConstructorErrorJSON, YAML, TOML and XML side by side#
Four text formats for structured data. They overlap, but each grew up around a different job, and that shows in what they leave out.
| JSON | YAML | TOML | XML | |
|---|---|---|---|---|
| Current spec | RFC 8259 and ECMA-404 (both December 2017) | YAML 1.2.2 (October 2021), a revision of 1.2 from 2009 | TOML 1.1.0 (December 2025) | W3C XML 1.0, Fifth Edition (November 2008) |
| Comments | None | # to the end of the line | # to the end of the line | <!-- … --> |
| Built-in value types | String, number, boolean, null | Null, boolean, integer, float and string in the recommended core schema; others through tags | String, integer, float, boolean, offset and local date-times, dates and times | None: content is text until a schema gives it types |
| Nesting | Objects and arrays | Mappings and sequences; anchors and aliases reuse a node | Tables, arrays, inline tables and arrays of tables | Elements with attributes; namespaces mix vocabularies |
| Schema language | JSON Schema, a separate spec (latest 2020-12) | None; the spec’s “schemas” only decide how unquoted values are typed | None in the spec | DTDs (part of XML 1.0), W3C XML Schema (XSD), RELAX NG |
| Typical use | Web API bodies; JSON Lines logs and events | Kubernetes manifests, GitHub Actions workflows, Compose files | Cargo.toml, pyproject.toml, Telegraf config | Office documents, SVG, RSS and Atom feeds, SOAP, the S3 API |
- Each cell is taken from the format’s own specification, and typical uses from the documentation of the tools named. The same table appears on the JSON, YAML, TOML and XML pages.
See it in a real stack
No architecture uses YAML yet. Drop it into the playground and wire it up yourself.Open playground →Where it came from2001–2021
Around 2001, Clark Evans and Oren Ben-Kiki were on the SML-DEV mailing list, which was trying to simplify XML, and Ingy döt Net had written a plain-text serialization module for Perl. Together they designed a data language for people first: readability heads their ranked list of goals, with matching the native data structures of dynamic languages third. The first YAML framework was written in Perl in 2001, Ruby shipped one in its core distribution in 2003, and after three years of design work on the yaml-core list, YAML 1.0 was published in January 2004.
YAML 1.1 followed in 2005, with generous implicit typing that read yes, no, on and off as booleans. Around then the authors noticed that JSON was, by coincidence, almost a subset of YAML. Kyrylo Simonov released PyYAML and LibYAML in 2006, and many other libraries built on them. YAML 1.2 (2009) made YAML a strict superset of JSON and dropped many of the problematic typing rules, but PyYAML, which many other libraries had used as a reference, still implements 1.1. A new design team began meeting in 2020 and published revision 1.2.2 in October 2021.
Why it’s built this way
- Indentation instead of brackets
- Human readability was the first design goal. Tabs are banned from indentation because different systems treat tabs differently.
- Guess types from unquoted values
- YAML wanted to match the native data of dynamic languages without type annotations. In 1.1 the guessing was broad, which caused the Norway problem; 1.2’s core schema narrowed booleans to
trueandfalse. - Anchors and aliases
- Repeated nodes are written once and referenced, so YAML can serialize shared objects and graphs, not just trees. Naive expansion of aliases later became a denial-of-service vector.
- Tags for language-specific types
- To be expressive and extensible, a tag can name any type. Libraries such as PyYAML used tags to rebuild arbitrary objects, which is why their default loaders were unsafe for untrusted input.
Timeline
- 2001
Design starts on yaml-core; the first YAML framework is written in Perl
- 2004
YAML 1.0 published (January)
- 2005
YAML 1.1, with
yes/noandon/offbooleans - 2006
Kyrylo Simonov releases PyYAML and LibYAML
- 2009
YAML 1.2 makes YAML a strict superset of JSON
- 2019
go-yaml caps alias expansion after a Kubernetes API server DoS
- 2021
Revision 1.2.2 (October); PyYAML 6.0 requires an explicit loader
- YAML 1.2.2 spec, 1.1 Goals and 1.2 YAML History
- yaml.org: list of specifications (1.0 January 2004, 1.1 January 2005, 1.2 July 2009, 1.2.2 October 2021)
- Boolean language-independent type for YAML 1.1 (y, yes, on, off and more)
- go-yaml pull request #515: tune alias heuristic, add max depth limits (October 2019)
- Kubernetes issue #83253: CVE-2019-11253, JSON/YAML parsing vulnerable to resource exhaustion
- PyYAML CHANGES: 6.0 (2021-10-13) always requires the `Loader` argument
Sources33 · facts checked 6 October 2026
- YAML Ain’t Markup Language, revision 1.2.2 (October 2021)
- yaml.org: YAML specifications and dates
- Boolean language-independent type for YAML 1.1
- PyYAML documentation: a complete YAML 1.1 parser
- PyYAML resolver.py: YAML 1.1 bool and base-60 int patterns
- PyYAML wiki: yaml.load(input) deprecation and loaders
- PyYAML CHANGES (6.0 requires an explicit Loader)
- NVD: CVE-2019-11253 (Kubernetes API server YAML/JSON resource exhaustion)
- Kubernetes pull request #83261: limit YAML/JSON decode size, bump go-yaml to v2.2.4
- go-yaml pull request #515: alias expansion limits
- Kubernetes docs: Objects in Kubernetes (manifests are YAML by convention)
- GitHub Docs: Workflow syntax for GitHub Actions (workflow files use YAML)
- Docker Docs: Compose file reference
- Prometheus docs: Configuration (the file is written in YAML)
- RFC 8259: The JavaScript Object Notation (JSON) Data Interchange Format (December 2017)
- ECMA-404: The JSON data interchange syntax, 2nd edition (December 2017)
- JSON Schema: Specification (latest meta-schema 2020-12)
- JSON Lines: text format, also called newline-delimited JSON
- TOML v1.1.0 specification
- toml-lang/toml: 1.1.0 release notes (24 December 2025)
- The Cargo Book: The manifest format (`Cargo.toml` is written in TOML)
- Python Packaging User Guide: `pyproject.toml` specification
- Telegraf docs: Configure Telegraf (a TOML configuration file)
- W3C: Extensible Markup Language (XML) 1.0, Fifth Edition (26 November 2008)
- W3C XML Schema Definition Language (XSD) 1.1 Part 2: Datatypes (April 2012)
- RELAX NG home page (ISO/IEC 19757-2)
- W3C: Namespaces in XML 1.0, Third Edition (December 2009)
- ECMA-376: Office Open XML file formats
- W3C: Scalable Vector Graphics (SVG) 2, a language based on XML
- RSS Advisory Board: RSS 2.0 specification (RSS is a dialect of XML)
- RFC 4287: The Atom Syndication Format (December 2005)
- W3C: SOAP Version 1.2 Part 1: Messaging Framework (Second Edition)
- Amazon S3 API Reference: ListObjectsV2 (XML response)