How to find and remove a byte order mark on Mac
You can do this with Note My, and here is how to see a byte order mark that nothing else displays, remove it, and save the file back without one.
A byte order mark is a character at the front of a file — three bytes of it in UTF-8 — that nothing displays and almost everything trips over. A shell script begins with a shebang the kernel no longer recognises. A JSON parser reports an unexpected token at position 0. A configuration file loads with an invisible character glued to the first key. The file looks perfect in every editor you open it in, because the character has no width and no glyph.
This guide covers what the mark is, what to do about one at the start of a file as opposed to one in the middle, and how to save a file back without it. It all happens in Note My on your own Mac: no account, nothing uploaded, and the file never leaves the machine.
What a byte order mark is
The mark is a single Unicode character, U+FEFF, written at offset zero to tell a reader which encoding and byte order follow. In UTF-16 it is genuinely useful: without it, a reader cannot know whether the bytes are little-endian or big-endian. In UTF-8 there is no byte order to signal, so the mark carries no information and exists only as a hint that the file is UTF-8 at all. That hint is why it keeps appearing, and why so many tools that read UTF-8 without expecting it fail on the first line.
Because U+FEFF is zero-width, it is also a character that can end up anywhere. Concatenate two files and you get a mark in the middle of the result. Paste from a source that carried one and you get a mark inside a line. Those two cases take different fixes — one is about how the file is saved, the other about what is in the text — and telling them apart is the first thing to do before you go hunting for the character.
A mark at the very start needs a different fix
In the cleanup tools, U+FEFF appears under Zero-width characters, alongside U+200B, U+200C, U+200D, U+2060 and U+180E. Those characters are safe to take out wherever they appear, and our cleanup rules remove them under all four presets — Safe, Code-safe, Prose and Aggressive.
A U+FEFF sitting at the very start of the file is treated differently, and that is the case which matters here. In that position the character is not junk: it is the file's declared encoding marker, and an editor that quietly rewrote it would be changing how everything else on your Mac reads the file. So the leading mark stays exactly as you found it until you say otherwise, and Note My hands you a separate, explicit control for it — the encoding menu, described a few sections below. You decide, and the file does what you decided.
This is the fact that decides which tool you need. A leading BOM is an encoding problem and is fixed by saving in a different encoding. A U+FEFF anywhere else is a character problem and is fixed by the cleanup tools.
A mark anywhere else is junk you can remove
Move that same character one position to the right and Note My reports it. Everything below applies to a mark that is not at the very start of the file.
Our hidden-character scanner tells you about it through a pill in the status bar, so a stray mark reaches you without your having to go looking. The pill stays hidden when there is nothing to say, shows Clean in green when there is nothing to report, and switches to an orange "N hidden" or a red "N hidden · D risky" when it does. A stray zero-width character puts a count in that pill.
Click the pill and the popover offers Show in Text, Remove Invisible Character(s) and Review All…, plus Go to Next whenever there are findings to step through. Remove Invisible Character(s) is offered for the characters that are safe to take out anywhere, and a stray U+FEFF is one of those, so that single button clears it. One ⌘Z puts back everything the pass removed.
The same popover carries two switches — Protect Strings & Comments and Check While Typing — and both keep the popover open when you flip them. Protection is there to leave deliberate characters inside quoted text and comments alone. It never hides a zero-width character from you, so it will not stand between you and a stray mark.
Checking a very long document end to end
Our large-file engine keeps very long documents quick to open and edit, and when you want a definitive answer across one of them, the Review All sheet is where to get it: it covers a whole document however long it is, and lays out every finding for you to read before anything changes.
Open it from Clean ▸ Clean Invisible / Special Characters… in the toolbar's Clean menu. Set the scope to Whole Document, pick a preset, and press Scan. The left table lists every category with a checkbox, a severity chip and a count, so you can narrow the pass. The right table lists the findings themselves as Line:Col · Code Point · Category · Action · Risk, so you can read the code point and confirm you are looking at FEFF rather than another zero-width character. Double-click a finding to reveal it in the editor; Apply (N) in the footer performs the removals.
Clean ▸ Find Next Hidden Character and Clean ▸ Find Previous Hidden Character step through the findings in the editor, wrapping around and beeping when there is nothing left to find. The Clean menu keeps both to hand, and Go to Next in the status-pill popover walks the same findings straight from the pill, so you can work whichever way suits the document in front of you.
Seeing the character for yourself
A zero-width character has no glyph of its own, so Note My gives it one and the character stops being invisible. Zero-width characters, bidi controls, control characters, soft hyphens and the line and paragraph separators each get a slug marker, while the space family gets a background tint and trailing whitespace gets a bar, which is enough to tell them apart at a glance. Show in Text in the status-pill popover pulses the markers so you can find them, then settles them at a lower emphasis so they stay visible without nagging. With Reduce Motion on there is no pulse; the markers simply appear.
The toolbar's Show Invisibles toggle is the companion to this. It draws spaces, tabs and line endings, so it is the one to reach for when you are reading indentation or chasing trailing whitespace. For a zero-width character such as U+FEFF, the markers described above are the ones that show you where it sits.
Saving the file without a byte order mark
A leading mark is part of the file's encoding, and the way to remove it is to write the file in an encoding that does not have one. Our encoding handling lists "UTF-8" and "UTF-8 with BOM" as two separate choices among the eighteen encodings it offers, which is exactly the distinction you need here: you choose the one you want, explicitly.
-
Check what the file is in now
Open the encoding pill in the status bar, or the File ▸ Encoding menu. Both start from the same frequent set — UTF-8, UTF-8 with BOM, UTF-16 LE BOM, UTF-16 BE BOM, Windows-1252, ISO-8859-1 and Mac Roman. In the menu, the rest live behind Other Encodings…; the pill shows a Frequent section followed by one section per group.
-
Choose Convert to Encoding…
Pick File ▸ Encoding ▸ Convert to Encoding… and select plain UTF-8. Convert re-encodes the text you currently have and changes what will be written to disk. That is the operation you want: the characters stay as they are, the mark stops being written.
-
Save
Press ⌘S. The conversion changes what gets written, so nothing on disk moves until you save. A toast confirms the encoding change as you make it.
-
Check the result
Reopen the encoding menu and confirm the document now reads as UTF-8 rather than UTF-8 with BOM. If a stray U+FEFF has also worked its way into the body of the file, the status pill will still be reporting it — that one is a character, and it needs the cleanup pass described above.
Do both checks even when you are sure what the file is: step four catches a file with trouble in both places at once, which is common in anything assembled from several sources.
Reload with Encoding is the opposite operation
The Encoding menu holds two commands that sound similar and do opposite things, and choosing the wrong one is the most common way to make this worse.
| Command | What it does | Use it when |
|---|---|---|
| Reload with Encoding… | Re-decodes the bytes already on disk using a different encoding. The file is untouched; your reading of it changes. | The text looks garbled, because the file was decoded wrongly when it opened. |
| Convert to Encoding… | Re-encodes the text you have. What gets written to disk changes. | The text is correct and you want it saved differently — including without a BOM. |
If a file arrives with mojibake — accented characters replaced by pairs of odd symbols — reload first, in the encoding the file was actually written in, and only then convert. Converting garbled text just writes the garble down in a new encoding.
Adding a mark on purpose
Sometimes you need the opposite. A tool on the other side of a handoff may require a UTF-8 file to be marked, and UTF-16 files are usually expected to carry one. The route is the same: File ▸ Encoding ▸ Convert to Encoding…, then UTF-8 with BOM, or one of the marked UTF-16 or UTF-32 variants. All ten Unicode encodings are listed, with and without a mark, so you are choosing rather than guessing.
The preserve-BOM setting
Settings has an Encoding pane with four preferences: the default encoding for new files, the encoding to use for older non-Unicode text, whether to warn you when a file looks binary, and preserve BOM. New files default to UTF-8, the legacy encoding is Windows-1252, the binary warning is on, and preserve BOM is on.
With it on, a file that arrived marked stays marked when you save it. That is the right default — editing someone's file should not silently change how every other tool reads it — and it makes your ordinary saves entirely predictable: fix a typo in a marked file, press ⌘S, and the file comes back exactly as it went in, bar your typo. When you do want the mark gone, Convert to Encoding… is how you say so, and the choice holds from that save onwards.
Troubleshooting
The status pill says Clean but my parser still fails on line 1
That is the leading mark, which is an encoding matter rather than a character one. Use File ▸ Encoding ▸ Convert to Encoding…, choose plain UTF-8, and save. Your shebang or your first key is then the first thing in the file, and the parser reads line 1 the way it was always meant to.
I removed the character but it came back on the next save
If you deleted a leading mark by hand while the document's encoding is still UTF-8 with BOM, saving writes one back — that is what the encoding is. Change the encoding rather than the characters.
I want to be certain a very large file is clean
Run Clean ▸ Clean Invisible / Special Characters… with the scope set to Whole Document. That sheet covers the document end to end whatever its size, and the findings table gives you the code point for every hit, so you can confirm what you are looking at before you apply anything.
I want to see exactly where each U+FEFF sits
The cleanup pass is the instrument for a character with no glyph. It lists every finding as Line:Col · Code Point · Category · Action · Risk, so you can read FEFF off the row and tell it apart from another zero-width character, and a double-click reveals that finding in the editor. Show in Text then keeps the markers visible while you work through the file.
The file has marks in several places
Concatenated files do this. Scan the whole document in the Review All sheet, check the Zero-width characters row, and press Apply (N) — it removes every finding in the enabled categories in one pass, and one undo puts them all back. Then convert the encoding to plain UTF-8, which settles the mark at the very start of the file, and one save clears both at once.
Working through a set of files
A byte order mark rarely arrives on its own. One exporter, one handoff, one repository cloned from a Windows machine, and the same three bytes are sitting at the front of a dozen files. The work goes quickly once you scope it first and then convert with intent.
- Survey the directory first. Find in Folder searches every text file under a folder for the text you give it, which is a fast way to gather the files that belong to the same job — one build's output, one project's configuration. It only ever reads; nothing is written, so looking around costs you nothing.
- Open the set in tabs. Double-click a result to open that file at the line it was found on, or select the files in the Finder and drag them onto the tab bar, where each one lands in its own tab. Then move along the row and give each document the same treatment: read the encoding pill, convert, ⌘S, next. The pill sits in the status bar of whichever tab is in front, which makes each file a two-click job.
- Decide what you write next. The Encoding pane in Settings sets the encoding new files are created in. Leave it at UTF-8 and everything you start in Note My is unmarked from the first keystroke, so the problem stops arriving from your end.
- Read the bytes when you want proof. The Bytes marker style in Show Invisibles renders hex bytes in the document's own encoding, which is a direct look at what your whitespace and line endings really are — useful when a file has been through several hands and you want to see rather than assume.
- Keep the safety net under you. Every cleanup pass is a single undo away, and ⌘Z puts back everything one pass removed. An encoding choice changes only what will be written, so until you press ⌘S the file on disk is exactly as it was, and you are free to pick a different one and look again.
- It all happens on your Mac. Every scan and conversion described here runs locally: no account, no sign-in, nothing uploaded, and the file never leaves the machine.
Frequently asked questions
Does a UTF-8 file need a byte order mark?
Plain UTF-8 is the safer choice for anything headed into a shell script, a parser or a build system. UTF-8 has no byte order to signal, so the mark is only ever a hint that the file is UTF-8, and many tools read it as a stray character instead. Note My lists both forms in the encoding menu, so you can pick the one the receiving tool expects and know which you have chosen.
What happens to the mark at the very start of my file?
It stays exactly where it is until you decide otherwise. In that position the mark is the file's encoding marker rather than junk, and changing it quietly would change how every other tool on your Mac reads the file — so it is handled through the encoding menu, where the choice is yours and explicit. Anywhere else in the document a U+FEFF is reported as a zero-width character and removed with one click.
What is the difference between Reload with Encoding and Convert to Encoding?
They are opposites. Reload re-decodes the bytes already on disk using a different encoding, which fixes a file that was read wrongly. Convert re-encodes the text you have, which changes what gets written when you save.
How do I work through a folder of files that all carry a mark?
Work along the tab bar. Find in Folder shows you which files belong to the same job and opens the one you double-click at the line it matched; a selection dragged in from the Finder lands each file in its own tab. Every tab then gets the same short treatment: read the encoding pill, convert to plain UTF-8, ⌘S, next. Because encoding conversion and the cleanup pass both act on the document in front of you, you see each result before you move on, and a file that also has a stray U+FEFF in its body is dealt with in the same visit.
Will converting the encoding change my text?
Converting re-encodes the characters you have. Between UTF-8 and UTF-8 with BOM nothing changes except the mark, so the round trip is a safe one to make. If you are moving to one of the legacy encodings instead, read the document over first — the Unicode encodings carry the widest range of characters, and the encoding menu keeps all ten of them to hand if you would rather stay there.
Which cleanup preset removes zero-width characters?
All four. Zero-width characters are removed under Safe, Code-safe, Prose and Aggressive alike, so pick the preset that suits the rest of the file. Code-safe is the default.