How to remove invisible characters on Mac
You can do this with Note My, and here is how to locate every invisible character in a file, judge each one on the evidence, and remove only the ones that are genuinely safe to remove.
Text that looks correct and behaves incorrectly is almost always carrying something you cannot see. A comparison fails on two strings that match on screen. A shell script refuses to run. A search finds nothing where the word is plainly visible. Somewhere in those characters is a zero-width space, a non-breaking space, a bidi control, or a letter that is Cyrillic rather than Latin.
This guide covers how to put Note My to work on that file: where to look, and how to take out the ones that are safe to take out without rewriting anything you meant to write. Our hidden-character scanner does the looking; the judgement calls stay yours.
All of this happens on your Mac. Nothing is uploaded, there is no account, and a file you clean never leaves the machine.
What counts as an invisible character
Note My covers 21 categories, using the names the app itself shows, grouped into tiers.
| Tier | Categories |
|---|---|
| Always wrong — cleared in one click | Zero-width characters · Bidi controls · Soft hyphens · Control characters · Line and paragraph separators · Variation selectors |
| Context-dependent — offered for removal out in the code, reported inside strings, comments and prose | Non-breaking and other unusual spaces · Smart quotes, dashes and ellipses · Lone carriage returns |
| Yours to judge — located to the character, with the evidence in front of you | Homoglyph letters · Combining marks · Non-NFC clusters |
| Structural — reported, with trailing whitespace cleared on request | CRLF / mixed line endings · Trailing whitespace · Mixed tab/space indent |
The tier tells you what each finding gets you. An always-wrong finding can be removed in one click: taking it out cannot change what the text says. A context-dependent one is offered for removal out in the code, and reported only when it sits inside a string, a comment or a run of prose. A report-only one is located for you and left alone, because only you know whether that Cyrillic letter is a typo or a word in Russian. Nothing outside the first tier comes out unless you ask for it.
How the editor tells you a file is not clean
A pill in the status bar keeps count for you while you type. It stays out of the way when there is nothing to say, reads Scanning… while it works, then settles on one of three verdicts: Clean in green, N hidden in orange, or N hidden · D risky in red when some of the findings carry a danger severity. A file that has not been checked yet is never reported clean — the popover gives that case its own wording — so a green tick always means something.
The pill is deliberately quiet. It reports the always-wrong tier and leaves the rest alone, so it will not nag you about a curly apostrophe in a comment. Orange or red is your cue to open the review sheet.
Removing the safe ones in one click
-
Click the hidden-character pill in the status bar
The popover opens with Show in Text, Remove Invisible Character(s), Review All… and Go to Next, plus switches for Protect Strings & Comments and Check While Typing. Nothing is preselected, so pressing ↩ as it opens cannot fire a command that edits your document.
-
Choose Show in Text first
Markers are drawn over the findings: a slug for zero-width and control characters, a tint for the space family, an underline for smart punctuation and homoglyphs, a bar for trailing whitespace. They pulse, then settle so they stay findable; Reduce Motion skips the pulse.
-
Choose Remove Invisible Character(s)
Only always-wrong findings are offered here, so the command cannot change a word you wrote. However many characters come out, one press of ⌘Z puts the document back, and the undo entry is named for the number removed.
To step through findings one at a time instead, use Clean ▸ Find Next Hidden Character and Clean ▸ Find Previous Hidden Character. Each selects the character, scrolls to it, and wraps around at the end of the document.
Reviewing every finding before you delete anything
To see everything — including every category the pill keeps quiet about — open Clean ▸ Clean Invisible / Special Characters… from the toolbar's Clean menu, or the Review All… row in the pill popover. Use it before you hand a file on.
Across the top: a scope control set to Selection or Whole Document, a preset pop-up, and a Scan button. On the left, all 21 categories in danger-first order, each with a checkbox, a severity chip and a count. On the right, the individual findings. At the bottom: Show in Editor, Apply (N) and Close.
Apply is precise. It acts only on findings whose category is ticked and whose Action column says something will be done, so an informational finding stays informational however you set the checkboxes. One press of ⌘Z reverses the whole application under the name "Clean Invisible Characters", and the counts refresh. The sheet is the thorough route: it reports on a document of any size, so even a very long file stays reviewable finding by finding.
Reading a finding
Each row gives you five things: Line:Col, the Code Point, the Category, the Action that would be taken, and the Risk. Double-click a row to reveal that character in the editor.
The code point is the column that ends arguments: U+00A0 is a non-breaking space and U+0020 is not, however identical they look. Line and column numbers always match the gutter, even when you have scanned only a selection.
Choosing a preset
The preset pop-up offers four sets, plus Custom. Tick or untick any category and the pop-up switches itself to Custom, which is the honest thing for it to do.
| Preset | Categories | Use it when |
|---|---|---|
| Safe | 7 | Only what cannot be intentional: zero-width characters, bidi controls, soft hyphens, control characters, line and paragraph separators, variation selectors. |
| Code-safe (default) | 16 | Source code. Adds the odd-space family, smart punctuation, trailing whitespace and lone carriage returns. |
| Prose | 6 | Writing. Leaves your punctuation alone. |
| Aggressive | All 21 | You also want smart quotes, dashes and ellipses converted to their plain equivalents. |
Listing a category is not the same as rewriting it. Smart quotes are in the Code-safe set, but punctuation conversion is switched on by Aggressive alone. The preset the sheet opens with is set in Settings ▸ Text Cleanup ▸ Default preset.
Cleaning a selection instead of the whole document
Set the sheet's scope control to Selection and scan. Only the highlighted range is examined, and only findings inside it can be applied. With Selection chosen and nothing selected, the sheet says "No selection in editor." rather than quietly scanning everything.
There is a faster route for one job. Select a passage, right-click, and the editor's Clean AI Copy/Paste Markers command reads "…in Selection". It is a precise sweep: it strips only artefacts that cannot change visible rendering, wording, tone, punctuation, indentation or emoji structure, and anything needing judgement is counted and reported rather than removed.
Why emoji and accented letters survive the sweep
A careless invisible-character remover destroys emoji. The zero-width joiner that welds a family emoji together is, on its own, exactly the kind of character you are trying to delete — and deleting it splits one glyph into several. Note My will not do that. Joiners, non-joiners and variation selectors that are part of an emoji are listed for you and never removed, which is why a skin-toned emoji comes through a sweep intact. Accented letters are just as safe: combining marks are reported and never removed, because taking one out would quietly change a word.
The same restraint governs the byte order mark. One at the very start of a file raises no finding, because that is where it belongs. The same character anywhere else is treated as junk and offered for removal.
Protecting strings and comments
Protect authored text is on by default. With it on, a context-dependent finding inside a string, a comment or a passage of prose is listed for you and left as it stands — so the quotation marks inside a string literal survive while the code around them is cleaned. Our advanced language identifier puts that protection in the right places, whichever language you are working in. In a plain text file the whole document reads as authored text, so the curly quotes and dashes in your writing are reported to you rather than changed for you.
That protection covers the status bar pill, the Find Next and Find Previous Hidden Character commands and the markers in our comparison view. In the Review All sheet the controls are yours instead: read the Action and Risk columns, and tick only the categories you mean to change — particularly under the Aggressive preset.
What changes from one kind of file to another
The findings suit the file you are in. In Markdown, trailing whitespace is not reported, because two trailing spaces are a hard line break. In a Makefile, mixed indentation is left alone, because tabs are the syntax. In Python, mixed indentation is raised to danger. In a shell script, CRLF line endings are raised to danger, where a stray carriage return breaks a shebang.
Our advanced language identifier is what makes that fit possible, on your Mac and without sending the file anywhere.
The three findings you decide about
- Homoglyph letters. Thirty-seven Cyrillic and Greek look-alikes for Latin letters. One in an identifier is almost certainly a mistake — but it might be Russian, and only you can say which.
- Combining marks. Accents that attach to a preceding letter. Removing one silently changes a word.
- Non-NFC clusters. Text in a decomposed form that differs from its normalised form. Applying one swaps in the normalised version rather than deleting anything, which is what you want before a comparison or an import.
The third can be applied from the review sheet, because there is a safe replacement to put in place. Homoglyphs and combining marks stay yours to settle, so Apply passes over them however you set the checkboxes and a word you meant to write is never rewritten for you. They are located for you — line, column and code point — and the edit, if you want one, is yours to make.
Troubleshooting
The pill says nothing and the file clearly has hidden characters
The full picture is one press away: open Clean ▸ Clean Invisible / Special Characters…, press Scan, and you get every finding in the document, each with its line, column and code point, however long the file is. On a very large file the running count becomes something you ask for rather than something on show, which is how our large-file engine keeps typing and scrolling quick while you work. To have it on show on a file that size too, raise the size limit in Settings ▸ Text Cleanup.
The pill never appears, on any file
The pill has a master switch in Settings ▸ General ▸ Status Bar ▸ Hidden characters, and Check While Typing in the popover reaches the same behaviour from the other end. With both off, cleaning still works from the Clean menu.
Turning on Show Invisibles did not remove anything
Show Invisibles is a view rather than an edit: spaces, tabs and line endings are drawn on screen while the document stays exactly as it is, which makes it a safe way to look before you touch anything. When you want characters taken out, that is Clean ▸ Clean Invisible / Special Characters…, and the two work well together — turn on the view, clean, and watch the markers go.
Apply is disabled even though findings are listed
Apply comes alive the moment a listed finding sits in a ticked category and has something to do in its Action column, so read down that column. Rows marked as information are the ones being left in your hands — a homoglyph, a combining mark, a note that the document mixes line endings — and they stay yours to judge on the evidence. Tick a category whose rows carry a real action, or widen the scope to Whole Document and choose a preset that matches the file in front of you. Double-click any row to jump to that character and make the edit yourself.
A character came back after I pasted again
Clean pasted text is off by default, so a paste arrives as it is. Turn it on in Settings ▸ Text Cleanup and pasted text arrives already cleaned to your default preset. A paste with nothing actionable in it arrives exactly as it was, so the setting is safe to leave on.
I cleaned the wrong thing
Press ⌘Z. Every route — the popover's one-click removal, the sheet's Apply, our cleanup rules behind Clean ▸ Clean Now — takes one undo to reverse in full, under a name that says which operation you are reversing.
Taking a file from suspect to clean
Put together, the pieces make a short routine you can run over anything you are about to hand on. Open the document, set the sheet's scope to Whole Document and press Scan. Choose the preset that matches what you are holding: Safe for a file whose history you do not know, Code-safe for source, Prose for writing you want left as written, Aggressive when plain punctuation is the point. Read down the Action and Risk columns, tick the categories you mean to change, and press Apply.
Then check your work in the editor. Show in Editor puts the markers back on screen, and Clean ▸ Find Next Hidden Character walks the document one finding at a time — that one sits in the Clean menu on every file, so the route is the same whatever you have open. If the file arrived with its line endings mixed, Clean AI Copy/Paste Markers brings the stragglers into line with the LF endings already in the majority — it only ever moves in that direction, so a file that is meant to keep CRLF is never converted behind your back.
Three findings stay yours to settle at the end: a homoglyph, a combining mark or a decomposed cluster is put in front of you with its line, column and code point, and you make the call. That is the shape of the whole routine — our hidden-character scanner does the finding, you do the deciding, and one press of ⌘Z reverses anything you would rather not have done. Every step of it acts on the document you have open in front of you, on your Mac, and nothing about the file goes anywhere else.
Frequently asked questions
How do I tell which invisible character I actually have?
Open Clean ▸ Clean Invisible / Special Characters…, scan, and read the Code Point column. Double-click the row to jump to that character in the editor.
Will removing invisible characters change my visible text?
Your visible text stays as you wrote it. One-click removal is offered for the always-wrong tier alone, and anything that could change wording, punctuation or emoji structure is either reported and left in place or left for you to apply deliberately from the review sheet.
What happens to emoji in a sweep?
They come through whole. Joiners and variation selectors that are part of an emoji are reported and left in place, so a family, a skin tone or a heart stays one glyph rather than splitting apart.
How do I check a very large file?
Open Clean ▸ Clean Invisible / Special Characters… and press Scan: the review sheet reports on the whole document whatever its size, while our large-file engine keeps typing and scrolling quick. To have the status bar keep a running count on files that size too, raise the size limit in Settings ▸ Text Cleanup.