T tomlkit·org
Inspect Formatter Validator Convert TOMLJSON JSONTOML TOMLYAML YAMLTOML INITOML TOMLINI .envTOML TOML.env TOMLTS Transform Sort keys Flatten Minify Compare Diff Merge

TOML Minifier

updated 8 June 2026

Re-emit a TOML document in its most compact form. Tables become inline where possible, blank lines disappear, arrays tighten. The parsed value tree is unchanged.

comments are dropped on re-emit

What this tool does

It parses your TOML into a value tree and re-emits it in the smallest valid form. Under the hood this is the same parser and writer the formatter uses, but with the most aggressive compaction settings locked in: no blank lines between sections, arrays written tight ([1,2,3] with no spaces after commas), and every leaf table collapsed to an inline table ({ … }). The result is byte-for-byte deterministic and parses back to the exact same data.

The intent it closes: "I need this TOML as small as possible without it stopping being valid TOML." The real destinations are an HTTP header or query field with a length cap, a single environment variable, a database column, or a snapshot-test fixture where a canonical compact form makes byte comparison reliable across editors.

Two things to know up front. Comments are dropped — re-emission goes through the parsed tree, which carries no comments. And this is the formatter with the dials pinned: if you want to choose spacing, sorting, or quote style yourself, use the formatter instead. The minifier deliberately gives you one button.

When you'd reach for it

  • Fit a config under a length limit. Inlining leaf tables and dropping every blank line is the fastest way to squeeze a document into an HTTP header, a URL field, or a short text column.
  • Pack a config into one environment variable. Inline tables and tight arrays mean fewer line breaks to escape when you stuff TOML into a single FOO_CONFIG=… value.
  • Get a canonical compact fixture for snapshot tests. The output is deterministic for a given value tree, so byte-level comparison stays stable no matter which editor produced the source.
  • Strip layout noise before a size measurement. When you want to compare the actual data weight of two configs, minifying first removes the whitespace and comment differences.
  • Confirm a file is valid while you compact it. Minifying parses first, so a malformed file never produces output — a clean minify is also a syntax-valid file.
  • One-button compaction. When you don't want to fiddle with the formatter's seven controls, this locks in the smallest-output settings and runs.

How minifying works

One click of Minify runs three stages. There is nothing to configure that changes the result — the compaction settings are forced in code.

1. Parse the input

The full TOML 1.0 grammar is parsed into a value tree: dotted keys collapse into nested tables, dates become date-shaped values, integers keep their hex/octal/binary intent. If parsing fails, the status bar shows the error and no output is written — the parser is shared with the validator and formatter.

2. Lock in the compaction settings

Before emitting, the minifier overrides the writer with a fixed set: blankBetween off (no blank line between sections), compactArrays on (no spaces inside arrays), inlineMax 999 (inline a leaf table no matter how many keys it has), and inlineMode set to auto. These are pinned in the runner, not read from the page — see the layout section below for what each one does.

3. Emit the smallest tree-equivalent TOML

The writer walks the tree once. Scalars are written first, then any table that is a leaf (no nested tables of its own) is folded into an inline { … } table; tables that still contain sub-tables stay as [section] headers because TOML has no way to inline them losslessly. Arrays-of-tables ([[…]]) likewise stay as block [[…]] blocks — there is no shorter valid form. Key order is preserved from your input; the minifier never re-sorts.

What minify does to the layout

This tool has no options that change the output — the Tables control on the widget exists for parity with the formatter, but the runner forces auto mode regardless. Here is exactly what gets compacted, and what stays as-is because TOML can't express it any shorter.

Blank lines between sections

Removed. The formatter writes a blank line before each [section] for readability; the minifier writes none, so sections sit flush against each other.

Spaces inside arrays

Removed. [ 8001, 8002 ] becomes [8001,8002] — no space after the bracket, no space after each comma. Arrays always stay on one line; there is no wrapping.

Leaf tables → inline tables

A table that contains only scalars and arrays (no nested tables) is folded into an inline { … } table on the parent's line. This is the big size win on configs with many small sections.

What is left alone

A table that still holds a sub-table can't be inlined without breaking the spec, so it stays a [section] header. Arrays-of-tables stay as repeated [[name]] blocks. Spacing around = is one space each side — TOML requires a separator, so this isn't a place to save bytes. String quoting is left in basic form; quotes aren't optional in TOML.

Output

  • Validity: always valid TOML 1.0 that parses back to the same value tree as your input.
  • Encoding: UTF-8, no BOM.
  • Line endings: LF (\n). A single trailing newline is appended when the document is non-empty.
  • Blank lines: none — sections run flush.
  • Arrays: compact, one line, no inner spaces ([1,2,3]).
  • Inline tables: leaf tables are written { a = 1, b = 2 }. Note the spaces inside the braces are required by the spec and are not stripped — only arrays go fully tight.
  • Comments: not emitted. The parser doesn't carry them through.
  • Download: minified.toml, content type text/plain;charset=utf-8.

Example

Input:

title = "Example"

[owner]
name = "Tom"

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

Output:

title = "Example"
owner = { name = "Tom" }
database = { enabled = true, ports = [8001,8001,8002], connection_max = 5000 }

Both [owner] and [database] are leaf tables, so they collapse to inline tables on one line each; the blank lines vanish and the ports array loses its inner spaces. Note the inline-table braces keep their inner spaces — that's a spec requirement, not an oversight. The duplicate 8001 survives; minifying never deduplicates values.

Recipes by intent

Pack a config into one environment variable

Minify, then copy. Leaf sections become inline tables and arrays go tight, so the whole config drops to a handful of lines you can paste into a single VAR=… value with minimal escaping.

Fit TOML inside a header or short field

Minify and check the output length against your cap. If a deeply nested config still has block [a.b] headers it can't shed, that's the spec's floor — consider TOML → JSON (min) if the consumer accepts JSON, which can inline everything.

Produce a stable snapshot fixture

Minify both the expected and actual TOML before comparing. Because the output is deterministic for a given value tree, the comparison ignores editor whitespace, comment, and ordering differences and only flags real data changes.

Measure data weight, not formatting

Minify two configs and compare byte counts. With blank lines, comments, and array spacing stripped uniformly, the difference reflects actual content rather than layout style.

Limits and performance

  • In-memory. The input string, the parsed tree, and the output all sit in memory at once. Config-sized files are instant; multi-megabyte TOML can take a second or two to parse and emit.
  • Comments are not preserved. Parse → tree → emit drops them. Keep the source file as the source of truth and minify a copy.
  • There is a hard floor. Tables containing sub-tables and arrays-of-tables can't be inlined, and = separators and string quotes are mandatory — so the smallest valid TOML is rarely as small as minified JSON.
  • The textarea is the slow bit on huge files. Past roughly 50 MB of output, painting the result back into the right pane lags even after the minify completes — use Download .toml rather than Copy.

Errors and how to fix them

"Parse error" / the status bar goes red on click

The input isn't valid TOML 1.0. Common causes: unclosed quotes, an array that opens with [ but never closes, a missing = between key and value, or a duplicate key in the same table. Run the TOML Validator — it points at the exact line and column.

Output is empty

A TOML document's root must be a table. An empty input, or a fragment that isn't a top-level table, produces no output — the minifier refuses to emit anything that wouldn't be valid TOML.

My # comments disappeared

Expected. The parser doesn't carry comments into the value tree, so the emitter has nothing to write. Keep your original file; minify a copy for shipping or storage.

It barely got smaller

Your config is probably deeply nested. Tables that contain sub-tables can't be inlined without breaking the spec, so they stay as [section] headers — minifying only removes blank lines and array spacing for those. If the consumer accepts JSON, minified JSON can inline everything and will be smaller.

The arrays in my output still have spaces

The spaces you're seeing are inside inline-table braces ({ a = 1 }), which the spec requires. Real arrays are fully tightened ([1,2,3]). If a literal array still shows spaces, you're looking at the input pane, not the output.

FAQ

Is the output still valid TOML 1.0?

Yes. Inline tables and inline arrays are standard TOML syntax. Re-parsing the output produces the same value tree as the input — minifying never changes meaning, only layout.

How is this different from the formatter?

This is the formatter with its compaction dials pinned to the smallest-output settings and the controls hidden. The formatter lets you choose spacing, sorting, quote style, inline thresholds, and array wrapping; the minifier makes those choices for you and gives you one button. Reach for the formatter when you want control, this when you want small.

Why does the Tables dropdown not change anything?

The runner forces inline mode to auto regardless of that control, so it has no effect here. It's left on the widget for visual parity with the formatter. If you genuinely want always block or always inline behaviour, use the formatter, where the control is live.

Will it preserve my comments?

No. A pure parse-and-re-emit flow has nothing to carry comments through. If comments matter, keep your source file and minify a copy, or hand-edit with a comment-preserving library in your own pipeline.

Is my data uploaded?

Never. The parser and emitter run entirely in your browser. You can disconnect from the network before clicking Minify and it still works — safe for files with secrets or API keys.