diffpad
Paste. Compare. Copy the diff.
Semantic comparison
Compares by key paths, not line positions. Reordered keys produce zero noise.
Auto-detect format
Automatically detects JSON or YAML. No manual format selection required.
Client-side only
Everything runs in your browser. No data is sent to any server.
How Diffpad compares a Kubernetes Deployment
Paste this web-frontend Deployment manifest into the left pane. Paste a copy into the right pane with the metadata.labels block reordered, the tier: web label removed, replicas bumped from 2 to 4, the nginx image moved from 1.24 to 1.26, CPU and memory limits doubled, LOG_LEVEL flipped from warn to info, CACHE_ENABLED switched on, and a new CDN_URL env var appended. A line-based diff reports 14 changed lines, six of them pure label-reorder noise. Diffpad's semantic pass reports six changes. Both are right about different things, and which one you want depends on what you're about to do next.
The input: two versions of a user-service config
The example loaded by the YAML button is this exact Deployment, shipped with Diffpad as a reference fixture. The Original side declares replicas: 2, cpu: 250m, memory: 256Mi, nginx:1.24, and two env vars. The Modified side declares replicas: 4, cpu: 500m, memory: 512Mi, nginx:1.26, three env vars, and drops tier: web. Sort the labels alphabetically too (a common artifact of kubectl get -o yaml round-tripping through kustomize) and a naive line diff treats every label line as moved.
That round-trip noise is why the tool exists. We picked the YAML deployment as the default example because it reproduces the failure mode that pushed us toward a structural diff in the first place: a 30-line manifest where 14 lines look changed and only 5 are a real deploy-time risk.
What the semantic pass ignores and why
When both panes parse as YAML, Diffpad walks the parsed tree and compares values by key path. The path spec.template.spec.containers[0].image exists on both sides, so the diff records one modification: nginx:1.24 becomes nginx:1.26. The path metadata.labels.tier exists only on the left, so the diff records one deletion. Reordering app and tier under metadata.labels produces no row at all. Mapping keys in YAML are unordered by the 1.2 spec (§7.4.3), and Diffpad respects that.
The six rows the semantic pass produces look like this:
~ metadata.labels.tier "web" → (removed)
~ spec.replicas 2 → 4
~ spec.template.spec.containers[0].image nginx:1.24 → nginx:1.26
~ spec.template.spec.containers[0].resources.limits.cpu 250m → 500m
~ spec.template.spec.containers[0].resources.limits.memory 256Mi → 512Mi
+ spec.template.spec.containers[0].env[2] CDN_URL=https://cdn.example.comSix rows, all actionable. Nothing about label order, nothing about whitespace, nothing about whether you wrote "false" quoted or as a bare boolean. (The YAML 1.1 vs 1.2 boolean coercion question is one Diffpad sidesteps by comparing string-tagged values literally.)
Why doesn't the semantic diff show the LOG_LEVEL change?
It does. The env list has the same LOG_LEVEL key on both sides with a different value, so it shows as a modification on spec.template.spec.containers[0].env[0].value. The summary above abbreviated the env block to highlight the new CDN_URL insertion. Sequence diffs in YAML are positional by index, the one place semantic comparison still leans on order.
Where line-based diff takes over
Switch the input to a CSV export or a SQL migration script and structural diffing doesn't apply, because there's no canonical tree to walk. CSV rows are positional. SQL statements are ordered. .env files care about declaration order for shell evaluation. Diffpad detects these formats and falls back to a line-based Myers diff with whitespace-trim options. The Ignore Whitespace toggle in the compare bar collapses runs of spaces or tabs to a single space before comparison, which is what you want when one side came from a formatter and the other came from a raw cat.
Line-based mode is also where HCL, INI with duplicate keys, and any input where one pane parses cleanly and the other doesn't end up. We chose that fallback over refusing to diff mismatched parse states because a half-broken config is the most common reason anyone opens a diff tool.
What happens if I paste JSON in one pane and YAML in the other?
The detector identifies each pane on its own, both resolve to structural strategies, and the comparison runs across the canonical tree representation. A JSON object and a YAML mapping with the same keys and values produce zero diff rows. Cross-format mode answers a specific workflow: comparing an OpenAPI spec exported as JSON against the YAML source it was generated from, where 80% of the time the divergence is stale codegen and the other 20% is a real schema change.
Cross-format comparison and what gets lost
Cross-format diffing isn't free. YAML supports anchors and aliases (& and *), comments, and explicit type tags that JSON does not. When one pane is YAML and the other is JSON, Diffpad expands anchors before comparison, drops comments on both sides, and normalizes tagged scalars to their JSON equivalent. The lossy-honest version: if your YAML uses !!binary tags or relies on &anchor referenced six places downstream, the JSON-side diff will show structural equivalence even when the YAML round-trip would change byte-for-byte.
TOML and XML cross-compare with similar caveats. TOML's tables-of-arrays syntax flattens to nested arrays. XML element ordering matters for some schemas (XHTML) and doesn't for others (Spring config), so Diffpad treats sibling elements as ordered unless they share an id attribute the parser can key on.
Reading the diff summary output
The Copy Summary button produces a plain-text block formatted for pull request comments and Slack. It lists the comparison mode (semantic or line-based), the count of additions, deletions, and modifications, then each row with its key path or line number. The output is deterministic across runs, so the same two inputs on two different machines produce byte-identical text. We use that property as a regression check: any commit to the diff engine that changes the formatted summary for a fixed input fails CI.
For a six-row diff like the YAML example above, the summary is around 400 bytes. It fits in a GitHub PR review comment without truncation.
Frequently Asked Questions
How do I compare two JSON objects online?
How do I compare two YAML files?
Can I diff JSON against YAML in the same tool?
Why does my JSON diff tool flag key-order changes as differences?
How do I copy a JSON diff as plain text for a Slack message or PR comment?
Is Diffpad free and does it send my data to a server?
Does Diffpad handle nested objects and arrays?
What is a semantic diff and how is it different from a text diff?
Privacy
This tool runs entirely in your browser. No data leaves your device. There are no accounts, no tracking, and no cookies beyond what the ad network may set. See our Privacy Policy for details.