TOML Formatter & Validator

Format and validate TOML with a full TOML 1.0 parser built for this tool — duplicate keys, dotted-key table traps and impossible dates caught with line and column, while every scalar spelling is preserved byte-for-byte. Free, no sign-up — runs locally in your browser.

…or drop a file onto the panel. Files are read locally and never uploaded.

Configuration files often deserve discretion, so this tool deliberately does not auto-save your input — paste, format, copy, and it is gone when you leave.

TOML fails quietly — until it doesn't

TOML is the configuration language of Rust, Python packaging and half the modern toolchain, and its failure mode is treacherous: a file can look perfectly tidy and still be invalid in ways only a real parser sees. A key defined twice under two tables. A header reopening a table that dotted keys created three sections earlier. February 30th, typed with total confidence. Most “TOML formatters” online never parse the file at all — they shuffle whitespace and pronounce the result fine. This one implements the TOML 1.0 specification — grammar, value rules and the semantic table/key rulebook — and formats only what it has fully verified, with the first violation reported at its exact line and column.

How to use this tool

  1. Paste the TOML, upload a .toml file, or drop one onto the panel — Cargo.toml, pyproject.toml, application configs all welcome.
  2. Press Format TOML: you get the canonical layout plus a count of keys and tables, so you can confirm the whole file was read. Validate only gives the verdict by itself.
  3. On an error, start from the position: the message gives line and column, and for redefinitions it also cites where the original was defined — the pair of lines is almost always the whole story.
  4. Use the two sample buttons to see the difference: the broken sample is the specification's own classic — dotted keys first, then a header for the same table.
  5. Copy or download the formatted file. Your input is not auto-saved between visits, by design.

What the parser enforces

Grammar: all four string forms with escape validation (including surrogate-range checks on \u escapes and the control-character bans), the full number grammar — underscores only between digits, no leading zeros, base prefixes, exponents, inf and nan — and RFC 3339 datetimes checked against the real calendar and clock, leap years included. Layout values: arrays may nest and span lines with comments inside; inline tables must stay on one line and take no trailing comma, as the spec demands. Semantics: no key or table is defined twice; dotted keys cannot burrow into values, static arrays or header-created tables; a super-table may be defined after its sub-tables (that one is legal, and allowed); a table may not be reopened once its array-of-tables has begun.

The formatter's side of the bargain

In exchange for that strictness, formatting changes nothing it does not have to. The order of keys and tables is the order you wrote. Scalars print byte-for-byte as authored — your 1_000_000, your 0xDEAD_BEEF, your carefully escaped strings. Comments stay where they belong, standalone above their line and trailing after it. Arrays render on one line when short, one item per line when they were multiline, contain comments, or grow past a readable width. What changes is only what “canonical” means here: spacing around =, dotted-key spacing, and array layout — so two valid files that mean the same thing come out looking the same, and diffs go back to showing meaning instead of whitespace.

Frequently asked questions

Does this tool really parse TOML, or does it just tidy the spacing?

It parses, fully, against the TOML 1.0 specification — every string form (basic, literal, and both multiline variants, with escape and control-character checks), the complete number grammar (hex/octal/binary, underscores, exponents, inf and nan), RFC 3339 datetimes validated against the real calendar (2023-02-29 is an error, 2024-02-29 is not), arrays, inline tables, dotted keys, tables and arrays of tables. Formatting re-prints from that parse; nothing that does not parse gets formatted, and the error tells you the line and column.

Which errors does the validator catch that others miss?

The semantic rules a spacing pass cannot see: a key defined twice (the error names where it was first defined); a table header for a table that dotted keys already created — the specification's own classic invalid example; a table extended after an array of tables began; dotted keys burrowing into a value or a static array; impossible dates and 24:00:00; leading-zero numbers and misplaced underscores; a trailing comma or a newline inside an inline table. These are the errors that pass eyeball review, because the file looks tidy while meaning something else — or nothing.

Will formatting change my file's meaning or ordering?

No. Formatting normalises the spacing around = and inside brackets, aligns dotted keys (a . b becomes a.b), and lays arrays out by a fixed rule — one line when short, one item per line when long, multiline in the source, or comment-bearing. It never reorders keys or tables (TOML order is behaviour: out-of-order table definitions are legal in specific ways the formatter respects, not shuffles), never rewrites a scalar's spelling — 1_000 stays 1_000, 0xDEAD stays 0xDEAD, 1979-05-27 07:32:00 keeps its space — and preserves comments, both standalone and trailing.

What is the strict dotted-key rule the result mentions?

The specification's examples establish that dotted keys create their intermediate tables as they go, and that once a table exists via a header, later dotted keys may add new keys inside it only under narrow conditions — the spec marks the natural-looking pattern (define keys under [fruit] with apple.color, then open [fruit.apple] as a header) as invalid outright. This formatter enforces the documented rule set conservatively: dotted keys may descend into tables they created themselves, and into fresh sub-tables of the current section — and anything murkier is refused with a positioned explanation rather than accepted on a guess. If your file relies on a borderline pattern, the error tells you exactly which line pair collided.

Cargo.toml, pyproject.toml, Hugo config — all fine here?

Yes — they are all TOML 1.0, and this tool exists precisely for them: the manifest you are about to commit, the config a deployment rejected at 2 a.m., the settings file you inherited. Nothing is uploaded (a pyproject.toml can carry index URLs and a Cargo.toml your dependency list; both stay in your browser), the input is never auto-saved (configuration does not belong in a browser draft), and a Validate-only pass gives you the verdict without producing a reformatted copy when all you need is certainty.

Related tools