SmartConvert logoSmartConvert

JSON Compare & Diff

Compare two JSON documents and pinpoint added, removed and changed values — entirely in your browser.

Runs locally in your browser — no upload.

How to Compare Two JSON Files Online

Comparing two JSON documents by eye is slow and unreliable: a single changed value can hide inside thousands of lines of nested objects and arrays. Paste the original on the left and the modified version on the right, and this tool lists every difference with its exact path — so you can review API changes, config updates and test fixtures in seconds instead of scrolling through walls of text.

The comparison is semantic rather than textual. Both documents are parsed into data structures first, so a reordered key or a different indentation never counts as a difference: {"name":"Alice"} and a pretty-printed version of the same object compare as identical. Only genuine changes in values, types or structure are reported.

It also runs entirely in your browser. JSON payloads routinely contain session tokens, customer records and internal endpoints, and none of it is uploaded here: parsing, comparison and rendering all happen on your device, and closing the tab leaves nothing behind.

Paste or drop both documents

Drop a .json file into either panel, paste the raw text, or press Load example to see the whole workflow with realistic data. Each panel has Format and Clear buttons so you can pretty-print one side before comparing without leaving the page. Files never leave the browser, so there is no upload step and no account.

The example document is a small order payload with a nested user object and an items array. Loading it produces four differences immediately, which makes it a good way to see how paths and value types are reported before you bring your own data.

What the diff reports

Every difference is classified into one of three kinds, and each carries the full path to the value that changed.

KindMeaningExample
AddedThe right document has a value the left one lacksuser.email appears only on the right
RemovedThe left document has something the right one droppeduser.phone exists only on the left
ChangedBoth sides have the same path, but the value or type differsuser.name goes from "Alice" to "Bob"

The example above produces exactly this output:

PathChangeBeforeAfter
user.nameChanged"Alice""Bob"
user.phoneRemoved"123456789"—
user.emailAdded—"alice@example.com"
items[1].nameChanged"B""C"

A summary line counts the totals — for instance "4 differences found · 1 added · 1 removed · 2 changed" — and the filter buttons narrow the list to a single kind. Every path has a Copy Path button, so you can paste items[1].name straight into your editor, a test assertion or a ticket.

Semantic JSON diff vs text diff

A line-based diff compares characters, so it reports changes that are not changes at all:

ChangeA text diff showsA semantic JSON diff shows
{"a":1,"b":2} reordered to {"b":2,"a":1}Two changed linesNo difference
Two-space indent changed to four spacesEvery line changedNo difference
Number written as 1.0 instead of 1ChangedNo difference — same value
Number 1 vs string "1"ChangedChanged — different type
Array [1,2,3] vs [3,2,1]ChangedChanged — order is meaningful
Boolean true vs string "true"ChangedChanged — different type

The rest of this section explains why each row lands where it does.

  • Key order — {"a":1,"b":2} and {"b":2,"a":1} describe the same object. A text diff flags both lines; a semantic diff reports nothing.
  • Whitespace and indentation — reformatting a payload from two spaces to four produces a large text diff and an empty semantic one.
  • Number formatting — 1 and 1.0 are the same JSON number value, so they compare as equal.
  • Type changes are real — the number 1 and the string "1" are genuinely different, and so are true and "true". Those are reported as changed, because a consumer parsing the payload would behave differently.

Nested objects are compared at any depth and reported under their full path, such as user.profile.name or settings.notifications.email. Keys that are not valid identifiers use bracket notation, so {"content-type":"json"} becomes ["content-type"].

Arrays are compared by index, because element order usually carries meaning in JSON: [1,2,3] and [3,2,1] are different documents. A changed element shows up as items[1].name, and extra elements on either side appear as added or removed at their index.

Comparing API responses

The most common real-world use is checking what an endpoint actually changed. Fetch the response before and after a deploy, save each as a .json file, and drop them into the two panels. Volatile fields such as timestamps, request IDs and pagination cursors will dominate the diff unless you remove them first, which is easy with jq:

# strip volatile fields, then sort keys for a stable comparison
jq 'del(.meta.requestId, .meta.timestamp) | .items |= sort_by(.id)' before.json > a.json
jq 'del(.meta.requestId, .meta.timestamp) | .items |= sort_by(.id)' after.json > b.json

Drop a.json and b.json into the tool and every remaining difference is a real contract change. Because the comparison happens locally, this is also safe for staging payloads that contain real customer data.

The same workflow works for config files: compare a working config.json against one from a failing environment, and the diff usually points at the changed connection string or feature flag immediately.

Ignoring fields you do not care about

This tool compares whole documents and deliberately does not hide paths for you — a diff that silently ignores fields is how real regressions get missed. If a payload contains fields you want to exclude, remove them first and compare the cleaned copies:

jq 'del(.updatedAt, .traceId)' payload.json > payload-clean.json

That keeps the comparison honest: what you see in the results is exactly what differs between the files you supplied.

Compare JSON in code

If you need this inside a test suite or a CI job rather than in a browser, the same semantics are a few lines away.

// Node: order-insensitive deep equality, no dependency required
import assert from "node:assert/strict";
assert.deepStrictEqual(JSON.parse(before), JSON.parse(after));

Python users can reach for json plus a recursive walk, or deepdiff when readable output matters more than zero dependencies. For shell scripts, jq --sort-keys normalises key order before a plain diff:

diff <(jq -S . before.json) <(jq -S . after.json)

The browser tool is faster for one-off reviews and for payloads you would rather not paste into a terminal history; the code snippet is better once the comparison becomes a permanent check.

If either document is hard to read because it arrived minified, the JSON Formatter & Validator can beautify and validate it first — both tools share the same parser, so a document that formats cleanly will also compare cleanly. Tokens and encoded values inside an API response can be inspected with the JWT Decoder or the Base64 Encoder & Decoder.

How to Use This Tool

  1. Paste the original JSON into the Left panel — or drop a .json file onto it, then use Format or Clear as needed.
  2. Paste the modified JSON into the Right panel the same way.
  3. Click "Compare JSON" to parse both documents and compute their semantic differences.
  4. Review the summary — total count plus the added / removed / changed breakdown — and filter the list by kind.
  5. Copy any path with one click to jump straight to it in your editor.

Malformed input never produces a misleading diff: if either side fails to parse, the tool reports which side is invalid along with the exact line and column, and the comparison waits until both documents are valid.

Limits and troubleshooting

  • Size — each side accepts up to 5 MB of text (5,000,000 characters). The interface warns you past 500,000 characters, because very large documents take noticeably longer to parse and diff. If you hit the limit, split the payload or extract the relevant subtree with jq.
  • Invalid JSON — trailing commas, single quotes and comments are not JSON. The error message points at the line and column so you can fix it, and the JSON Formatter & Validator reports the same diagnostics.
  • Non-finite numbers — values such as 1e999, which parse to Infinity, are rejected rather than silently treated as equal.
  • Empty panels — both sides must contain a document; the tool tells you which panel is missing input instead of guessing.
  • Array order — if your diff is full of array changes, sort the arrays first (as in the jq example above) so only real changes remain.

Benefits

  • Semantic, not textual — key order and whitespace never count as differences.
  • Precise paths — every change is located, from user.name to items[2].id.
  • Added / Removed / Changed — differences are classified so reviews stay fast.
  • 100% private — parsing and comparison happen locally; nothing is uploaded.
  • File-friendly — drop a .json file into either panel, no signup needed.
  • Free forever — no account, no limits beyond browser memory and no watermarks.

Frequently Asked Questions

Paste the original document into the left panel and the modified version into the right, or drop a .json file onto each panel, then click Compare JSON. The tool parses both documents and lists every added, removed and changed value with its full path, such as user.name or items[1].id. Nothing is uploaded, so the comparison works offline as well.

A JSON diff compares two JSON documents and lists exactly what changed between them: which values were added, which were removed, and which were modified. Unlike a plain text diff, a semantic JSON comparison understands the data structure, so it can point you to the precise location of each change, like user.name or items[1].id.

Yes. Object property order and whitespace never count as differences. {"a":1,"b":2} and {"b":2,"a":1} are reported as identical, because they describe the same data. Only real changes in values, types or structure are listed.

Yes — that is the most common use case. Save the response before and after a deploy as two .json files and drop one into each panel. Strip volatile fields first, such as request IDs and timestamps, or they will dominate the diff; a short jq command like del(.meta.requestId) is usually enough. Because comparison is local, staging payloads with real customer data stay on your machine.

Each side accepts up to 5 MB of text, which is 5,000,000 characters. The interface warns you once a document passes 500,000 characters, because parsing and diffing very large payloads takes noticeably longer. If you hit the limit, split the document or extract the relevant subtree with jq before comparing.

Yes, at any depth. Nested changes are reported with their full path, for example user.profile.name or settings.notifications.email. Keys that are not plain identifiers use bracket notation, such as ["content-type"], and you can copy any path with one click.

Arrays are compared by index, so order matters: [1,2] and [2,1] are different. A changed element is reported with its index path, such as items[1].name, and extra elements on either side show up as added or removed. If your diff is dominated by array changes, sort the arrays first — with jq's sort_by() for example — so only real changes remain.

Yes. The number 1 and the string "1", or true and "true", are different values and will be flagged as changed. Numbers are compared by numeric value, so 1 and 1.0 count as the same JSON value. Non-finite results such as 1e999 are rejected instead of being treated as equal.

The comparison covers whole documents by design — a diff that silently hides fields is how real regressions get missed. To exclude fields, remove them first and compare the cleaned copies, for example jq 'del(.updatedAt, .traceId)' payload.json > payload-clean.json. What you see in the results is then exactly what differs between the files you supplied.

No. Both documents are parsed and compared entirely in your browser with JavaScript. Nothing is ever sent to a server, so sensitive API responses and config data stay on your device. Closing the tab discards the inputs.

No, the tool compares one pair at a time. To review a chain of versions, compare the oldest against the middle version, then the middle against the newest; each run shows only the changes introduced between those two documents.

Yes, completely free. There is no account, no usage quota and no watermark, and the tool works offline once the page has loaded because no server call is involved.