You paste what looks like the exact same paragraph into both sides of a diff tool, and instead of "no differences found," every single line lights up as changed. Nothing you can see is different — same words, same punctuation, same spacing on screen. That's the trap: a diff tool compares bytes, not appearances, and several common causes of "invisible" difference don't render as anything a human eye can catch.
Line Endings: CRLF vs. LF
The single most common cause. Windows text editors traditionally end a line with two characters — carriage return + line feed (\r\n, CRLF). Linux, macOS, and most modern tools end a line with just one — line feed (\n, LF). Open the same file that was saved on Windows and then on a Mac, and every line differs by an invisible \r at the end, even though nothing visible changed. Git is notorious for surfacing this: a file edited on Windows and one edited on Linux can show a full-file diff where the only real change is one word, because every line's ending character disagrees.
How to spot it: most diff tools have a "show whitespace" or "show invisible characters" toggle — turn it on and CRLF-vs-LF differences appear as a visible \r marker at each line end instead of a mysterious "everything changed."
Trailing Whitespace
A space or tab at the end of a line is invisible in almost every editor and every browser. Copy a paragraph from a webpage, a PDF, or a chat message, and it's common to pick up trailing spaces that were part of the original formatting but render as nothing. If one version has a trailing space on a line and the other doesn't, a byte-level diff correctly reports that line as changed — there's just nothing to see.
- Trailing spaces/tabs at line ends — common when copying from rendered HTML or rich text.
- Leading whitespace differences — four spaces vs. a tab vs. two spaces, all rendered identically wide by most fonts, but different bytes.
- Non-breaking spaces (
) — copied from web pages that use instead of a regular space. Looks exactly like a space, is a completely different character.
Invisible Unicode Characters
Beyond whitespace, a handful of zero-width or visually-empty Unicode characters routinely survive copy-paste and cause a diff to flag "different" text that reads identically:
| Character | What it is | Where it sneaks in |
|---|---|---|
(BOM) | Byte Order Mark | Files saved by Windows Notepad or exported from Excel often start with an invisible BOM |
| Zero-width space | Common in text copied from web articles, used to control word-wrap |
| Non-breaking space | HTML , common in copy-pasted web content |
/
| Line/paragraph separator | Some rich text editors use these instead of \n |
None of these render as anything on screen. A diff tool sees them as real characters and reports a real difference — because there is one, just not one you can perceive without a hex viewer or a "reveal invisibles" mode.
Unicode Normalization: Same Letter, Different Bytes
This one is subtler than whitespace. Some accented characters can be encoded two different ways that render identically: as a single precomposed character (é as one code point, U+00E9) or as a base letter plus a combining accent (e + U+0301, two code points that render as é when displayed together). Text copied from macOS (which tends to use decomposed form) and text typed on Windows (which tends to produce precomposed form) can look byte-for-byte identical on screen while differing at the character level — a diff tool built for plain byte comparison will flag every accented character as changed. The fix is normalizing both strings to the same Unicode form (NFC or NFD) before comparing, which most diff libraries do not do automatically.
Encoding Mismatches
If one file is saved as UTF-8 and another as Windows-1252 (a common legacy Windows encoding) or ISO-8859-1, plain ASCII text (English letters, digits, basic punctuation) is usually identical either way — but the moment there's a curly quote, an em dash, or an accented letter, the underlying bytes diverge even though most text editors will silently decode and display both correctly. A raw byte-level diff doesn't decode anything; it just compares bytes, so an encoding mismatch on non-ASCII characters shows up as a difference on lines that look completely unchanged.
Quick Checklist Before You Trust "No Differences"
- Toggle "show whitespace" or "show invisible characters" in your diff tool — this alone catches the majority of cases (CRLF, trailing spaces, non-breaking spaces).
- Check for a BOM at the very start of the file if line 1 shows a difference but looks identical.
- Re-save both files with the same encoding (UTF-8, no BOM) if the source files came from different platforms or tools.
- Normalize Unicode (NFC) before comparing if either source went through a Mac clipboard, a PDF extraction, or an OCR pipeline — all three commonly produce decomposed accented characters.
- Strip trailing whitespace deliberately if you're comparing prose pasted from different sources (web pages, chat apps, word processors) rather than source code, where trailing whitespace is usually meaningful.
Quick FAQ
Why does Git show a whole file as changed when I only edited one line?
Almost always line endings — the file was re-saved with a different CRLF/LF convention than the one already committed, so every line's terminating character differs. Configuring .gitattributes or core.autocrlf to enforce one line-ending convention repo-wide prevents this.
I copied text from a PDF and a Word doc that should be identical — why does it diff as different everywhere? PDF text extraction frequently introduces non-breaking spaces, unusual hyphen characters, or decomposed Unicode for accented letters, none of which a Word export produces the same way. Normalize whitespace and Unicode form before comparing extracted PDF text.
Does it matter for code, or just prose? It matters more for prose, ironically. In code, most languages ignore whitespace differences functionally (though not in Python, YAML, or Makefiles), and CRLF/LF is usually caught by tooling. In prose comparison — contracts, articles, translated copy — there's no compiler to shrug off a stray character, so invisible differences are exactly the ones worth catching before you conclude two versions match.
Related Free Tools
- Text Diff — compare two texts and see exactly which characters differ
- HTML Entity Encoder — convert
and other entities to see what character they really are - Why Is My JSON Invalid? — another case where an invisible character breaks something that "looks" fine