u'ufeff' in Python string
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
The character in a Python string is a Byte Order Mark (BOM). It appears when you read a file that was saved with UTF-8 BOM encoding, and Python decodes it using standard utf-8 instead of utf-8-sig. The fix is to use encoding="utf-8-sig" when opening the file, which strips the BOM automatically. If the string is already loaded, strip the leading character manually before processing.
What is the Byte Order Mark?
BOM (U+FEFF) is a Unicode character originally designed to indicate the byte order of a text stream. In UTF-16 and UTF-32, byte order matters because multi-byte integers can be stored in big-endian or little-endian format. BOM at the start of the stream tells the decoder which order to expect.
In UTF-8, byte order is irrelevant because UTF-8 encodes each byte independently. However, some tools still prepend a BOM to UTF-8 files as a signature to indicate that the file is UTF-8 encoded. Microsoft Notepad, Excel's CSV export, and many Windows applications do this by default.
The BOM in UTF-8 is the three-byte sequence EF BB BF. When Python decodes these bytes with the utf-8 codec, they become the single character in the resulting string.
Why BOM Causes Bugs
BOM is invisible in most displays but is a real character in the string. This breaks string comparisons, dictionary key lookups, CSV header parsing, and JSON processing.
In CSV processing, the BOM becomes part of the first column header. A column named name does not match "name" in a dictionary lookup, causing KeyError exceptions that are extremely difficult to debug because the header looks correct when printed.
Fix 1: Read Files with utf-8-sig Encoding
The utf-8-sig codec is specifically designed to handle BOM. It strips a leading BOM during decoding and is otherwise identical to utf-8. If no BOM is present, it behaves exactly like utf-8.
This is the cleanest solution. Apply utf-8-sig at the point where the file is first opened, and all downstream code receives clean text.
Fix 2: Strip BOM from In-Memory Strings
When you receive text from an API, message queue, or database where you cannot control the encoding parameter, strip the BOM after the fact:
Only strip from the start of the string. Using .replace("", "") globally can corrupt data in edge cases where U+FEFF appears as a zero-width no-break space within the text body (its secondary Unicode function).
Fix 3: Handle BOM in CSV Processing
CSV files from Excel are one of the most common sources of BOM issues. Here is a robust CSV reading pattern:
For pandas users, read_csv accepts an encoding parameter:
Fix 4: Handle BOM in JSON Processing
JSON files with BOM cause json.loads to fail in some Python versions:
The safest approach is always decoding bytes with utf-8-sig before passing the string to json.loads.
Detecting BOM in Files
Sometimes you need to check whether a file contains BOM before deciding how to process it:
This is useful in data pipelines where files come from multiple sources with inconsistent encoding practices.
Removing BOM from Files on Disk
If you want to permanently remove BOM from a file:
For a command-line approach:
Writing Files With or Without BOM
If you need to produce files with BOM for consumers that require it (such as Excel reading UTF-8 CSV files correctly on Windows):
Note that utf-8-sig also works for writing. It prepends the BOM bytes to the output.
Common Pitfalls
Using .replace("", "") globally. This removes every occurrence of U+FEFF in the string, not just the leading BOM. In Unicode, U+FEFF also serves as a zero-width no-break space, which can legitimately appear within text. Strip only the leading character.
Decoding bytes twice. If bytes pass through two decoding steps with different codecs, hidden characters can reappear. Decode once at the boundary, then work with strings throughout.
Assuming BOM only appears in files. Clipboard data, HTTP response bodies, database exports, and API payloads can all contain BOM. Any text crossing a system boundary should be treated as potentially BOM-prefixed.
Not including BOM in test fixtures. BOM bugs are invisible in development because developers typically create clean UTF-8 files. Add at least one test fixture that starts with b"\xef\xbb\xbf" to catch regressions in CSV, JSON, and configuration file parsers.
Forgetting the newline="" parameter with csv module. When opening files for the csv module, always pass newline="" to prevent double newline translation. This is unrelated to BOM but frequently co-occurs in CSV handling bugs.
Summary
is a Byte Order Mark (BOM) character. In UTF-8, it appears as the three-byte sequenceEF BB BF.- The primary fix is reading files with
encoding="utf-8-sig", which strips leading BOM automatically. - For in-memory strings, strip only the leading
character, never replace it globally. - CSV files from Excel and Windows tools are the most common source of BOM issues in Python.
- Use
utf-8-sigfor writing when you need BOM output (for example, CSV files that Excel must open correctly on Windows). - Add BOM-containing test fixtures to your test suite to catch encoding regressions early.

