TOML to YAML Converter
Convert TOML to YAML or YAML to TOML with datetimes, nulls, anchors and comments all accounted for — entirely on this device.
TOML date-times can stay unquoted YAML timestamps, or be quoted so no loader re-parses them. Minimal quotes only where YAML requires it; the other two quote every string. Short scalar-only arrays and tables can render inline as [a, b] instead of a block. Where long scalars fold. No fold keeps every value on one line.
Drop a .toml or .yaml file, or open one — the file never leaves this device.
Press ? for shortcuts
Do it offline:$ python3 -c "import tomllib,yaml,sys;yaml.safe_dump(tomllib.load(open('config.toml','rb')),sys.stdout)"
How to use it
- Paste TOML, drop a file, or pick one — nothing leaves the browser, and the badge names the direction it read.
- Set the YAML you want out: indent width, quoting, block or short flow collections, wrap column, and bare or quoted date-times.
- Scan the counts beneath the result — dropped comments, quoted times, millisecond precision — each measured from this run.
- Copy it, save it as .yaml, or press Share to fold the panes and options into the link.
Drop a Cargo.toml, pyproject.toml or netlify.toml here and read it back as YAML — typed date-times stay date-times, 64-bit integers keep every digit, and each table header turns into indentation. Whatever cannot survive the trip is counted under the result rather than left for you to discover later. Paste YAML instead and the badge flips, up to 20 MB, on this device.
How it works
Reading TOML produces typed values, and those values — not their text — are what the YAML writer receives. That is why 1979-05-27T07:32:00Z lands as a bare timestamp rather than a quoted string, and why an integer past 2^53 is printed digit for digit instead of rounding through a float.
Structure moves the same way: [tool.poetry] and dotted keys collapse into ordinary nesting, and every [[member]] block becomes one item of a sequence. Nothing is renamed and no key invented; the only additions are the quotes YAML needs to keep a value meaning what it meant.
Examples
# build matrix
[package]
name = "ithomia"
edition = "2021"
rust-version = "1.79"
[[workspace.members]]
path = "crates/cli"
[[workspace.members]]
path = "crates/worker"
[profile.release]
lto = true
codegen-units = 1
package:
name: ithomia
edition: "2021"
rust-version: "1.79"
workspace:
members:
- path: crates/cli
- path: crates/worker
profile:
release:
lto: true
codegen-units: 1
Two [[workspace.members]] blocks become two sequence items, and [profile.release] becomes two levels of indentation. One line is reported: 1 comment dropped — the TOML parser does not keep comments.
snowflake = 9223372036854775807
ratio = nan
ceiling = inf
built = 1979-05-27T07:32:00Z
window = 07:32:00
[flags]
snowflake: 9223372036854775807
ratio: .nan
ceiling: .inf
built: 1979-05-27T07:32:00.000Z
window: "07:32:00"
flags: {}
The 64-bit ceiling, nan, inf and the empty table survive. Two values change, both counted: 1 local time quoted — YAML has no time-only type, and an unquoted 07:32:00.000 reads back as the number 27120.0; built gains .000 — millisecond precision.
cache:
dir: .cache
ttl: null
The value at line 3, column 8 is null — TOML has no null value; remove the key or switch null handling to "omit".Edge case, running the other way: this one refuses, because there is no TOML spelling for an unset value. Switch null handling to omit and the result is [cache] with dir alone, plus a count naming cache.ttl.
Every example on this page is executed against the same engine that powers the tool, on every build.
Gotchas worth knowing
Headers become indentation; doubled ones become a list
[a.b] and a dotted a.b.c both open the same nesting on the way out. A doubled header is the one that changes shape: each [[bin]] block becomes one item under a single bin key.
Three of the four date-time kinds cross unquoted
An offset date-time, a local date-time and a plain date all print bare and reload as dates. A time with no date goes out in quotes, counted, because bare it would be read in base 60.
Fractional seconds are printed to the millisecond
07:32:00 comes back as 07:32:00.000, and a stamp carrying microseconds is rounded there. A count says so on every run that touches a date-time.
Comments are counted on the way past, never carried
The parser reports how many it saw and drops them all, in both directions. A comment-preserving round trip is not something these serializers can do.
Multi-line strings arrive as block scalars
A triple-quoted TOML value is emitted with the pipe form rather than one long escaped line. Wrap column controls only where plain text folds; block scalars are left alone.
Going back, four things stop the conversion
A null or empty value, a mapping key that is not a string, a root that is a list or a scalar, and a stream of several documents. Each refusal points at the line, and two of the four have an option that converts anyway.
Common errors
Incomplete key-value: cannot find end of key at line 1, column 2 — probable cause: something opened here was never finished — look for a missing `=`, `]`, `}` or closing quote.- An unclosed [table header, a bare key with no = after it, or a string missing its final quote all land here. The column is where reading stopped — usually one character past what you left open.
The value at line 2, column 8 is null — TOML has no null value; remove the key or switch null handling to "omit".- Manifests and chart values are full of keys left empty on purpose, and none of them can be written in TOML. Delete the key, give it a real value, or let the omit option drop it and say how many went.
The mapping key at line 2, column 3 is a bigint, not a string — TOML keys are always strings; quote the key to convert.- Port maps and status tables give YAML numeric keys without anyone noticing. TOML keys are text only: quote the key upstream, or switch key handling to stringify, which rewrites it and counts the rewrite.
The input holds 3 YAML documents (second document at line 2, column 1) — a TOML file carries a single document; set multi-document handling to "first" to convert document 1.- One manifest often holds a Service, a Deployment and an Ingress separated by ---, and TOML has no such separator. Split the file, or take document one and read the count of what was left behind.
FAQ
Can this page also read YAML and give me TOML?
Yes — the badge switches by itself when you paste, and s pins the direction by hand. Both directions run in the same panes, so there is no second address to remember.
Will the comments in my pyproject.toml come through?
No. They are counted and dropped — a property of the serializers, not a setting left off. Keep the original file as the source of truth and treat the YAML as generated output.
Why did my timestamp gain .000 on the end?
Date-times are carried as instants and printed with millisecond precision, so a stamp written without a fraction prints one. It parses back to the same moment; for the original text, set date-times to quoted.
Keyboard shortcuts
- ⌘/Ctrl + Enter
- Convert now; inputs above 2 MB wait for it.
- ⌘/Ctrl + S
- Save the result as .yaml or .toml.
- ⌘/Ctrl + C
- Copy the result when no text is selected.
- ⌘/Ctrl + Shift + C
- Copy the result even when text is selected.
- s
- Swap the direction; one undo restores it.
- t
- Move to the next color theme.
- ? or ⌘/Ctrl + /
- Open this shortcut list.
- Esc
- Dismiss the top overlay; panes keep their size.