How to compare two markdown files side-by-side
- Step 1Switch to Upload file mode — The two-file diff needs the Upload file tab, not Paste text. In Paste mode there is only one text box (File A) — the second slot, File B, only appears as an upload drop area. So to compare two files, click Upload file first.
- Step 2Drop the original into File A — File A is the original / baseline — the version you are comparing *from*. Lines that exist only in File A will be shown with a
-prefix (removed). Accepts.md,.mdx,.markdown, and.txt. - Step 3Drop the revised version into File B — File B is the revised / new version — the one you are comparing *to*. Lines that exist only in File B are shown with a
+prefix (added). If you leave File B empty, the diff treats it as an empty document and every line of File A is reported as removed. - Step 4Run the diff — Click run. The diff engine computes the unified diff in the browser. There are no options to configure — md-diff is a fixed line-by-line unified diff with 4 lines of context; there is no ignore-whitespace, word-level, or semantic mode to set.
- Step 5Read the patch — The result is plain unified-diff text in a scrollable panel. Read it top to bottom: each
@@ -a,b +c,d @@header tells you where in the file the next change sits;lines are unchanged context,-lines were in File A,+lines are new in File B. - Step 6Copy or download the result — Use Copy to grab the diff text for a PR comment or email, or Download to save it as
diff.patch. The filename inside the patch header is taken from File A's name; the labels are always File A and File B.
Anatomy of the unified diff output
Every md-diff result is a standard unified diff. These are the markers you will see and what each one means.
| Marker | Where it appears | Meaning |
|---|---|---|
Index: <name> + === line | Top of the patch | Patch header naming the file (taken from File A's filename). Cosmetic — included for patch/git apply compatibility |
--- <name> File A | Header block | Identifies the from side. The right-hand label is literally File A |
+++ <name> File B | Header block | Identifies the to side. The right-hand label is literally File B |
@@ -3,6 +3,6 @@ | Start of each change block (hunk) | -3,6 = starting line 3, 6 lines from File A; +3,6 = starting line 3, 6 lines from File B |
(leading space) | Inside a hunk | Context line — identical in both files (4 lines of context surround each change) |
- prefix | Inside a hunk | Line present in File A but removed in File B |
+ prefix | Inside a hunk | Line added in File B that was not in File A |
What a line-by-line diff catches vs. misses
md-diff compares raw source lines. It is not a semantic or word-level diff, so some kinds of change show up more coarsely than you might expect.
| Source change | How md-diff reports it | Caught? |
|---|---|---|
| One word edited in a sentence | The whole line shows as one - (old) + one + (new) pair | Yes — but at line granularity, not word |
| Trailing whitespace added to a line | Line shows as changed (-/+ pair) even though it renders identically | Yes |
- bullet swapped for * bullet | Each affected line shows as a -/+ pair | Yes |
| A paragraph reflowed (rewrapped to different line lengths) | Every wrapped line differs, so the whole paragraph shows as removed + re-added | Yes — but noisily |
Heading ## H demoted to ### H | That heading line shows as a -/+ pair | Yes |
| Two files with identical text but different line endings on a line | May show as changed depending on the captured line content | Yes (whitespace is significant) |
Cookbook
Real before/after Markdown source and the unified diff md-diff produces. Output abbreviated to the relevant hunk.
A single headline word changed
The editor changed one word in the H1. A rendered preview makes you hunt for it; the diff isolates it to a single line pair.
File A: # The 2026 Annual Report Prepared by the editorial team. File B: # The 2026 Interim Report Prepared by the editorial team. Diff (hunk): @@ -1,2 +1,2 @@ -# The 2026 Annual Report +# The 2026 Interim Report Prepared by the editorial team.
Heading level demoted
A copy editor pushed a section heading one level deeper. Invisible in some renderers, obvious in the diff.
File A: ## Background Context goes here. File B: ### Background Context goes here. Diff (hunk): @@ -1,2 +1,2 @@ -## Background +### Background Context goes here.
A bullet style swap nobody asked for
An auto-formatter rewrote dash bullets as asterisks. The rendered list looks the same, but the source changed on every line.
File A: - First point - Second point File B: * First point * Second point Diff (hunk): @@ -1,2 +1,2 @@ -- First point -- Second point +* First point +* Second point
Trailing whitespace introduced on save
An editor's app added trailing spaces. The text reads identically but the diff flags the line — useful when a downstream linter complains.
File A (no trailing space): The deadline is Friday. File B (trailing spaces after 'Friday.'): The deadline is Friday. Diff (hunk): @@ -1 +1 @@ -The deadline is Friday. +The deadline is Friday.
File B left empty by mistake
If you only fill File A and run, md-diff diffs against an empty document — every line of A appears as removed. This is a quick way to confirm you actually loaded the second file.
File A: # Draft Paragraph one. Paragraph two. File B: (empty — not uploaded) Diff (hunk): @@ -1,3 +0,0 @@ -# Draft -Paragraph one. -Paragraph two.
Edge cases and what actually happens
File B can't be pasted in Paste mode
By designThe Paste text tab shows a single textarea, which becomes File A. File B is only available as an upload drop area. To diff two pasted snippets, save the second snippet to a .md/.txt file and upload it as File B, or save both and switch to Upload mode.
Files swapped (original in File B)
Inverted resultIf you put the new version in File A and the old one in File B, the diff still runs — but additions and removals are inverted (your real additions show as -). The tool has no way to know which is newer; File A is always the 'from' side. Re-run with the files in the correct slots.
File B left empty
ExpectedLeaving File B empty is not an error — md-diff diffs File A against an empty document, so every line of A is reported as removed. If you see an all-- diff, you forgot to load File B.
Identical files
ExpectedTwo byte-identical files produce a patch with the header but no hunks — i.e. no @@ blocks and no +/- lines. An empty body means the source text matches exactly, including whitespace and line endings.
Whitespace-only differences
Reportedmd-diff treats whitespace as significant and has no ignore-whitespace option. Trailing spaces, tab-vs-space indentation, and blank-line changes all show as line differences even when the rendered output is identical.
Reflowed paragraph reads as a full rewrite
NoisyBecause the diff is line-by-line, rewrapping a paragraph to different line widths changes most lines, so the whole paragraph shows as removed then re-added. The text may be 95% identical; the diff cannot tell. Diffing the un-wrapped source (one sentence per line, or no hard wraps) gives cleaner results.
File over the character limit
RejectedEach side is checked independently against your plan's character limit (Free: 500,000 chars). A file that exceeds it throws an error naming the file and its character count. The other file is unaffected — only the oversized side blocks the run.
Word-level change you wanted highlighted
Line granularity onlymd-diff reports a one-word edit as a full old-line / new-line pair, not an inline word highlight. There is no word-diff or character-diff mode. If you need word-level highlighting, this tool's line granularity won't provide it.
Frequently asked questions
Is this a semantic diff or line-by-line?
Line-by-line, using a unified diff algorithm (the same family as git diff). It compares raw source lines and does not understand Markdown structure semantically — it will tell you a heading line changed, but it doesn't model heading hierarchy or list nesting as concepts.
What format is the output?
A standard unified diff (a .patch file). It has a header naming File A and File B, @@ ... @@ hunk markers, and /-/+ line prefixes for context, removed, and added lines. You can download it as diff.patch and apply it with git apply or patch if both sides are real files.
How many lines of context does it show?
Four lines of unchanged context around each change block, which is the engine default. There is no control to widen or narrow it — md-diff has no options panel.
Can I compare two pasted snippets without files?
Not directly. Paste mode provides a single textarea (File A); File B is upload-only. Save your second snippet as a .md or .txt file and upload it as File B, then switch the first input to Upload too (or keep A as a file).
Does it highlight changes in green and red?
The output is plain unified-diff text — additions are marked with + and removals with -, which is how unified diffs encode added/removed lines. The on-page result is shown as monospace text, not a colour-highlighted side-by-side view.
Are my files uploaded anywhere?
No. The diff runs in your browser. Both files are read locally and compared on the page, so confidential or embargoed drafts never reach a server.
What file types can I diff?
.md, .mdx, .markdown, and .txt. Both slots accept the same set. The diff is on the text content, so plain .txt works fine even though the tool is framed around Markdown.
Why does a tiny edit show a whole paragraph as changed?
Your paragraph is probably hard-wrapped, so a small edit reflows the wrap and changes many lines. A line-by-line diff reports each changed line. Author with one sentence per line, or no hard wraps, for cleaner diffs.
How big can the files be?
Each side is limited by your plan: Free 1 MB / 500,000 characters, Pro 10 MB / 5,000,000 characters, Pro-media 50 MB / 20,000,000 characters, Developer 500 MB / unlimited characters. The character limit is checked per file, separately from the byte size.
Can I diff two files on the Free plan even though batch is 1 file?
Yes. The single-file batch limit applies to batch tools like the merger; md-diff is a dedicated two-input tool, so a Free user can load File A and File B and run it. Each file just has to be within the Free character/size limit on its own.
Why are my additions showing as removals?
You likely put the newer file in File A and the older one in File B. File A is always the 'from' side, so anything only in A shows as removed. Swap the files into the correct slots.
What if I need to merge or split files instead of comparing?
Use md-merger to combine several Markdown files into one, or md-splitter to break one file into per-heading files. To normalise formatting before diffing so cosmetic differences disappear, run both files through md-prettifier first.
Privacy first
All Markdown processing runs locally in your browser using JavaScript. No file is ever uploaded to JAD Apps servers — only metadata counters are saved for signed-in dashboard stats.