TOML (Tom's Obvious, Minimal Language) is a config-file format created by GitHub co-founder Tom Preston-Werner. It was designed to map unambiguously to a hash table: any two compliant parsers reading the same file produce the exact same structure, with nothing left to interpretation.

That predictability is the whole point. Where YAML's indentation-based nesting and implicit type coercion (a bare NO silently parsing as boolean false is the classic example) leave room for parsers to disagree, every TOML value only has one valid reading. It ships as a versioned spec at toml.io, currently at 1.0.0/1.1.0.

Anatomy of a TOML file

Flat key-value pairs at the top, grouped into named tables below:

name = "my-app"
version = "1.2.0"
authors = ["Alice", "Bob"]

[dependencies]
serde = "1.0"
tokio = { version = "1", features = ["full"] }

[[bin]]
name = "server"
path = "src/main.rs"

A [table] header groups the keys under it, equivalent to a nested JSON object. A [[array-of-tables]] header (double brackets) starts a new entry in an array every time it repeats, equivalent to a JSON array of objects — that's what [[bin]] becomes if it appears twice in the file.

Types, including a native date

TOML's type system is deliberately small: strings, integers, floats, booleans, arrays, tables, and one type most config formats leave out entirely: a first-class date-time.

created_at = 2024-01-15T09:00:00Z   # offset date-time, no quotes needed
release_date = 2024-01-15           # local date
port = 8080
timeout = 30_000                    # underscores allowed as digit separators
debug = false
tags = ["api", "auth"]

Because 2024-01-15T09:00:00Z is a real typed value and not a string, a TOML parser can validate it's a well-formed date at parse time. Converted to JSON, it becomes an ISO 8601 string, since JSON has no native date type of its own.

TOML vs YAML vs JSON

TOMLYAMLJSON
NestingExplicit [table] headersIndentationBraces
Comments##None
Native datesYesYes (implicit)No — strings only
AmbiguityNone by designNorway problem, tab-vs-space, 1.1 vs 1.2 parsersNone
Written byHumans, config filesHumans, config filesMachines, API payloads

Pick TOML when you want config that's diffable and unambiguous without YAML's indentation risk. Pick JSON for anything machine-generated or API-facing.

What TOML cannot represent

No null value

The spec never defined one. A key either has a real value or it's absent from the document, there's no third state for "present but empty." Converting JSON to TOML, a null field has to be resolved first: drop the key, or replace it with a real value.

No top-level array

A TOML document is always a table at the root. ["a", "b", "c"] on its own isn't valid TOML; it has to be wrapped in a key first, e.g. items = ["a", "b", "c"].

This site's TOML ↔ JSON Converter checks for both cases up front and tells you exactly which key is the problem, rather than silently dropping data.

Where TOML is used

Cargo.toml is the manifest for every Rust package: dependencies, features, build targets. pyproject.toml is the standard build-system and tool config for Python (PEP 518/621), read by Poetry, Black, and Ruff. Hugo, Gitea, and a long list of CLI tools default to TOML for their own config files, for the same reason: predictable parsing without a YAML indentation mistake breaking a build.

Frequently asked questions

Tom's Obvious, Minimal Language, created by GitHub co-founder Tom Preston-Werner. It was designed to map unambiguously to a hash table, so any two compliant parsers produce the exact same structure from the same file.

That predictability is the whole point: unlike YAML, where 1.1 and 1.2 parsers can disagree on what a bare "yes" or "NO" means, a TOML value only ever has one valid interpretation.