Text Diff / Compare
Compare two texts or files side by side or inline — line, word or character granularity — entirely on this device.
Treats CRLF and LF as the same ending. Off by default, so Windows-vs-Unix line-ending differences stay visible.
Compares composed and decomposed forms of the same character (café lookalikes) as equal.
Drop a file into either pane — it is read on this device and never uploaded.
Press ? for shortcuts
Do it offline:$ diff -u old.txt new.txt
How to use it
- Paste the older text into pane A and the newer text into pane B — the diff runs as you type, and a file dropped on either pane is read locally with a progress indicator.
- Switch between side-by-side and unified views; both keep the same fixed viewport, so the page never jumps while you work.
- Pick the granularity — line, word or character — to control how finely each changed pair of lines is highlighted.
- When a chip reports that the texts differ only in line endings, trailing whitespace, case or Unicode form, enable that ignore option straight from the chip.
- Take either side of any change block: → Use left copies that block's left version into the right pane, ← Use right does the reverse, and the diff recomputes at once — Revert all merges restores both panes to their pre-merge text.
- Copy the unified diff, download it as a .patch file or a standalone HTML report, or share the comparison as a link.
Paste two versions of anything — a config, a contract clause, a SQL dump — and see exactly what changed. The comparison runs line by line first, then refines each changed pair down to words or characters. View the result side by side or unified, silence line-ending or case noise with one click, merge individual change blocks into either pane, and export a .patch file that standard tooling applies unchanged.
How it works
Each pane is split into lines, and every distinct line is interned to a small integer through a lookup table — an exact stand-in for hashing, with no collisions possible. The Myers O(ND) difference algorithm then runs over the two integer arrays rather than the raw text, which keeps big inputs tractable: the expensive pass touches line identities, never characters.
Matching runs become context, unmatched runs become deletions and additions, and changes closer than seven unchanged lines apart merge into a single hunk carrying three lines of context on each side — the same grouping GNU diff prints. Where a hunk pairs a deleted run with an added run, those line pairs are refined to word or character level, and only for rows currently on screen, so refinement cost follows your scrolling, not the file size. Each hunk's unmatched runs also form the change blocks behind the merge buttons: → Use left splices that block's left-pane lines into the right pane, ← Use right the reverse, and the comparison then reruns on the merged text. Revert all merges restores the exact pane contents captured before the first merge.
Both passes run under a time budget. When two inputs disagree so widely that the fine-grained pass cannot finish, the result honestly downgrades to line-level output behind a visible notice instead of freezing the tab. The exported .patch follows the POSIX and GNU unified format — hunk headers, single-line counts omitted, the no-newline marker included — so patch and git apply accept it without edits.
Examples
Anita reviews every merge request before lunch.
--- a
+++ b
@@ -1 +1 @@
-Anita reviews every merge request before lunch.
+Anita reviews every merge request after lunch.
At word granularity the changed pair is refined token by token: “before” is struck out, “after” is inserted, and the rest of the sentence stays quiet. The patch text above is line-shaped on purpose — a .patch records whole lines, while the word highlights live in the panes.
app_name = ledger
region = ap-south-1
max_connections = 100
--- a
+++ b
@@ -1,3 +1,3 @@
app_name = ledger
region = ap-south-1
-max_connections = 100
+max_connections = 250
Two context lines ride along with the one directive that changed, exactly as GNU diff would print them. Inside the pane, refinement narrows it further — “100” out, “250” in — while the key and the equals sign never light up.
invoice_id = 4021
due_date = 2026-08-31
--- a
+++ b
@@ -1,2 +1,2 @@
-invoice_id = 4021
-due_date = 2026-08-31
+invoice_id = 4021
+due_date = 2026-08-31
Every line reads as deleted and re-added, yet the printed pairs look identical — the only change is the invisible carriage return before each line feed. A chip reports “The texts differ only in line endings.”; one click on Ignore line endings and the verdict becomes “No differences found”.
Every example on this page is executed against the same engine that powers the tool, on every build.
Gotchas worth knowing
Large files are compared, not uploaded
A 50 MB file per pane is within range: the line-interning pre-pass keeps the heavy work proportional to line count, the viewport renders only the hunks you scroll to, and beyond roughly 5 MB combined a working readout with an elapsed-time counter and a Cancel button takes over. Past 64 MB per pane the tool refuses with a banner naming the limit — it compares all of an input or none of it.
Unrelated inputs downgrade honestly
Two texts that share almost nothing are the worst case of any diff algorithm. Rather than letting the tab hang, the comparison stops at its time budget and presents line-level differences behind the notice quoted under common errors below — a coarser answer, never a wrong one, and still a valid patch.
Accents can differ without looking different
The é in “café” can be stored precomposed or as e plus a combining accent; both render identically and compare as different. When that is the only disagreement, a chip says so, and the Normalize Unicode option compares the panes in NFC — Unicode's canonical composition — so lookalikes stop counting.
Right-to-left text keeps its direction
Arabic, Hebrew or Urdu lines inside otherwise left-to-right files are isolated row by row, so a deleted RTL line cannot reorder the +/− gutters around it. Each row takes its direction from its own first strong character, in the panes and in the exported HTML report alike.
Two files, two encodings
Dropped files are sniffed before decoding: byte-order marks are trusted outright, BOM-less UTF-16 is recognized by its zero-byte pattern, and everything else reads as UTF-8. If the panes decode differently, a warning names both encodings; a binary-looking file asks before being compared as text, so a stray NUL byte never turns the diff into mojibake.
Common errors
Pane A input is larger than the 64 MB limit for this tool.- The per-side cap is a memory guard, not a quota — the same message names pane B when the second text is the oversized one. Nothing is trimmed to fit: the comparison takes an input whole or declines it whole.
Inputs differ too much for a fine-grained diff — showing line-level differences.- A downgrade notice, not a failure. The inputs disagreed so widely that word- or character-level refinement ran out of its time budget, so whole changed lines are shown instead. The line-level result is complete and still exports as a working .patch.
Pane A input is larger than the 64 MB limit for this tool. For bigger files use the CLI: diff -u old.txt new.txt- The page-side refusal banner: it appears before any comparison starts and names the command that handles arbitrarily large files on your own machine. Refusing never clears a pane — whatever you pasted stays put.
FAQ
Is this text compare tool free, and how much can it take?
There is no account, no quota and no paid tier on this page. The one bound is a 64 MB memory guard per pane — headroom above the 50 MB files the tool is built for — and crossing it produces a refusal naming the limit, never a silent truncation.
What do line, word and character granularity actually change?
Line granularity marks whole lines as added or removed. Word and character granularity keep the same line diff but highlight, inside each changed pair, exactly which tokens or characters moved. Prose reads best at word level; minified or dense code usually wants characters.
What exactly is the .patch file this page downloads?
A unified diff — the plain-text change format understood by patch, git apply and every code-review system. Each hunk carries a line-number header, three lines of context, deletions prefixed with - and additions with +. Applying it to the old text reproduces the new text exactly.
Why do CRLF and LF line endings count as differences by default?
Because they are real bytes that real systems disagree over — a Windows checkout and a server copy of one file can differ in carriage returns alone, and hiding that would hide a genuine deployment problem. When endings are the only difference a chip says so, and Ignore line endings makes the panes compare equal.
Does anything I paste here leave this device?
No. Comparing, refining and exporting all run in your browser — open the network panel while diffing and watch: no request carries your text. A share link keeps the whole comparison state in the URL fragment, the part of an address a browser does not transmit.
Why does the result sometimes show line-level differences only?
You hit the time budget: refining wildly different inputs to words or characters can grow quadratically, so past the budget the tool posts “Inputs differ too much for a fine-grained diff — showing line-level differences.” and delivers the coarser view immediately instead of stalling.
Can I compare two files instead of pasted text?
Drop a file onto either pane or use its picker — reading happens on this device. UTF-8 with or without a BOM and both UTF-16 byte orders are detected automatically; a file that looks binary asks for confirmation first rather than rendering as garbage.
Keyboard shortcuts
- ⌘/Ctrl + Enter
- Re-run the comparison now, at any input size.
- ⌘/Ctrl + S
- Save the unified diff as a .patch file (this overrides the browser's save-page default; the help overlay notes it).
- ⌘/Ctrl + C
- Copy the unified diff while nothing is selected; any text selection still copies itself.
- ⌘/Ctrl + Shift + C
- Copy the unified diff even with a selection active.
- s
- Swap panes A and B — additions and deletions trade places, and a single undo restores the original order.
- n
- Jump to the next change; the same move exists as a visible button above the diff.
- p
- Jump back to the previous change.
- t
- Cycle to the next theme.
- ? or ⌘/Ctrl + /
- Open the shortcut help overlay.
- Esc
- Dismiss the topmost overlay; pane contents always survive.