Text & Data

TOML Format & Validate

Validate, lint, format and explore TOML 1.0, and convert it to JSON, with exact error locations. Runs in your browser.

Paste or type TOML, or choose File → Load sample.

Input

TOML options

Keyboard shortcuts

Ctrl/⌘ + Enter
Format (in the input)
← → on the tree divider
Resize the panes (Home/End for the limits; double-click resets)
Esc
Close a menu or overlay, then leave full screen
↓ on a menu
Open it; ↑ ↓ move through its items
← → in the menu bar
Move between menus

Where your data goes

Using this page Using the API, MCP or A2A
Where it runs In your browser. The TOML is parsed, checked and re-formatted by JavaScript on this page (the smol-toml parser plus this site's comment-preserving formatter); nothing you paste is sent anywhere. In a Cloudflare Pages Function at the Cloudflare data centre nearest the caller.
What leaves your device Nothing you enter. After the page and its scripts load, no request carries your input. The browser enforces this: the page's Content-Security-Policy sets connect-src 'none' and form-action 'none', which block fetch, XHR, WebSocket, EventSource, beacons and form posts.

The server receives the TOML text, processes it in memory inside the request, and returns the result. Your input is not stored or logged; only the per-call metadata row (operation, time, status, sizes) is recorded. The server makes no network requests. For confidential documents use the page, which does the same work in your browser and sends nothing.

The server receives the JSON text, processes it in memory inside the request, and returns the result. Your input is not stored or logged; only the per-call metadata row (operation, time, status, sizes) is recorded. The server makes no network requests. For confidential documents use the page, which does the same work in your browser and sends nothing.

Stored Nothing leaves the page. No cookies, analytics or third-party scripts; the browser keeps only your View → Inline config choice. Your inputs and results: never. What is stored is your client record (client ID, a SHA-256 hash of your secret, expiry, and the profile you registered with) and one metadata row per call: operation, time, transport, status, error code, duration, request and response sizes, and country.
Logged Nothing (no requests are made). Only the per-call metadata above, attributed to your client ID. Never parameters, bodies, results, or credentials. Cloudflare, as the host, also processes request metadata (IP address, full URL including the query string, headers) under its own policies, so put inputs in POST bodies.
Access Open to anyone. Requires a client ID and secret (how to get one). HTTPS only; TLS terminates at Cloudflare.

Details and how to verify this yourself: Security & privacy.

User guide

The studio works like a desktop window: a menu bar (File, Edit, View, Settings, Help) with the full-screen icon at the right of the same row. Settings → Options… opens the options in an overlay (or View → Inline config shows them in the card), and Help → Keyboard shortcuts… lists the keys.

  1. Paste or type TOML in the Input view, or choose File → Load sample to start from an example. The editor numbers its lines, and the document is checked as you type.
  2. Read the verdict. The Problems view (the button at the right of the status line, which shows the count) lists every finding with its line, column, rule and a short explanation. Errors make the document invalid; warnings and notes are about style. Click a finding to jump to that spot in the input.
  3. Choose Edit → Format (or press Ctrl+Enter). The Formatted view shows the canonical layout; Use as input copies it back into the editor so you can keep working on it.
  4. Open the Tree view to browse the data as it will be read (see the value mapping below). Every table and array can be collapsed, and each entry shows its type and its path.
  5. Copy or Download the result, or File → Clear input to start again. The full-screen icon at the right of the menu bar makes the studio fill the window; Esc returns.

Settings → Options… sets how the output looks: the indent for arrays broken over several lines, the line length after which a long array is broken (and longer lines are reported), and sort keys to order the keys in each table.

Formatting keeps your comments. Most TOML tools re-serialise the parsed data and lose every comment. This one rewrites the layout around them: comments on their own line, at the end of a line, and inside multi-line arrays all stay where they were, attached to the same key or element. Strings, numbers and dates are copied exactly as written, so 1_000, 0xDEAD_BEEF, 1.0 and a literal 'C:\path' survive unchanged.

What the checks catch. Beyond outright syntax errors, the usual TOML surprises are a key or [table] defined twice (often a [table] header that collides with a dotted key such as a.b = 1), an integer too large for 64 bits, and syntax from the TOML 1.1 draft that some parsers accept and others reject: line breaks or a trailing comma inside { inline tables }, the \e and \xHH escapes, and times without seconds (07:32). Mistakes from other formats get a hint: True (booleans are lowercase), null (TOML has none) and unquoted strings.

Converting. The same data can be turned into JSON, or JSON into TOML, through the API (see below). JSON has no comments, dates or 64-bit integers, so the conversion follows the value mapping in the specification.

Specification

Grammar. TOML 1.0.0. The parser is smol-toml, which also accepts some TOML 1.1 syntax; that syntax is reported as a warning (rule toml-1-1-syntax) so the document stays readable by TOML 1.0 parsers. A UTF-8 byte order mark is accepted with a warning. Only the first syntax error is reported, because after a syntax error the rest of the text has no reliable structure.

Positions. line and column are 1-based, and columns count Unicode code points, so an emoji counts as one character. offset is 0-based in UTF-16 code units (what a browser text box uses), so the editor can select the spot exactly. LF, CRLF and a lone CR each end a line.

Rules. Severity error makes the document invalid; warning and info do not. “Format fixes” means the formatted output no longer has the problem.

RuleSeverityWhat it checksFormat fixes
syntaxerrorThe text is TOML. The message names the problem and, for common mistakes, how to fix it.No
duplicate-keyserrorEach key and table is defined once: no repeated key in a table or inline table, no repeated [table] header, no [table] that reopens a table made by dotted keys, an inline table, a value or an [[array]], and no dotted key that extends a table defined elsewhere.No
integer-rangeerrorIntegers fit in 64 bits (−9,223,372,036,854,775,808 to 9,223,372,036,854,775,807), as TOML 1.0 requires. smol-toml would otherwise accept larger ones.No
toml-1-1-syntaxwarningNo TOML 1.1-only syntax: line breaks, comments or a trailing comma inside an inline table; \e and \xHH escapes; times and date-times without seconds.Yes, except comments inside an inline table, which stay (one entry per line) because removing them would lose them
inconsistent-indentationwarningKeys under the same table header (or at the top) all have the same indentation. Consistent indentation is not reported, but Format removes it.Yes
trailing-spaceswarningNo spaces or tabs at the end of a line. Spaces inside a multi-line string are part of its value and are not reported.Yes
final-newlinewarningThe text ends with exactly one line break.Yes
line-endingswarningAll line breaks use the same style.Yes, unless a multi-line string contains the other style (its value is kept)
byte-order-markwarningNo U+FEFF at the start.Yes
unnecessary-quotesinfoA quoted key (or part of a dotted key) that could be bare: only A–Z, a–z, 0–9, _ and -.Yes
table-orderinfoA table is not defined after its own sub-tables ([a.b] then [a]), and the sub-tables of one table are not split up by unrelated tables ([a.x], [b], [a.y]). Both are legal TOML but hard to read. Sub-tables of each [[array]] element are tracked per element.No (tables are never reordered)
long-inline-tableinfoAn inline table is at most 80 characters when written on one line; a [table] section reads better. Only the outermost of nested inline tables is reported.No
empty-tableinfoA [table] or [[array]] header has keys or sub-tables under it. x = {} is not reported.No
multiline-string-crlfinfoA multi-line string contains CRLF line breaks. They are part of the value here, but TOML lets parsers normalise them to LF, so other tools may read a different string.No
line-lengthinfoLines are at most the configured length (default 120 characters; 0 or none turns the check off).No

Formatting.

  • One key = value per line with one space either side of =, no indentation, and no trailing spaces. A comment at the end of a line follows one space.
  • Dotted keys are written without spaces around the dots; quotes that are not needed are removed.
  • Blank lines: none at the start or end, at most one in a row, none directly after a table header, and exactly one before each header. Comments directly above a header (no blank line between) stay with the header.
  • Arrays stay on one line unless they were already written over several lines, contain comments, or would make the line longer than the line length; then each element goes on its own line, indented by the indent setting per level, with a trailing comma. Blank lines between elements are kept (at most one).
  • Inline tables are written { a = 1, b = 2 } on one line (an empty one as {}).
  • TOML 1.1 syntax is rewritten to TOML 1.0: \e becomes \u001B, \xHH becomes \u00HH, 07:32 becomes 07:32:00.
  • The output ends with one line break. A document that uses only CRLF stays CRLF; anything else becomes LF. A byte order mark is removed.
  • Sort keys orders the keys of each table by UTF-16 code units, within each group of lines separated by blank lines; a comment directly above a key moves with it, and comments at the very top of the document stay there. Keys inside inline tables are sorted too. Tables themselves are never reordered: the order of [[array]] elements is data, and sub-tables belong to the element above them.
  • Strings (including multi-line strings, byte for byte), numbers and dates are copied as written.
  • The formatted document always parses to the same data as the input. This is checked on every format: if it ever did not, the input would be returned unchanged.

Value mapping to JSON (the Tree, value and TOML → JSON).

TOMLJSON
String, booleanThe same.
Table, inline tableObject, keys in document order.
Array, array of tablesArray.
Integer within ±(2^53 − 1)Number (0xff → 255).
Integer beyond ±(2^53 − 1)Decimal string, every digit kept: 9223372036854775807 → "9223372036854775807".
FloatNumber (1.0 → 1, -0.0 → 0); inf, -inf, nan → the strings "inf", "-inf", "nan".
Offset date-timeISO 8601 string with the offset as written and milliseconds: 1979-05-27 07:32:00-08:00 → "1979-05-27T07:32:00.000-08:00".
Local date-time, date, timeThe TOML text, with T and milliseconds: "1979-05-27T07:32:00.000", "1979-05-27", "07:32:00.000".

Fractions of a second beyond milliseconds are truncated (.999999 → .999). A key named __proto__ is an ordinary key.

JSON → TOML. The top level must be an object. Strings, booleans and numbers become key = value; numbers are copied as written, so 1.0 stays a float. Non-empty objects become [table] sections and non-empty arrays whose elements are all objects become [[array]] tables; objects inside other arrays become inline tables, and an empty object is {}. In each table the plain keys come first, then the sub-tables, so the key order can change. A null is an error naming its JSON Pointer (TOML has no null); so are an integer beyond 64 bits and a string with an unpaired surrogate. Duplicate JSON keys keep the last value. The output is formatted as above.

Statistics. tables counts tables below the root ([table] sections, dotted-key tables, inline tables and each [[array]] element); keys counts keys in all tables; arrays counts arrays, including arrays of tables; depth is 1 for a flat document and one more per level of table or array.

Not checked. Whether keys or values make sense for any particular program (Cargo, pyproject, Hugo and so on: use a schema for that); the order of keys; naming style (snake_case versus kebab-case); and whether a float or date can be represented exactly by the program that reads it.

API.

EndpointInput limitParameters
POST /api/toml/format50,000 charactersinput, indent (1–8, default 2), max_line_length (0–1000, default 120; 0 turns wrapping and line-length off), sort_keys
POST /api/convert/toml-to-json200,000 charactersinput, indent (0–8 spaces, default 2; 0 is minified)
POST /api/convert/json-to-toml200,000 charactersinput, indent, max_line_length, sort_keys

input can be a string field or a raw text/plain body. /api/toml/format returns valid, summary (counts of errors, warnings and infos), diagnostics, formatted, value and stats. An invalid document is a 200 response with valid: false and formatted and value set to null, not an HTTP error. The conversions return 422 unprocessable_input with the line and column (or JSON Pointer) when the input cannot be converted. The page has no size limit.

Lint rules

Rule Severity What it checks Fixed by Format
syntax error The text is TOML: every line is a key = value pair, a [table] or [[array]] header, a comment or blank. no
duplicate-keys error Each key and table is defined once: no repeated key in a table, no repeated [table] header, and no header or dotted key that redefines an existing value or inline table. no
integer-range error Integers fit in 64 bits (−9223372036854775808 to 9223372036854775807), as TOML 1.0 requires. no
toml-1-1-syntax warning No TOML 1.1 syntax that TOML 1.0 parsers reject: line breaks, comments or a trailing comma inside an inline table, \e and \xHH escapes, times without seconds. Format rewrites all of them except comments inside an inline table. yes
inconsistent-indentation warning Keys in the same table are indented the same way. yes
unnecessary-quotes info A quoted key that could be bare (only A–Z, a–z, 0–9, _ and -) is written bare. yes
table-order info Related tables are kept together: a table is not defined after its own sub-tables, and the sub-tables of one table are not split up by unrelated tables. no
long-inline-table info Inline tables are at most 80 characters on one line; longer ones read better as a [table] section. no
empty-table info A [table] or [[array]] header has keys or sub-tables under it. no
multiline-string-crlf info Multi-line strings use LF line breaks. CRLF inside one becomes part of the value here, but TOML lets parsers normalise it, so other tools may read LF. no
trailing-spaces warning No spaces or tabs at the end of a line. yes
final-newline warning The text ends with exactly one line break. yes
line-endings warning All line breaks use the same style (LF or CRLF). yes
byte-order-mark warning No byte-order mark (U+FEFF) at the start. yes
line-length info Lines are at most the configured length (default 120 characters). no

Errors make the document invalid. Warnings and information are style findings; the document still parses.

API & MCP

The same logic is available over HTTP and as MCP tools. Unlike this page, these run on the server: see where your data goes.