Upload a TOML file and format it into a clean, readable TOML output in seconds—right in your browser.
cargo fmt conventions) or 4 spaces. TOML itself is whitespace-insensitive inside tables, but consistent indent makes diffs cleaner and aligns with the dominant Rust/Python community style..toml file. Everything runs in your browser — no upload, no signup, no telemetry. Inline error messages flag invalid syntax (unbalanced brackets, duplicate keys, malformed datetimes) with the offending line.TOML (Tom's Obvious, Minimal Language) was created by Tom Preston-Werner in 2013 and reached its stable 1.0.0 specification on January 11, 2021. It's the configuration format of choice for some of the most-used developer tools on the planet: Rust's Cargo.toml, Python's pyproject.toml (PEP 518/621), Hugo's hugo.toml, Poetry, Ruff, Black, mypy, pytest, and more. A clean, consistently-formatted TOML file makes code review, diffing, and onboarding easier — and quickly surfaces typos or duplicate keys that the spec rejects.
[dependencies] entry so serde = { version = "1.0", features = ["derive"] } lines up cleanly and git diffs only show real changes.[tool.ruff], [tool.mypy], [tool.pytest.ini_options], etc. A single formatter pass keeps every tool section visually consistent.hugo.toml (the older config.toml name still works but isn't recommended); a formatted file with sorted [params] and [menu] blocks is far easier to maintain across themes.[tables], and malformed RFC 3339 datetimes all fail with a clear line number.--config CLI flag or environment variable? Minify trims comments and excess whitespace down to the smallest legal TOML.| Property | TOML | YAML | JSON |
|---|---|---|---|
| Comments | # line comments |
# line comments |
Not allowed (JSONC/JSON5 add them) |
| Indentation significance | None — whitespace-insensitive inside tables | Significant — wrong indent breaks parsing | None — braces and commas define structure |
| Native datatypes | String (4 variants), int (dec/hex/oct/bin), float, bool, 4 datetime variants, array, table, inline table, array of tables | String, int, float, bool, null, sequence, mapping (plus implicit coercions) | String, number, bool, null, array, object |
| Native datetime | RFC 3339 offset, local datetime, local date, local time | ISO 8601 (per spec) — support varies by parser | None — encode as string |
| Multi-document | One document per file | Multiple docs separated by --- |
One value per file |
Norway problem (no parsed as bool) |
No — TOML quotes string literals | Yes in YAML 1.1; YAML 1.2 fixes it but many parsers still default to 1.1 | No — strings are quoted |
| Spec stability | 1.0.0 (Jan 2021), 1.1.0 (Dec 2025) | 1.2.2 (Oct 2021) | RFC 8259 / ECMA-404 |
| Best fit | Application & tooling config (pyproject, Cargo, Hugo) | CI/CD, Kubernetes manifests, Ansible playbooks | API payloads, machine-generated data |
| Comments survive round-trips | Lost on most programmatic round-trips (without tomlkit / toml_edit) |
Lost on most round-trips (without ruamel.yaml) |
N/A — none to preserve |
| Type | Example | Notes |
|---|---|---|
| Basic string | name = "TOML" |
Backslash escapes (\n, \t, é); double quotes |
| Multi-line basic string | desc = """line 1\nline 2""" |
Triple double quotes; escapes allowed; leading newline trimmed |
| Literal string | path = 'C:\Users\nodejs' |
Single quotes; no escapes — what you see is what you get |
| Multi-line literal string | regex = '''<\d+>.*?</\d+>''' |
Triple single quotes; ideal for regex, Windows paths, HEREDOCs |
| Integer (decimal) | port = 8080 |
Underscores allowed: 1_000_000 |
| Integer (hex/oct/bin) | mask = 0xff, 0o755, 0b1010 |
All since 0.5.0; signed not allowed on non-decimal |
| Float | pi = 3.14159, inf, nan |
IEEE 754 binary64; special values inf/-inf/nan |
| Boolean | enabled = true |
Lowercase only — True is invalid |
| Offset datetime | t = 1979-05-27T07:32:00-08:00 |
RFC 3339 with -08:00 offset or Z for UTC |
| Local datetime | t = 1979-05-27T07:32:00 |
No timezone — "wall clock" time |
| Local date / time | d = 1979-05-27, t = 07:32:00 |
Date or time alone, no offset |
| Array | ports = [80, 443, 8080] |
Mixed types allowed in 1.0+; trailing commas allowed |
| Table | [server] then host = "x" |
Section header; whitespace-insensitive inside |
| Inline table | point = { x = 1, y = 2 } |
Single line; immutable once defined |
| Array of tables | [[products]] repeated |
Each [[header]] appends a new table element |
| Dotted keys | server.http.port = 80 |
Implicitly creates [server] and [server.http] |
| Comment | # config for prod |
# to end of line; not allowed inside strings as a comment |
The current stable spec is TOML 1.0.0, released January 11, 2021 — that's what most parsers (Python tomllib, Rust toml/toml_edit, Go BurntSushi/toml) target. TOML 1.1.0 shipped in December 2025 and adds inline-table flexibility (trailing commas, newlines inside braces), optional seconds in temporal values, and a few other small improvements. The formatter accepts the 1.0.0 grammar by default; 1.1.0-only constructs may be reformatted into 1.0.0-compatible equivalents.
Rust's Cargo ships Cargo.toml as its manifest format. Python's modern packaging standard is pyproject.toml (defined in PEP 518 for build-system requirements and PEP 621 for project metadata) — it's used by Poetry, Hatch, PDM, setuptools, plus tool sections for Ruff, Black, mypy, pytest, isort, and Coverage. Hugo uses hugo.toml (renamed from config.toml after v0.110), and projects like Bottle, Traefik, Helm subcharts, Black, and many GitHub Actions step into TOML as well.
A hash symbol # marks the rest of the line as a comment, unless it appears inside a string literal. Block comments don't exist — wrap multi-line notes with multiple # lines instead. Comments may appear above key/value lines, above table headers, or after a value on the same line. Most programmatic parsers (tomllib, toml, serde_toml) discard comments on parse; if you need to preserve them through edit/save cycles use a style-preserving parser like Python's tomlkit or Rust's toml_edit.
Use dotted keys when you have only a couple of nested keys and the parent table doesn't need its own header: server.http.port = 80 is concise and creates [server.http] implicitly. Use inline tables (point = { x = 1, y = 2 }) for fixed records that conceptually represent a single value — Cargo's serde = { version = "1.0", features = ["derive"] } is the canonical example. For larger or growable sections, use the full [header] form so each field gets its own line. Inline tables are immutable after definition — you cannot add more keys to them later in the file.
[[x]]) work?The double-bracket header [[products]] declares an array element. The first time it appears, TOML creates the array products and inserts a new empty table; each subsequent [[products]] appends another table. Inside each one, you set normal key/value lines:
[[products]]
name = "Hammer"
sku = 738594937
[[products]]
name = "Nail"
sku = 284758393
Order matters — tables are inserted in the order they appear. Use this for repeated structures like Cargo's [[bin]]/[[example]] targets or a list of users in a config file.
"""...""" is a multi-line basic string: backslash escapes work (\n, \t, \uXXXX), and you can end a line with a single \ to elide the trailing newline plus following whitespace. '''...''' is a multi-line literal string: no escapes, no interpretation — bytes between the delimiters are taken as-is. Use literal for regex patterns, Windows paths ('C:\Users\me'), JSON-embedded-in-TOML strings, and anything else where backslashes are meaningful. A newline immediately after the opening delimiter is trimmed by the spec in both forms.
Four variants, all from RFC 3339:
1979-05-27T07:32:00-08:00 (or Z for UTC). Fully timezone-aware.1979-05-27T07:32:00 (no offset). Represents wall-clock time without a zone.1979-05-27. A calendar date with no time.07:32:00. A time of day with no date.Fractional seconds are allowed (07:32:00.999). The T separator can be a space (1979-05-27 07:32:00) for readability. TOML 1.1.0 makes the seconds field optional in some contexts, but for 1.0.0 compatibility include it.
By default no — keys stay in the order you wrote them, which preserves the intent of files where ordering carries meaning ([[bin]] lists in Cargo, [tool.poetry.dependencies] in pyproject, ordered Hugo menu entries). The formatter only normalises whitespace, indentation, comment alignment, and inline-vs-expanded table style. If you need alphabetic sorting use a dedicated tool like taplo fmt --option sort_keys=true or Prettier's prettier-plugin-toml.
No. The TOML Formatter runs entirely in your browser — your file never leaves the tab. There are no network requests after the initial page load, so secrets in environment-style sections ([env], [secrets], API tokens in tool configs) stay on your machine. The page also works offline once loaded.
This page is a formatter only — it normalises TOML in place. For TOML→JSON conversion, the simplest path is the Python one-liner python -c "import tomllib,json,sys; print(json.dumps(tomllib.loads(sys.stdin.read())))" (Python 3.11+). For TOML↔YAML, use the YAML to JSON and JSON to YAML converters along with a TOML→JSON step. For pretty-printing the JSON output, paste it into the JSON Formatter.