Text Diff
Compare two texts side-by-side with line and word-level highlighting — privately.
How to use Text Diff
- Paste or type the original text into the Left pane.
- Paste or type the updated text into the Right pane.
- Toggle Ignore case or Ignore whitespace if you want those axes treated as equal.
- Read the colored side-by-side view — red highlights deletions on the left, green highlights insertions on the right, and within replaced lines the specific changed words are tinted.
- Press ⌘/Ctrl + Enter to re-run the diff and write the state into the URL for sharing.
- Click Copy patch to grab a unified-diff block you can drop into a PR review or a chat message.
Text Diff
A fast, private, browser-only text comparison tool. Paste any two versions of a document — two drafts of a paragraph, two versions of a config file, two log outputs, two prompts — and Text Diff shows you exactly what changed, line by line, with word-level highlighting inside each changed line so you never miss a single-word substitution.
Why a dedicated text diff tool matters
Comparing two blocks of text is one of the most common operations in a developer, writer, or editor's day, and yet most online "difference checkers" are either ad-infested pages that POST your text to a server, or bare-bones textarea-pair widgets that just dump the two inputs side by side without actually diffing them. This tool ships a structural diff that runs the classic Longest Common Subsequence algorithm in your browser, identifies which lines are equal, inserted, or deleted, and then — for lines that were replaced — runs a second pass at the word level so you see exactly which tokens changed.
The result is the kind of diff you used to need a desktop tool for: line-accurate, word-precise, with proper side-by-side panes, stable line numbers, and a clean unified-patch export. No accounts, no uploads, no analytics watching your payloads. The entire algorithm is under 200 lines of pure TypeScript and runs in your browser — nothing about the two texts you compare leaves the page.
What it does
- Line-level LCS diff — classifies every line as equal, inserted, or deleted using the dynamic-programming Longest Common Subsequence algorithm. Guaranteed minimal edit distance, deterministic output.
- Word-level highlighting within changed lines — when a delete and an insert pair up, a second LCS pass over word tokens tints the specific words that differ. Catches single-character typos that line-only diffs bury in noise.
- Side-by-side view with line numbers — left and right panes render as a two-column table with 1-based line numbers, colored backgrounds for inserts (green) and deletes (red), and per-row alignment so your eye moves horizontally across the change.
- Ignore case option — folds
HelloandHELLOto the same line key without mutating the surfaced text. - Ignore whitespace option — collapses runs of whitespace inside a line so
"a b"and"a b"compare equal. Useful for diffing re-wrapped Markdown or reformatted YAML. - CRLF, LF, and lone CR handling — the splitter normalises every line terminator, so a Windows-saved file and a Unix-saved file with identical content show zero differences.
- Unicode-aware — word tokenisation uses
\p{L}and\p{N}property escapes, so Cyrillic, CJK, accented Latin, and emoji all tokenise sensibly. - Unified patch export — the Copy patch button emits
---/+++/@@hunk headers followed by space/plus/minus prefixed lines, the format understood bypatch(1), every modern code review tool, and most LLM prompts. - URL-hash share — pressing ⌘/Ctrl + Enter or clicking Share writes both texts and the option toggles into the URL fragment, so you can send a colleague a link that opens to the exact comparison you were looking at. The fragment never reaches a server.
How the algorithm works
The Longest Common Subsequence (LCS) algorithm builds a two-dimensional table where each cell (i, j) holds the length of the longest subsequence common to the first i lines of the left text and the first j lines of the right text. Building the table takes O(n·m) time. A backtrack from the bottom-right corner of the table then emits the edit script: whenever both current lines match the current cell value came from a diagonal move (equal); otherwise the move came from the side with the higher score (insert or delete).
For the word-level pass, the exact same algorithm runs on the tokens of the two lines that were paired as a replace. Because most replaced lines are short, this second pass is effectively free — but it's what makes the diff view actually readable when you are comparing two drafts of a sentence, two slightly different log lines, or two versions of a config key.
Line keys are normalised — lower-cased if Ignore case is on, whitespace-collapsed if Ignore whitespace is on — before the LCS table is built, so the options affect equality without mutating what you see in the output.
Common use cases
- Comparing two drafts of documentation, a contract, or an email.
- Auditing a config file for unexpected edits (migrations, CI reruns, accidental reformat).
- Hunting the exact line that changed in a failing log snapshot.
- Checking an LLM rewrite against the original prompt or response.
- Confirming a find-and-replace didn't over-fire.
- Reviewing a translation against its source paragraph by paragraph.
What's not supported (yet)
- Three-way merge view — today Text Diff is strictly two-way. A three-pane merge with a computed base is on the roadmap.
- Block-level move detection — if you cut a paragraph from one place and paste it elsewhere, the tool reports that as a delete and an insert, not a move. A move-aware mode would require a more expensive diff variant (like Patience or Histogram diff); worth it for code, but noisier for prose.
- Syntax-aware diff — for structured data, use the dedicated JSON Diff tool, which compares parsed values, ignores key order inside objects, and emits path-tagged changes.
- Character-level diff for very short lines — Text Diff's word-level pass bottoms out at word tokens. For single-character comparison (DNA sequences, obscure codes), a character-level fork is on the backlog.
Related tools
- JSON Diff — structural diff for parsed JSON documents; ignores key order, compares values by type, reports changes as paths.
- Case Converter — normalise identifier casing before or after a diff to avoid noise when comparing renamed variables.
Frequently asked questions
Does this text diff tool send my content to a server?
No. The Text Diff tool runs the Longest Common Subsequence algorithm entirely in your browser. Your left and right inputs never touch a server, an analytics pixel, or a third-party service. The Share button encodes the two texts into the URL fragment (`#s=…`), and by HTTP design fragments never travel to the server. That makes it safe to paste contract drafts, internal documentation, log snippets, or any other text you would not paste into a random web form.
How does word-level highlighting work on changed lines?
When a line on the left is paired with a replacement line on the right, Text Diff runs a second LCS pass over the two lines' word tokens. Words and separators are detected using Unicode-aware regex classes (`\p{L}`, `\p{N}`), so the tool works for English, Cyrillic, Chinese, accented European text, and mixed scripts. The changed words are tinted red on the left and green on the right so your eye lands on the substitution instead of scanning the whole line.
What's the difference between line-level diff and text diff?
Line-level diff treats each newline-separated chunk as an atomic unit — if a single character changes, the entire line is flagged as one delete and one insert. That's the standard `git diff` behaviour. Text Diff layers a word-level pass on top, so within a changed line you also see which specific words moved. This dramatically reduces noise when you are comparing two paragraphs of prose or two slightly different log messages where only a fragment changed.
Does "ignore whitespace" also ignore blank lines?
It collapses runs of whitespace inside a line and trims leading or trailing whitespace before the LCS key comparison, so `"hello world"` and `"hello world"` count as equal. An entirely blank line is still treated as a distinct entry, so a trailing blank line difference will still show up — blank lines often carry semantic meaning in formats like Markdown or diff context. For true blank-line-agnostic comparison, strip empty lines from both sides before pasting.
Can I copy the diff as a unified patch?
Yes. The Copy patch button emits a unified-diff-style block — `--- left / +++ right` followed by `@@` hunk header and lines prefixed with space, plus, or minus. That format is understood by `patch(1)`, every major code review tool, GitHub comments, and most LLM prompts, so you can paste the result directly into a PR description or a chat thread without hand-formatting.
How large can the inputs be?
The LCS table grows with the product of the two line counts, so memory is the practical ceiling. On modern browsers, two inputs of a few thousand lines each complete in well under a second. Above ten thousand lines per side you may see noticeable lag because the algorithm is O(n·m). For genuinely huge files, split into chapters and diff them one at a time, or fall back to a command-line tool.