YAML Formatter_

A YAML formatter and validator that keeps your comments. Paste a document, pick an indent, and get it back re-indented and checked — with every # comment, every anchor and every alias exactly where you left them, because this works on the document tree rather than parsing to a plain object and serialising a stripped copy.

It also names the values that will be read differently by whatever consumes the file, which is how a manifest that validates cleanly still deploys the wrong thing.

toolkit.codes/yaml-formatter

Formatted
Nothing to format yet

How to use

  1. 01Paste the document, or upload a .yaml file. It is read in the page — nothing is sent anywhere.
  2. 02Pick an indent. Two spaces is the convention almost everywhere; four and eight are there for house styles that differ.
  3. 03If you need it, switch collection style or sort the keys. Both default to leaving your document alone, because a formatter whose default rewrites your file is one people run once.
  4. 04Read the panel underneath. This YAML formatter and validator reports the parse errors with a line and a column, and separately lists the values that a 1.1 reader will interpret differently — that is the checker part, and it is the part that catches problems a syntax check cannot.
  5. 05Copy the result or download it as a .yaml file. Comments, anchors and aliases come with it.

Values that do not mean what they look like

You wroteYAML 1.2 (this page)YAML 1.1 (Kubernetes, Ansible)How to force a string
country: NOthe string "NO"false — the Norway problemcountry: "NO"
enabled: yesthe string "yes"trueenabled: "yes"
debug: offthe string "off"falsedebug: "off"
answer: ythe string "y"trueanswer: "y"
start: 12:30the string "12:30"750 — read as base-60start: "12:30"
runtime: 1:00:00the string "1:00:00"3600runtime: "1:00:00"
mode: 0755755 — leading zero dropped, including by this formatter493 — read as octalmode: "0755", and quote it before formatting
version: 1.101.1 as a number1.1 as a numberversion: "1.10"

Every row here is unquoted. Quoting settles all of them, and it is the reason experienced YAML authors quote far more than looks necessary. The 0755 row is the one to watch: because YAML 1.2 resolves it to a plain number, formatting writes it back without the zero — this page included — so a 1.1 reader that saw 493 before will see 755 after. The panel under the editor names that on your own document, before you copy.

What each option does to one document

OptionSettingWhat comes out
Indent2 spaces (default)a:
  b: 1
Indent4 spacesa:
    b: 1
Collection styleKeep as written (default)list: [1, 2] stays inline; a block list stays block
Collection styleBlock everywherelist:
  - 1
  - 2
Collection styleFlow everywherelist: [ 1, 2 ] — compact, and awkward to diff
Key orderKeep order (default)b then a, as you wrote them
Key orderSort alphabeticallya then b, at every level, each key taking its comment with it. Sequences are never sorted — their order is data
Line width80 (default)A long plain scalar folds onto continuation lines
Line widthNo wrappingLong scalars stay on one line however long they get

The defaults change as little as possible: same order, same collection styles, two-space indent. Everything that restructures your document is opt-in.

Where YAML formatting goes wrong

Most formatters delete your comments

Parse to a plain object, serialise the object: the comments were never in the object, so they cannot come back. It is the default way to build one of these and it is silent — you notice when you paste the result back into the repository and the review shows forty deleted lines. Check any formatter with a two-line file that has a comment in it before you trust it with a real one.

Tabs are illegal, not merely discouraged

YAML forbids the tab character for indentation outright, which surprises people whose editor inserts tabs everywhere else. The parse fails rather than misreading, so this one is at least loud — but the message from most libraries points at the line after the tab, not the tab. This page names the line and says what to replace it with.

A copy-paste that shifts indentation changes meaning

In a language where whitespace is structure, moving a block two spaces right reparents it. The document usually stays valid, so nothing complains: your setting is now nested under the wrong key and takes effect as a default instead. Format before you diff, so the diff shows real changes rather than whitespace.

Duplicate keys are resolved silently

Write the same key twice in one mapping and the last one wins with no complaint from most tooling. It happens most often after a merge conflict is resolved badly, and the earlier value simply disappears. This page formats the document anyway — withholding output would not help — but it warns you and names the line.

Anchors get expanded, or they do not

An anchor and its alias are a reference: define a block once, refer to it in three places. Some tools resolve them on the way through, so your compact document comes back with the block copied out three times and the reference gone. That is a legitimate operation but it is not formatting, and it should be your choice. Here both are preserved as written, and the panel tells you how many the document has.

Kubernetes secrets pasted into a server-side formatter

The YAML people paste into web tools skews heavily toward manifests, CI configuration and inventories — which is to say deploy tokens, registry credentials and Secret objects whose base64 is encoding, not encryption. Several popular formatters offer fetch-from-URL, which is necessarily server-side, and save-and-share links, which publish. Check where a tool runs before pasting anything from a cluster into it.

When you would reach for it

Tidying a manifest before review

A Kubernetes deployment that has been edited by four people with three editors. Re-indent it so the diff shows the change rather than the whitespace.

Before
spec:
    replicas: 3
    template:
      metadata:
            labels:
                app: api
After (indent 2)
spec:
  replicas: 3
  template:
    metadata:
      labels:
        app: api

Finding the tab

A CI pipeline fails with a parse error that names a line where nothing looks wrong. The tab is on the line above.

Input
jobs:
	- build
Result
Line 2: YAML forbids tabs for
indentation. Replace the tab with
spaces.

Catching a value before it ships

A config that validates everywhere and still behaves wrongly, because the consumer reads 1.1 and you wrote an unquoted two-letter country code.

Input
region: NO
retries: 0755
Reported
NO  → "NO" here, false under 1.1
0755 → 755 here, 493 under 1.1

Working with YAML more comfortably

  • Quote more than feels necessary. Version strings, country codes, times, anything with a leading zero, and any bare word from the yes/no/on/off family. It costs two characters and removes an entire class of bug.
  • Format before committing rather than before reviewing. A whitespace-only reformat mixed into a behaviour change makes the diff unreadable for whoever has to approve it.
  • Multi-document streams are normal — several resources separated by --- in one file. Every document here is formatted and emitted; a tool that returns only the first has quietly eaten your Service.
  • Converting rather than tidying is a different operation with a real cost: JSON has no comments, no anchors and no multi-document streams, so anything crossing that boundary loses them. The YAML-to-JSON and JSON-to-YAML converters are queued and will appear in the tool registry as they go live.
  • For JSON that arrived here by accident: JSON is valid YAML, so it formats fine, but the JSON formatter will validate it more usefully.

Technical details

Engine
The yaml package (ISC), pinned in the lockfile and loaded only on this page. Chosen over js-yaml because it parses to a document tree that retains comments, anchors and node style rather than to a plain value
Version
YAML 1.2, core schema. Values that a YAML 1.1 reader resolves differently are listed rather than silently rewritten
Preserved
Comments in every position, anchors, aliases, merge keys and multi-document streams. Asserted by byte-exact fixture tests plus an idempotence law and a semantic-equivalence law on every build
Errors
Line and column with the expectation spelled out. Tabs, bad indentation and duplicate keys get messages written for this tool rather than passed through from the library
File handling
Uploads are read inside the page with the browser File API and are never transmitted; Download writes out what is already in the tab.
Limits
Input is refused above 1 MB, checked before any parsing — a tenth of what the JSON tools allow, because a YAML document tree carries layout for every node and costs far more to build than plain text. Measured: 1 MB takes about four seconds. The output pane stops drawing past 300,000 characters. Copy and Download are unaffected and always carry the complete result.
Network
None from tool code. A test sweep calls every function this page uses with fetch and XMLHttpRequest replaced by stubs that throw, so a stray request fails the build instead of shipping. Disconnect from the network and the page still works.

Frequently asked questions

Will this delete my comments?

No, and that is the main reason this page exists. It parses to a document tree that holds comments, anchors and node styles, then writes back from that tree — so a comment above a key stays above that key and a trailing comment stays on its line. Fixture tests compare the output byte-for-byte on every build, because a promise like this is worth nothing unless something checks it.

Why is my unquoted "no" being treated as a string?

Because this page targets YAML 1.2, where it is one. Under YAML 1.1 it is the boolean false — the Norway problem — and 1.1 is what Kubernetes and Ansible use. Neither reading is a bug; they are different specifications. The panel under the editor lists every value this affects in your document, so you can quote them before something downstream disagrees with you.

What happens to anchors and aliases?

They are kept exactly as written. An anchor stays an anchor and an alias stays a reference, rather than being expanded into duplicated copies of the block. The panel reports how many of each your document contains. If you want them expanded, that is a conversion rather than a formatting operation, and converting to JSON does it as a side effect because JSON has no way to express a reference.

Does it handle multiple documents in one file?

Yes — every document in a --- separated stream is parsed, formatted and emitted, and the count is shown. This is worth checking in any tool you use, because a formatter that returns only the first document will silently drop the rest of a manifest, and the result still looks like valid YAML.

Is it safe to paste a Kubernetes Secret in here?

Safer than most places, and you should still think about it — base64 in a Secret is encoding, not encryption, so anything that receives it receives the credential. The work is JavaScript running in this tab. Every function it calls is covered by a test that stubs fetch and XMLHttpRequest to throw, so a request that slipped in would break the build rather than reach a server — and you can confirm it for yourself by disconnecting and carrying on.

Does formatting ever change what my file means?

It must not, and that is enforced rather than promised: a test parses the input and the output separately and compares the resulting data structures, and the build fails if they differ anywhere. A second test formats the output again and requires byte-identical results, which catches the class of bug where a formatter never settles and every run produces a new diff.

Can I use this on a docker-compose or GitHub Actions file?

Yes — both are ordinary YAML, and both make heavy use of the features that get mangled elsewhere. Compose files use anchors and merge keys to share service definitions, and Actions workflows are full of comments explaining why a step is pinned to a particular SHA. Those are exactly the things preserved here.

Why is the size limit so much lower than the JSON tools?

Because keeping the comments costs. A plain parse throws away layout as it goes; this one retains position, style and comment attachment for every node, and the cost grows faster than linearly — a megabyte takes around four seconds in a browser tab, and 1.6 MB takes over eight. The cap is set from that measurement rather than by analogy with the other tools. For a file that size, run yq locally.

UTF-8
Ready
100% LOCAL

What a YAML formatter has to get right

A YAML formatter reads a document, works out its structure, and writes it back with consistent indentation, consistent quoting and a predictable layout. For most formats that is a cosmetic operation. For YAML it is not, and the reason is that indentation is the structure. Move a line two spaces to the right in JSON and nothing happens; do it in YAML and that line now belongs to a different parent. So a YAML formatter is doing something with real consequences, and the standard by which to judge one is not how pretty the output is but how much of your file survives the trip.

The comment problem, which is the whole story

Here is how nearly every online YAML formatter is built. It calls a library to parse your document into a plain data structure — a map of strings and numbers and lists — and then asks the same library to write that structure back out. This is two lines of code and it works, in the sense that valid YAML goes in and valid YAML comes out.

It also deletes every comment in the file. Not because anyone chose that: a plain data structure has nowhere to put # this timeout is 300 because the upstream gateway gives up at 305, so by the time the writer runs, that sentence no longer exists. And in a configuration file the comments are frequently the only surviving record of why anything is set the way it is. Of the formatters surveyed for this page, not one states what it does with them.

This page does not work that way. It parses to a document tree that retains comments, anchors, aliases and the original style of every node, and writes back out from that tree. A comment above a key stays above that key, a trailing comment stays on its line, and the anchor you defined is still an anchor rather than three duplicated copies of the block it pointed at. That behaviour is covered by fixture tests that compare byte-for-byte, because a claim like this is worthless unless something checks it on every build.

Which YAML is this, exactly

There are two YAML specifications in daily use, and they disagree about what your file says. Under YAML 1.1 the bare word no is the boolean false — the famous case being a country list where Norway's NO quietly became false. YAML 1.2 fixed this: no is the string "no". This page targets 1.2 with the core schema, because it is the current specification and because deliberately choosing the version with the data-corruption bug would be hard to defend.

The catch is that 1.2 is often not what reads your file. Kubernetes, Ansible and anything built on Go's yaml.v2 resolve values by 1.1 rules. So your document can validate perfectly here and still be misunderstood by the thing you feed it to. That is why the panel under the editor lists every unquoted value whose meaning changes between the two versions, with both readings side by side and the fix. It is the one thing this page does that none of the alternatives do, and it exists because "your YAML is valid" is not the same claim as "your YAML means what you think".

What formatting changes, and what it must not

The useful distinction is between layout and meaning. Layout is indentation, where lines break, whether a list is written inline as [1, 2] or expanded onto its own lines, and the order sibling keys appear in. Meaning is the data: which keys exist, what values they hold, how they nest. A formatter is allowed to change the first and must never change the second, and the difference is not always obvious from looking at the output.

The way this page holds itself to that is a test that parses the input and the output independently and compares the resulting data structures. If they differ by so much as a single value, the build fails. There is a second test alongside it — formatting the output again must produce exactly the same bytes — which catches a subtler class of bug where a formatter keeps nudging its own work and every run of it produces another diff.

One thing worth knowing is that sorting keys is a layout change in YAML but not always a harmless one in context. A Kubernetes manifest conventionally opens with apiVersion, kind, then metadata; sorting alphabetically puts apiVersion first by luck and spec before metadata by rule, which is valid, deploys identically, and will look wrong to every reviewer. That is why sorting is off by default here rather than on.

The validator half of the job

Almost every search for a YAML formatter is really a search for a formatter and validator at once, and the reason is that people arrive here holding a file that something has already rejected. So the errors matter as much as the output. A parse failure here gives you a line, a column and a sentence about what went wrong, rather than the library’s own phrasing — because a message like "implicit keys need to be on a single line" is precise and tells you nothing at all about the tab character you pasted three lines earlier.

It is worth being clear about what a validator of this kind can and cannot tell you. It can say the document is well-formed YAML and where it stops being so. It cannot say whether your Deployment has the fields Kubernetes requires, whether your workflow references a job that exists, or whether the value you wrote is the value you meant — those are schema questions and they need something that knows the schema. What this page adds beyond well-formedness is the version check, which sits in the gap between the two: your file is syntactically fine and the value is still going to surprise you.

Several documents in one file

A YAML file can hold a stream of documents separated by ---, and in Kubernetes that is the normal case: a Deployment, its Service and its ConfigMap arriving as one file that kubectl apply reads end to end. This matters when choosing a formatter, because the naive implementation calls a parse function that returns the first document and quietly discards the rest. The output is still valid YAML and still looks like your file, so nothing announces the loss — you find out when the Service is missing from the cluster.

Every document in the stream is parsed and emitted here, the separators are put back, and the count is shown in the status line under the panes so you can check it against what you pasted. If you paste three documents and it says one, something is wrong and you can see that it is wrong.

The command line, Python, and your editor

If you want a YAML formatter CLI for a repository rather than a one-off paste, yq -P re-indents in place and prettier --write '**/*.yaml' covers a whole tree with the formatting most teams already use for everything else. For a YAML formatter Python route, the important detail is which library: PyYAML discards comments exactly as described above, while ruamel.yaml was written specifically to round-trip them and is what you want for anything that edits a config file in place. And for a YAML formatter neovim setup, point conform.nvim at yamlfmt or prettier and let it run on save. All three of those keep the file on your machine, which for anything with credentials in it is the right answer regardless of what any web tool promises.