Skip to main content
TD

Text Diff Checker

Compare two blocks of text line by line and see exactly what was added or removed.

Did you like the tool? Thanks!
Share:

How to Use Text Diff Checker

Paste an "Original" and a "Changed" version of your text side by side and get a line-by-line comparison below: unchanged lines in plain text, removed lines highlighted in red with a leading minus sign, and added lines highlighted in green with a leading plus sign, plus a one-line summary of how many lines were added and removed. The comparison updates automatically as you edit either side.

About Text Diff Checker

Comparing two versions of a document, a config file, or a block of code by eye is slow and unreliable once more than a few lines have changed — it is easy to miss a single altered line buried in an otherwise identical paragraph, or to misjudge whether a line moved versus was actually deleted and a different one added in its place. A proper diff algorithm answers this precisely: given two sequences of lines, what is the smallest, most sensible set of line removals and additions that turns the first into the second? This tool implements that from first principles using the Longest Common Subsequence (LCS) algorithm at the line level — the same underlying idea used by tools like the Unix `diff` command and `git diff`. The two texts are each split into an array of lines, and a dynamic-programming table is built where each cell `dp[i][j]` holds the length of the longest common subsequence between the remaining lines of the original text (from line `i` onward) and the remaining lines of the changed text (from line `j` onward). Filling that table takes work proportional to the product of the two line counts (`O(n × m)`), which is why very large inputs are capped — see below. Once the table is filled, a backtracking pass walks from the start of both texts to the end, and at each step: if the current lines in both texts match, it is recorded as "same" and both pointers advance; otherwise, the algorithm looks at which neighboring cell in the DP table has the larger value to decide whether the current original line was removed or the current changed line was added, and advances the corresponding pointer. The result is a single ordered list of same/added/removed operations that, when read top to bottom, explains exactly how to transform the original text into the changed text one line at a time. This is a line-level diff, not a character-level or word-level diff — a line that has even one character changed shows up as one full "removed" line (the old version) immediately followed by one full "added" line (the new version), rather than highlighting just the changed word or character within that line. Line-level diffing is the right granularity for the vast majority of real use cases (comparing paragraphs, config files, code, CSV rows, changelogs) because it matches how people actually think about "what changed" in structured or semi-structured text, and it is dramatically cheaper to compute than character-level diffing on anything beyond a few lines. If you need to see exactly which word changed within a line, visually comparing the removed/added line pair side by side (they appear immediately adjacent to each other in the output) is usually enough to spot the difference at a glance. Because the DP table's size grows with the product of both texts' line counts, comparing two very large documents (tens of thousands of lines each) would require a table with hundreds of millions of cells, which would freeze the browser tab for a noticeable amount of time — an unacceptable trade-off for a tool meant to feel instant. To keep the comparison responsive, input is capped at 2,000 lines per side; if either side exceeds that, a clear message explains the limit rather than the tab silently hanging. For the overwhelming majority of real comparisons (a paragraph, a function, a config file, a changelog), 2,000 lines is far more headroom than needed. The comparison recomputes automatically as you type in either box, with a short debounce delay (200ms) so it does not needlessly recompute the full DP table on every single keystroke while you are still typing or pasting — a small deliberate trade-off between "instant" and "not wasting CPU on intermediate keystrokes", not a requirement of the algorithm itself.

Details & Tips

The algorithm, step by step: 1. Split both "Original" and "Changed" text into arrays of lines (handling Windows, Mac and Unix line endings). 2. If either array exceeds 2,000 lines, stop and show a friendly limit message instead of computing (protects against an O(n×m) table becoming too large to build quickly). 3. Build a dynamic-programming table sized (n+1) × (m+1), filled from the bottom-right corner backward: `dp[i][j] = dp[i+1][j+1] + 1` if line `i` of the original equals line `j` of the changed text, otherwise `dp[i][j] = max(dp[i+1][j], dp[i][j+1])`. The final value `dp[0][0]` is the length of the longest common subsequence of lines between the two texts. 4. Backtrack from `dp[0][0]` forward: walk two pointers `i` (into the original) and `j` (into the changed text) from the start. If the lines at both pointers are equal, record "same" and advance both. Otherwise, compare `dp[i+1][j]` and `dp[i][j+1]` — whichever is larger indicates which side has more remaining common material if that line is treated as changed, so a "removed" is recorded and `i` advances if `dp[i+1][j] >= dp[i][j+1]`, otherwise an "added" is recorded and `j` advances. Once one text is exhausted, any remaining lines in the other are all recorded as removed (if original) or added (if changed). Why a debounce, not a hard requirement: the diff recomputes 200 milliseconds after you stop typing in either box, rather than on every keystroke. This is a deliberate implementation choice to avoid rebuilding the whole DP table dozens of times per second while actively typing or pasting a large block — the algorithm itself is fully deterministic and does not require debouncing to produce a correct result, it is purely a responsiveness optimization. Worked example — a 3-line change: Original: `line one` / `line two` / `line three` Changed: `line one` / `line TWO` / `line three` Result: `line one` (same), `line two` (removed), `line TWO` (added), `line three` (same) → summary: "1 line(s) added, 1 line(s) removed". What this tool does not do: word- or character-level highlighting within a changed line (it is a line-granularity diff, matching how tools like `git diff` present line changes by default), and it does not attempt to detect that a block of lines was "moved" rather than removed-and-re-added elsewhere — a moved block shows up as a removal at its old position and an addition at its new position, which is standard LCS-diff behavior and matches what most line-diff tools produce.

Frequently Asked Questions

Does this diff compare individual words or characters within a line?
No, it is a line-level diff: a line with any change appears as one full removed line followed by one full added line, rather than highlighting just the changed word or character. Comparing the removed/added pair side by side usually makes the exact change easy to spot.
What algorithm does this use?
A hand-rolled Longest Common Subsequence (LCS) diff over the two arrays of lines, computed with classic dynamic programming and then backtracked into a same/added/removed sequence — the same underlying approach used by tools like Unix diff and git diff.
Is there a size limit on how much text I can compare?
Yes, comparison is capped at 2,000 lines per side. Beyond that, the dynamic-programming table needed would be large enough to noticeably freeze the browser tab, so a clear limit message is shown instead.
Why doesn't the diff update instantly on every keystroke?
It recomputes about 200 milliseconds after you stop typing in either box, which avoids rebuilding the full comparison table many times per second while you are actively typing or pasting — a small responsiveness optimization, not a limitation of the algorithm.
What does the summary line mean?
"N line(s) added, M line(s) removed" counts how many lines in the result are marked as added (green, present only in Changed) and removed (red, present only in Original). Unchanged lines are not counted in either number.
If I move a paragraph to a different position, how is that shown?
As a removal at its original position and an addition at its new position — the algorithm does not have a special "moved block" detection, which matches how most standard line-diff tools present a moved block.
Does whitespace-only differences (like trailing spaces) count as a change?
Yes, lines are compared for exact equality, so a line that differs only by trailing whitespace, a tab versus spaces, or a different line ending style will be shown as removed-and-added, since the underlying strings are not identical.
Is my text uploaded to a server for comparison?
No, the entire diff is computed locally in your browser using JavaScript. Nothing you paste is sent anywhere.
Can I use this to compare two versions of code?
Yes, it works on any plain text, including source code, configuration files, CSV data or plain prose — it treats every input purely as lines of text.
What happens if both boxes are empty?
No comparison is shown; the tool waits until at least one side has content before computing and displaying a diff.
What happens if the two texts are completely identical?
Every line is shown as unchanged (plain text, no red or green highlighting), and the summary reads "0 line(s) added, 0 line(s) removed".
Does the diff care about the order of the Original and Changed boxes?
Yes, swapping the two boxes swaps which lines are shown as removed (red) versus added (green) — "Original" is always treated as the starting point and "Changed" as the destination.

Part of These Collections

Also Available As

text diff checker, compare two texts, diff tool online, text comparison tool, line diff, find differences between text, diff checker

Found a Problem?

Let us know if something with Text Diff Checker isn't working as expected.

Thanks — we'll take a look.