Help shape the future of JSON Workbench! We'd love to hear how you use it.

Why compare two files

Every project drifts. A config that worked last week, an environment file copied between machines, a generated client that should be identical, or a log snapshot taken before and after a deploy all require you to find what actually changed. Reading two files side by side is slow and error-prone. A diff turns the hunt into a clear verdict: same, added, removed, or edited, line by line.

The file comparison tool on this page is built for that exact verdict. It is not a merge tool and it does not guess intent. It aligns two plain-text inputs, highlights every difference, and lets you walk through the changes in order. There is no upload, no account, and no backend required.

Config drift

Compare .env, nginx.conf, docker-compose.yml, or Kubernetes manifests between commits or hosts to catch the one line whose value shifted.

Environment diffs

Diff staging vs production variable dumps or feature-flag files. Spot a missing key or a flipped boolean before it becomes an incident.

Generated-code review

Compare generator output like OpenAPI clients, Protobuf stubs, or migration SQL before committing. The diff shows only what the generator actually changed without formatting noise.

Log & data deltas

Drop two log excerpts, CSV exports, or NDJSON slices side by side. Added and removed lines surface regressions, missing events, or pipeline gaps instantly.

Getting files in

The editor accepts text instead of binaries, and it offers three paths that all end in the same synchronized view. Pick the method that matches where your content already lives.

MethodWhen to use itWhat happens
PasteA snippet is already on your clipboard, such as a code block from a PR, a log excerpt, or a config copied from SSH.Click Paste on that side or press Ctrl+V / Cmd+V. The editor on that side is replaced with the clipboard text and the diff recomputes immediately.
UploadThe content lives on disk, like a .txt, .json, .yml, .xml, or any text-based source file.Drag the file onto the dropzone or click it to open the file picker. Only one file per side is accepted. Binaries such as .pdf, .png, .zip, or .exe are rejected with a toast message. Files larger than 10MB are attached as a File reference and streamed chunk by chunk instead of being read into memory all at once.
Tool handoffYou just decoded two Base64 payloads in separate tabs and want to know why they differ, or a formatter output is ready to compare.On the Base64 page, every decode opens a numbered tab. Hover any tab and click the ⇄ compare icon — the two decoded texts land here as Left and Right, with the tab labels as file names. The same handoff works from JSON Compare: navigate here and the shared store already holds the content.
All three paths feed the same pair of panes. The link icon above each pane switches that side between Search and URL import. URL import fetches remote text directly and automatically converts GitHub file-view URLs to their raw equivalent.

Anatomy of the result

The result is a synchronized side-by-side view: two panes scroll in lockstep so every change on one side is aligned with its counterpart on the other. The annotated mock below shows the real layout:

FILE · COMPARISONtext/plain · side-by-side
Left — app.env.example
1HOST=localhost
2PORT=3000−
3LOG_LEVEL=info
4TIMEOUT=30~
Right — app.env.production
1HOST=localhost
2PORT=8080+
3LOG_LEVEL=info
4TIMEOUT=60~
The left pane is the original, and the right pane is the modified. The gutter shows line numbers, and the inner marker column shows +, −, or ~ for add, remove, or change.
1
Added (green)
A line that exists only on the right. Monaco shades it green and places a + marker. In the example, PORT=8080 appears only on the right, as the left line is absent.
2
Removed (red)
A line that exists only on the left. It is shaded red with a − and a strikethrough. Here PORT=3000 was removed in production, so you see exactly where.
3
Changed (amber)
A paired line whose text differs. Both sides are shaded amber with a ~ marker and the differing span is highlighted inline. TIMEOUT=30 → TIMEOUT=60 is a single edit, not an add plus a remove.
4
Aligned & searchable
Unchanged lines stay neutral and keep both panes aligned. Per-side Search (find-as-you-type) and the global Previous / Next Change arrows (top-right) jump between hunks without scrolling.
Above each pane, the toolbar offers Search or URL import, Trash to clear that side, a match counter (No matches or 2 of 7), up/down match navigation, Copy (always), Paste (disabled only in read-only >10MB mode), and Trim (file-mode only, which replaces Format/Minify). The far-right controls walk the global diff hunks, and Exit clears the store to return to the formatter.

Navigating large files

Files larger than 10MB do not fit comfortably in a React string prop. The editor switches to a streaming path the moment either side exceeds the threshold, whether the content came from a paste or a dropped File object.

Optimized read-only mode

Large file detected. Optimized Read-Only mode enabled for performance. History (Undo/Redo) and Folding are disabled. Showing chunked data as it loads.

Stays interactive
  • Scrolling, synchronized side-by-side view and line numbers
  • Per-side search and URL import
  • Global Previous / Next Change navigation (ArrowUp / ArrowDown)
  • Copy per side and word-wrap toggle (Alt+Z)
Temporarily disabled
  • Editing: readOnly and domReadOnly are true on both panes
  • Trim, Format and Minify transforms (tooltip: “Trim disabled for large files”)
  • Paste into the large pane
  • Minimap, folding, undo/redo history and JSON diagnostics

The 10 MB threshold applies per side. Below it, your content is preserved automatically if you reload the tab. Above it, the file is streamed directly into the viewer without being stored, so a reload starts fresh. Clearing both sides returns the editor to full interactive mode.

Limits & privacy

Everything on this page runs in your browser. There is no upload, no server-side processing, and no storage beyond what is needed to display the current comparison.

That also means limits are local and not enforced by a quota:

Local-first

Text never leaves the device. Close the tab and the content is gone; reload and the store is empty.

Memory-bound

Tens of megabytes are comfortable on desktop. The practical ceiling is the tab's available memory, and very large single-line files are the hardest to render.

No upload

Files are read locally from your device. The network is only used if you explicitly import content via a URL.

Gotchas

These are the cases that surprise people who compare files for the first time. Each one is real behavior, not a bug, and has a simple fix.

Whitespace-only differences light up the whole line▾
In file mode, ignoreTrimWhitespace is false, so the diff treats indentation and trailing spaces as meaningful. That is deliberate because for plain text, a space is data. In JSON mode, the same flag is true. If the noise bothers you, press Trim: it trims each line, drops empty lines entirely, and collapses runs of two or more spaces into one. Use it when you care about content, not formatting.
CRLF vs LF shows every line as changed▾
Files from Windows end lines with CRLF (\r\n), while macOS/Linux and most git checkouts use LF (\n). Trim handles this too: it splits on \n and trim() strips the stray \r, normalizing line endings to LF. If you need to preserve line ending style, don't trim; instead configure your editor or git config core.autocrlf before comparing.
A minified JSON file is one huge line and the diff looks broken▾
A single-line file has nowhere to align, so any change appears to affect the whole file. Horizontal scrolling plus syntax highlighting also suffer. Run the content through the JSON Formatter first (Format) to expand it into indented lines, then bring the formatted outputs back here. Side note: huge single lines also defeat Trim, which operates line-by-line.
The output looks like or mojibake▾
That is an encoding mismatch, not corruption. The tool expects UTF-8. Files saved as Windows-1252 or Latin-1 with accented characters will display garbled output. Re-save the file as UTF-8 first (VS Code: bottom-right encoding indicator > Save with Encoding > UTF-8), then compare again.
There is no Format, Minify or language switch, only Trim▾
Correct. File compare declares availableModes: ['code'] and capabilities canCopy / canPaste / canDownload only. No canFormat, no canMinify, no Tree or Table view. The page is a plain-text diff. For structured data with formatting, use JSON Compare or the JSON Formatter.

Frequently asked questions

Is my data uploaded or stored anywhere?

No. Pasting, dropping, URL import, and the diff itself all happen in your browser. Nothing is sent to a server and nothing is persisted beyond the current tab's in-memory store. Clearing both sides or leaving the page calls reset() and empties the store.

What file types can I compare?

Any text-based file such as .txt, .env, .json, .yml, .xml, .csv, .md, or source code. Binaries such as .pdf, .docx, .png, .zip, or .exe are blocked by extension. Files like image/*, video/*, and audio/* are blocked by MIME type before anything is read.

What does Trim actually do? Will it change my file?

Trim is not lossless. It splits on newlines, trims each line, drops any line that becomes empty, joins with \n, and then collapses every run of two or more whitespace characters into a single space. Blank lines you intentionally left will be deleted. The editor is updated in place and the transformed text is what gets diffed and copied.

How large a file can I compare?

There is no hard file-size cap, but the >10MB path is read-only and the tab's memory is the real limit. Many users comfortably compare 20–30MB text files on desktop, but beyond that the browser may slow or run out of memory. If you only need a section, split the file first.

Can I compare decoded Base64 payloads here?

Yes. On the Base64 page, each decode opens a numbered tab. Hover a tab and click the ⇄ icon, then do the same on a second tab. Both decoded texts arrive here side by side, with the tab labels shown as file names. You can also open JSON Compare and navigate to this page — the content carries over automatically.

How is this different from JSON or folder compare?

Use JSON Compare when you need JSON-aware alignment and formatting; it tolerates whitespace noise by default. Use folder compare to map entire directory trees. Use this file compare when the input is plain text, when whitespace matters, or when you want the strictest line-by-line verdict.

Related tools

Once the file diff is clean, hand structured payloads to the JSON Formatter for validation and formatting, switch to JSON Compare when the content is JSON and you want lenient whitespace handling, use folder compare to spot missing or renamed files across two directories, or decode an embedded payload with the Base64 tool and hand the decoded tabs back here.