YAML Diff: Compare Two YAML Files Online
Paste two YAML documents and get a precise side-by-side diff. Built for Kubernetes manifests, GitHub Actions workflows, Helm values, and docker-compose files.
What is the YAML diff tool?
A free, in-browser tool for comparing two YAML documents. Paste an old version on the left, the new one on the right, and the differences highlight character by character. The text never leaves your browser, which matters when you are diffing manifests that contain secret refs or internal hostnames.
The diff is character-level, the same engine our text diff tool uses. YAML mode in the editor handles syntax highlighting per the YAML 1.2.2 specification, so your block scalars, anchors, and flow collections all colour correctly.
If you have ever stared at a 400-line Helm values.yaml diff in a pull request and tried to find the one indentation slip that broke the chart, this is the tool that finds it in seconds. It is also useful when copy-pasting between Slack and your editor mangles tabs, which YAML refuses to accept.
How the YAML diff actually works
The diff runs at the character level, then a semantic cleanup pass groups the highlights into meaningful chunks instead of scattered single characters. Insertions show in green on the right pane, deletions in red on the left, and the line counts in each header tell you how many distinct edits the diff found.
YAML has parsing rules that bite people who treat it like a forgiving format. Indentation is structural per the YAML 1.2.2 spec, so a single misplaced space changes the document tree. Tabs are forbidden as indentation, and the parser will reject them outright. Implicit typing turns the unquoted token NO into the boolean false in YAML 1.1, which is the famous Norway problem: country code lists silently lose Norway. YAML 1.2 narrowed the rules so only true, false, null and numeric forms convert without quotes, but plenty of tools still parse 1.1.
If you have already converted your YAML to JSON for a downstream consumer, our JSON diff tool handles structural concerns like key ordering and canonicalisation. JSON is a strict subset of YAML 1.2, so any valid JSON document is also valid YAML — that compatibility is documented in the spec and is why js-yaml and libyaml can both round-trip JSON without surprises.
How to compare YAML in three steps
Two text panes, one diff. No signup, no upload, no server round-trip.
- 1
Paste or upload your YAML
Paste the old YAML on the left, the new one on the right. Or click Upload on either side to load a .yaml or .yml file directly. The Sample button fills both panes with a small Kubernetes Deployment so you can see the tool in action first.
- 2
Check the indentation matches your intent
YAML uses spaces only for indentation, never tabs. If you pasted from a chat client or a terminal that converted spaces into tabs, the parser will reject the file. The editor highlights tabs and trailing whitespace so you can spot them before they cause a deploy to fail.
- 3
Read the diff
Deletions appear in red on the left, insertions in green on the right. Both panes scroll in lockstep so you can follow long manifests without losing your place. The change counts in each header summarise how many distinct edits the diff found.
When YAML diff is the right tool
Comparing Kubernetes Deployment specs across staging and prod
Run kubectl get deployment web -o yaml in both clusters and diff the output. Often prod still has replicas: 2 and an old image tag because a sprint-end rollout never reached it, and a text diff is the fastest way to confirm that before you re-run kubectl apply. The Kubernetes object model is YAML through and through, so this is the everyday case.
Diffing GitHub Actions workflow YAML
When a workflow stops triggering after a branch rename or a job suddenly takes 8 minutes longer, diff .github/workflows/ci.yml against the previous green commit. The culprit is usually a changed on: filter, a removed cache: key in actions/setup-node, or a matrix entry that quietly went from node-version: "18" (string) to node-version: 18 (number) and tripped the type checker.
Reviewing docker-compose env changes before a deploy
Diff docker-compose.yml against the version in main to verify which environment: entries you actually changed. People paste a list of new env vars and forget that one of them was already set under a different service, so the override silently flips a flag elsewhere. The diff makes it obvious.
Tracking Helm chart values.yaml across releases
When upgrading a chart from 1.8.0 to 2.0.0, diff your values.yaml against the new defaults the maintainer published. Helm merges values key by key, so a renamed top-level key (image.tag moving under image.repository) silently falls back to the chart default. The diff surfaces the rename before helm upgrade rolls out a regression.
OpenAPI and Swagger YAML schema review
A 3,000-line openapi.yaml diff is unreadable when a code generator reorders paths alphabetically. Compare versions side by side and the actual change surfaces: a required field added to a request schema, or a response whose type quietly switched from string to integer. Easier than digging through a generated SDK to find why the build broke.
Ansible playbook diffs across environments
When a playbook works in dev and fails in prod, diff the inventory or the role defaults/main.yml between the two. A common cause is a hostvar that was never copied across, or a become: yes that was set on the role in dev but on a single task in prod. The diff finds it in seconds.
YAML quick reference
A short cheat sheet for the parsing edge cases this tool surfaces most often. All grounded in the YAML specification and real parser behaviour.
| Topic | What this tool does |
|---|
| Indentation | Spaces only, and the count is structural. Two and four spaces are both common; pick one per file and stay with it. The YAML overview on Wikipedia has a good summary if you want the history. |
|---|
| Tabs | Forbidden as indentation per the spec. Allowed inside scalar values. If your editor inserts a tab on Enter, configure it to use spaces for .yaml and .yml files. |
|---|
| Anchors and aliases | &name defines an anchor; *name references it. Useful for repeating large blocks like container env vars or default service config without copy-paste. |
|---|
| Merge keys | <<: *base merges the referenced mapping into the current one. A YAML 1.1 feature. Most parsers including libyaml still accept it; the YAML 1.2 spec dropped it. |
|---|
| Multi-document files | Three dashes (---) separate documents in a single stream. Useful for piping multiple Kubernetes objects through one kubectl apply -f. ... ends a document. |
|---|
| Block scalars | | preserves newlines (literal); > folds them into spaces. Modifiers - and + control trailing newlines. Use | for shell scripts, > for long human prose. |
|---|
| The Norway problem | Unquoted NO, YES, ON, OFF become booleans in YAML 1.1. Quote them, or use a 1.2 parser. See the YAML type definitions for which strings convert. |
|---|
| Encoding | UTF-8 is required by the YAML 1.2 spec. UTF-16 is permitted with a BOM. Tools in practice expect UTF-8 without a BOM, so save your files that way to avoid surprises. |
|---|
YAML diff: frequently asked questions
Does YAML's whitespace-sensitivity help or hurt the diff?
YAML is whitespace-sensitive, so a regular text diff is already useful: any indentation change is a structural change, and the diff catches it. The difference is presentation. The YAML mode highlights anchors, tags, block scalars, and flow collections with syntax colours, so you can tell at a glance whether a change is to a key, a string value, or a list item. The underlying diff algorithm is the same as our text diff tool.
Why is YAML so picky about indentation and spaces?
Because indentation is the only thing telling the parser which keys belong to which mapping. The YAML 1.2.2 spec defines the indentation level of a node by the count of leading spaces, and forbids tabs as indentation. A single extra space promotes a key into a sub-mapping. That strictness is the price for a format that does not need braces or commas, and it is why you see indentation bugs more often in YAML than in JSON.
What is the Norway problem?
YAML 1.1 implicit typing turns the unquoted token NO into the boolean false. So a list of country codes that includes NO for Norway silently becomes a list with one entry replaced by false. The same applies to YES, ON, OFF, and similar. StrictYAML documents this in detail. The fix is to quote the value ("NO") or use a parser that follows YAML 1.2, which only converts true, false, and null implicitly.
How do anchors, aliases and merge keys work?
An anchor (&name) marks a node so you can reference it later with an alias (*name), avoiding repetition in long files. The merge key (<<: *name) was a YAML 1.1 extension that copies all keys from the referenced mapping into the current one, useful for sharing common config across services. Merge keys are not part of YAML 1.2, but most parsers including js-yaml still support them for compatibility. The diff treats anchors and aliases as plain text, so a renamed anchor shows up cleanly.
Can I paste JSON into the YAML diff tool?
Yes. JSON is a strict subset of YAML 1.2, so any valid JSON document is also a valid YAML document. You can mix the two if you really want to, dropping a JSON-style flow collection into a block-style file. For pure JSON work, our JSON diff tool has format and validate buttons that are JSON-aware, including pretty-print and sort-keys.
Why does the parser reject my file when I use tabs?
Because the YAML spec forbids tabs as indentation. From the 1.2.2 spec: "To maintain portability, tab characters must not be used in indentation." Tabs are allowed inside scalar values (a string can contain a tab), just not at the start of a line where indentation is being measured. The fix is a quick find-and-replace from tab to two or four spaces, depending on the convention your file already uses.
Does this expand YAML anchors when comparing two files?
No. The diff is text-level, so an anchor like &base on one side and the inlined-equivalent mapping on the other will diff as different text even though a YAML parser would resolve both to the same node. The same applies to a *base alias versus its expanded form. If that's the comparison you actually want, pre-resolve anchors before pasting: pipe through yq with yq 'explode(.)' to expand anchors, or run the file through yq -P for canonical pretty-print on both sides.
How does this handle multi-document YAML with multiple --- separators?
Each --- starts a new document in the stream, per the YAML 1.2.2 spec. The diff sees the whole stream as one blob, so reordering documents will look like a wholesale change even when the set of objects is identical. This bites with Helm output, Kustomize builds, and Kubernetes kubectl apply -f bundles. The pragmatic move is to split on ---, sort the document blocks, and diff each pair separately, or run yq ea '[.] | sort_by(.kind, .metadata.name)' across all docs to canonicalise order before pasting.
Why does this flag explicit type tags (!!str, !!int) as different from implicit values?
Because the diff is text-level and value: no is not the same string as value: !!str no, even if a parser would treat them identically in some cases. The semantics also depend on YAML version. YAML 1.1 implicit typing turns no into false and country code NO into the boolean false: the Norway Problem. YAML 1.2 narrowed implicit booleans to just true and false. If you're comparing files round-tripped through Ruby psych (1.1 by default) and PyYAML's yaml.safe_load (1.2 via current libyaml), normalise both sides to explicit tags first and the surprise diffs go away.
Privacy and how this works
Your YAML never leaves your browser. The editor, syntax highlighter, and diff all run on your machine, locally. No analytics on your input, no logs, no cloud round-trip. The format we follow is the YAML 1.2.2 specification. To verify nothing is uploaded, open DevTools and watch the Network tab while you compare.