TOML format: a less ambiguous YAML for config files

3 min read

TOML (Tom’s Obvious Minimal Language) is designed for config files. Less ambiguous than YAML and easier to write than JSON. This article walks through the syntax and use cases.

Basics

# Comments use #

title = "TOML example"

[owner]
name = "Tom Preston-Werner"
created = 1979-05-27T07:32:00-08:00

[database]
server = "192.168.1.1"
ports = [8001, 8001, 8002]
connection_max = 5000
enabled = true

Features:

  • INI-file feel.
  • Sections (tables) via [name].
  • No indentation needed.
  • Strict, explicit types.

Types

TypeExample
String"hello", 'literal'
Int42, 0xff, 0o77, 0b1010
Float3.14, 1e10
Booleantrue, false
Datetime1979-05-27T07:32:00Z
Date1979-05-27
Time07:32:00
Array[1, 2, 3]
Table{ key = "value" }
Array of tables[[products]]

String forms

Four kinds:

# Basic (escapes allowed)
str1 = "I'm a "quoted" string"

# Literal (no escapes, single quotes)
str2 = 'C:Users\nodejs\templates'

# Multiline basic
str3 = """
Roses are red
Violets are blue"""

# Multiline literal
str4 = '''
This is
literal
'''

Tables (sections)

Hierarchy via [a.b.c]:

[servers.alpha]
ip = "10.0.0.1"
port = 8080

[servers.beta]
ip = "10.0.0.2"
port = 8081

Inline form:

[servers]
alpha = { ip = "10.0.0.1", port = 8080 }
beta = { ip = "10.0.0.2", port = 8081 }

Array of tables

List of table values:

[[products]]
name = "Hammer"
sku = 738594937

[[products]]
name = "Nail"
sku = 284758393
color = "gray"

In JSON:

{
	"products": [
		{ "name": "Hammer", "sku": 738594937 },
		{ "name": "Nail", "sku": 284758393, "color": "gray" }
	]
}

Dates

Native date types:

# UTC
date1 = 1979-05-27T07:32:00Z

# Local datetime (no zone)
date2 = 1979-05-27T07:32:00

# Date only
date3 = 1979-05-27

# Time only
time = 07:32:00

Less ambiguous than YAML.

Conversion to JSON

Same data, two formats:

title = "TOML"

[database]
server = "localhost"
ports = [8001, 8002]
{
	"title": "TOML",
	"database": {
		"server": "localhost",
		"ports": [8001, 8002]
	}
}

Round-trips cleanly (comments lost in JSON).

TOML vs YAML

PropertyTOMLYAML
IndentationNone requiredSignificant
AmbiguityLowHigh (Norway problem etc.)
CommentsYesYes
Date typeExplicitYes (impl-dependent)
Learning curveLowMedium
Deep nestingAwkwardGood

Choose TOML for config, YAML for deeply structured data.

Where it’s used

Cargo (Rust)

Cargo.toml:

[package]
name = "my-app"
version = "0.1.0"
edition = "2021"

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

Python (pyproject.toml)

Standardized in PEP 518, PEP 621:

[build-system]
requires = ["setuptools >= 61"]
build-backend = "setuptools.build_meta"

[project]
name = "my-package"
version = "1.0.0"
dependencies = [
    "requests >= 2.28",
    "click >= 8.0"
]

Replacing setup.py over time.

Hugo (static site generator)

config.toml (or hugo.toml):

baseURL = "https://example.com"
title = "My Blog"
languageCode = "en"

[params]
description = "Site description"

Pitfalls

Duplicate keys are errors

# Error
name = "first"
name = "second"

Stricter than YAML or JSON.

Table order

[a]
key = 1

[b]
key = 2

[a.c]  # OK — child of [a]
key = 3

But re-opening [a] is forbidden:

[a]
key = 1

[b]
# ...

[a]  # Error: already defined
other = 2

String escapes

Basic strings treat \ as special:

# Error (U is reserved)
path = "C:Users"

# OK (literal)
path = 'C:Users'

# OK (escaped)
path = "C:\Users"

Use literal strings for Windows paths.

Spec versions

  • 0.5.0 (2018) — widely deployed.
  • 1.0.0 (Jan 2021) — official release.
  • 1.1.0 — proposed extensions.

Use TOML 1.0 for new projects.

Tools

Libraries:

  • Rust — toml.
  • Python — tomllib (stdlib 3.11+), tomli.
  • Go — BurntSushi/toml.
  • JavaScript — @iarna/toml, toml.
  • Java — tomlj.

When to pick TOML

Good fit:

  • Config files (especially technical).
  • Package-manager manifests.
  • Flat-ish settings.

Poor fit:

  • Deeply nested data.
  • Streaming pipelines.
  • Bulk data transfer.

Summary

  • TOML is INI-style, type-explicit config format.
  • Used by Cargo, Python’s pyproject.toml, Hugo.
  • Stricter than YAML, friendlier than JSON.
  • Pick TOML for config; JSON for data interchange.

To convert TOML to JSON, the TOML-to-JSON tool on this site handles the typical cases.