Whitespace Remover_
Trim line ends, collapse repeated spaces, flatten blank lines, expand tabs, or strip every space in the document. Presets cover the usual jobs; the switches underneath do one thing each.
It also removes the whitespace with no glyph — no-break spaces, zero-width characters, stray byte-order marks — and tells you everything it took out. A cleaner that returns text and says nothing gives you no way to notice it ate something that mattered.
Found in this text before anything was changed:
- Input
- Text pasted or typed. The browser hands it over as LF whatever the source file used, so the ending style is chosen on the way out rather than read on the way in.
- Output
- The cleaned text, plus a list of every operation performed and how many characters or lines it affected.
- Processing
- Applied in a fixed order in this tab, because the order changes the answer. Nothing is removed without appearing in the report.
- Limits
- Removing characters is an edit, not a comparison. Scan first, read what is actually in the text, then decide — the panel tells you before you act.
- Why the report exists
- This is a tool you paste something important into. Every operation names what it removed and how much, so a fold that ate an ideographic space you needed is visible rather than silent.
The whitespace with no glyph
Not every space is U+0020
A no-break space looks exactly like an ordinary one and is a different character. Browsers, word processors and PDF viewers all emit it, so any text that reached you through the clipboard may carry some, and it survives every tool that only knows about U+0020. Alongside it are the typographic spaces — en, em, thin, hair, figure — and the ideographic space that Japanese text uses legitimately. Then the ones with no width at all: zero-width spaces and joiners, word joiners, and byte-order marks stranded in the middle of a concatenated file. This page names every one it finds, with its code point, before it changes anything.
A tab is a jump, not four spaces
Expanding tabs by replacing each one with a fixed number of spaces is the common shortcut and it misaligns every table anyone has ever pasted. A tab advances to the next multiple of the tab width, so a tab after three characters at width four becomes one space, not four. That is why columns line up in a terminal and collapse the moment a naive converter touches them. This page expands to the real tab stop, per line, so the alignment you could see is the alignment you keep.
The order of operations changes the answer
Fold unusual spaces into ordinary ones before collapsing repeated spaces and a · b becomes one space. Do it the other way and the run survives untouched, because a space followed by a no-break space is not a run of spaces — it is two different characters that happen to look the same. The sequence here is fixed and published in the specs below for exactly this reason: every step is cheap, and the difference between two orderings is text that looks cleaned and is not.
Mixed indentation is the one that changes meaning
Most whitespace problems are cosmetic. Indentation mixed between tabs and spaces is not: Python rejects the file outright, and in every other language it misleads you about which block a line belongs to. Two lines that appear equally indented can be one tab and four spaces, which are the same width on screen and different to a parser. The scan reports this separately from ordinary trailing whitespace, because it is the only whitespace defect that can change what a program does.
Scan, choose, clean
- 01Paste the text. If it holds anything invisible, a panel appears naming each character, its code point and how many there are — before a single thing is changed.
- 02Pick a preset for the common jobs, or set the switches yourself. "Clean a paste" is the one for text that came out of a web page or a PDF.
- 03Turn on "Show invisible characters" to see the input with no-break spaces, tabs and trailing spaces rendered as visible marks.
- 04Read the list under the output. Every operation says what it removed and how much, so nothing leaves without being counted. Then copy or download.
Four things people paste in here
A table copied out of a PDF
Columns held together by no-break spaces and doubled ordinary ones.
Clean a paste
3 no-break spaces, 1 zero-width, 1 BOM
A key an email client wrapped
A token broken across three lines by the message body.
One long string
Every break and space gone
A Python file that will not run
Some lines indented with a tab, some with spaces.
Indentation is mixed
Tabs → spaces, width 4
A draft with ragged blank lines
Two, three or four blank lines between paragraphs.
Collapse runs
Exactly one, everywhere
The spaces that are not spaces
| Character | Looks like | Where it comes from |
|---|---|---|
U+00A0 no-break space | An ordinary space | Anything that reached you through the clipboard — browsers, word processors, PDF viewers |
U+2007 figure space | A space as wide as a digit | Numeric tables that align without tabs |
U+2009 thin space | A narrow space | Typeset text, French punctuation |
U+3000 ideographic space | A wide space | Japanese and Chinese text — often deliberate, so check before folding |
U+200B zero-width space | Nothing at all | Line-break hints from a CMS or a rich-text editor |
U+200D zero-width joiner | Nothing at all | Emoji sequences — removing it can split one emoji into several |
U+FEFF byte-order mark | Nothing at all | A UTF-8 file with a BOM, or several concatenated together |
The ideographic space and the zero-width joiner are the two worth pausing over: both are frequently meant. The scan reports counts so you can judge, rather than folding them silently.
The order operations run in, and why it is fixed
| Step | What happens | Why here |
|---|---|---|
| 1 | Line endings set for the output | First, so every later step works on one convention |
| 2 | Byte-order mark and zero-width characters removed | Before anything measures a column, since they occupy none |
| 3 | Unusual spaces folded to U+0020 | Before collapsing, or a run containing one is not a run of spaces |
| 4 | Tabs expanded or introduced | After folding, so the column arithmetic counts real characters |
| 5 | Repeated spaces and tabs collapsed | Once every space is the same character |
| 6 | Line ends trimmed | After the inner work has settled what a line contains |
| 7 | Blank lines collapsed or removed | Once trimming has made whitespace-only lines actually blank |
| 8 | Document ends trimmed | Last, so it sees the final shape |
Step 3 before step 5 is the one that matters most. Reversed, a space next to a no-break space survives as two characters and the text looks cleaned without being cleaned.
Cleaning without breaking things
- Read the scan before choosing anything. Folding an ideographic space is right in a pasted table and wrong in Japanese prose, and only you can tell which you have.
- Use "Show invisible characters" on the input when a scan reports something and you cannot see where — trailing spaces appear as ·, unusual spaces as ␣, tabs as →.
- Leave "Remove control characters" off unless a scan found some. It is the most aggressive switch here and legitimate text almost never contains them.
- Expand tabs rather than deleting them when the text is code or a table. Deleting a tab closes a column; expanding it keeps the alignment you could see.
- For finding out which lines repeat once the whitespace is gone, the duplicate line remover takes it from here — it diagnoses the same invisible characters and deliberately leaves removing them to this page.
- Zero-width joiners hold emoji sequences together. Stripping them can turn one emoji into two or three, so check the count before using that switch on anything with emoji in it.
Where cleaning whitespace does damage
Some invisible characters are meant to be there
A zero-width joiner is what holds a multi-part emoji together, and an ideographic space is ordinary punctuation in Japanese and Chinese. Both are invisible and both look like damage to a tool. That is why this page counts and names them before doing anything, and why the switches that remove them are off by default.
Whitespace is grammar in some formats
YAML, Python and Markdown all use indentation to mean something. Collapsing inner runs or trimming line ends will change what those documents say, not just how they look. For code, expand tabs to spaces and leave the rest alone; for YAML, use a formatter that understands the structure instead.
Expanding tabs is not reversible
Once a tab has become spaces, nothing can tell those spaces from ones that were typed. Turning them back with "From spaces" converts every run of the tab width, including runs that were never tabs. Convert in one direction, once, and keep the original if it matters.
Removing all whitespace beats every other option
It runs before line handling and takes everything — spaces, tabs and line breaks alike. It is meant for rejoining a wrapped key or token. Applied to prose it produces one unreadable word, and there is no undo beyond your own paste buffer.
A trailing newline is not the same as a blank line
Most files end with one line break and that is correct — many tools require it. Trimming document ends removes blank lines, not that final newline, and the output here never gains a trailing newline it did not already have.
This page cannot see what line endings your file used
Not a limitation of the tool but of the text box: HTML requires a browser to normalise a textarea’s value to LF, so a CRLF file pasted in arrives here with the carriage returns already gone. Nothing on this page can detect or repair a mixed-ending file, and any tool that claims to from a paste box is claiming something the platform does not allow. The line-ending control is genuinely useful in the other direction — choosing what the output uses.
What each option does exactly
- Order of operations
- Fixed and published in the table above: line endings, invisible characters, unusual spaces, tabs, inner collapsing, line trimming, blank lines, document ends. Folding unusual spaces before collapsing is the step that changes the result
- Unusual spaces
- U+00A0, U+1680, U+2000 through U+200A, U+202F, U+205F and U+3000 are folded to an ordinary space. Each is named with its code point in the scan before anything is folded
- Zero-width
- U+200B, U+200C, U+200D, U+2060 and U+FEFF. The byte-order mark is handled separately when it sits at position zero, so it is reported once rather than twice
- Control characters
- U+0000–U+0008, U+000B, U+000C, U+000E–U+001F and U+007F. Tab, line feed and carriage return are deliberately excluded — they are whitespace with a job
- Tab expansion
- To the next multiple of the width, computed per line, not a fixed number of spaces per tab. Width is clamped to 1–16
- Line endings
- A text box cannot hold a carriage return — HTML requires the browser to normalise a textarea’s value to LF — so whatever you paste arrives here as LF however it was stored. This control therefore chooses the convention of the OUTPUT rather than repairing the input, which is a real job when the result is going to a Windows tool that wants CRLF
- The report
- Every destructive operation appears with a count and a unit. Nothing is removed silently, and an operation that changed nothing is not listed rather than being listed as zero
- Copy and Download carry more than the box shows
- The result panel is a text box and normalises to LF like any other, so a CRLF conversion is invisible in it. Copy and Download take the real string rather than reading the box back, which is the only way that option can do anything at all — verified by a browser test that inspects the clipboard
- Scope
- This page removes; the duplicate line remover diagnoses the same characters and deliberately refuses to strip them, and the line counter reports without changing anything
- Network
- None from tool code. A test sweep calls every function this page uses with
fetchandXMLHttpRequestreplaced by stubs that throw, so a stray request fails the build instead of shipping. Disconnect from the network and the page still works.
Questions about removing whitespace
How do I remove extra spaces from text?
Paste it above with "Collapse inner runs" and "Trim line ends" on, which is the "Tidy up" preset. That turns every run of spaces or tabs inside a line into one space and clears the ends. If the text came from a web page or a PDF, use "Clean a paste" instead — it also folds the no-break spaces that ordinary space removal cannot see.
Why do spaces come back after I remove them?
They were never ordinary spaces. A no-break space, a thin space or an ideographic space all look like U+0020 and are different characters, so a tool that removes spaces leaves them untouched. Paste the text here and the scan names each one with its code point and count; "Normalise unusual spaces" folds them into ordinary spaces so the collapsing step can see them.
What is a zero-width character and how did it get in my text?
A character with no width at all — zero-width spaces and joiners, word joiners, byte-order marks. They arrive from rich-text editors that insert line-break hints, from CMS output, and from UTF-8 files whose byte-order mark ends up mid-document after concatenation. They are invisible and they break exact string comparisons, which is usually how people discover them.
Should I convert tabs to spaces or spaces to tabs?
For code, follow whatever the project already uses; mixing the two is the only version that actually breaks things. When you do convert, expand to the next tab stop rather than a fixed count, which is what this page does — replacing each tab with four spaces misaligns any column that did not start at a multiple of four.
Will this break my YAML or Python?
It can, easily. Indentation is grammar in both, so collapsing inner runs or trimming lines changes meaning rather than appearance. Use the tab expansion on its own for code, leave the rest off, and for YAML specifically the YAML formatter understands the structure instead of treating it as text.
Does it tell me what it removed?
Yes, and that is the point of it. Every operation reports how many characters or lines it affected and what kind they were, so nothing disappears silently. Operations that changed nothing are left out of the list rather than listed as zero, so what you read is what actually happened.
Is my text uploaded anywhere?
The work is JavaScript running in this tab. Every function it calls is covered by a test that stubs fetch and XMLHttpRequest to throw, so a request that slipped in would break the build rather than reach a server — and you can confirm it for yourself by disconnecting and carrying on.