This page is a code-point lookup and detection reference. If you first need to decide whether a gap controls width, wrapping, indentation or line structure, start with the practical Unicode whitespace guide.

Whitespace is a category, not a single character

In everyday use the word space covers dozens of distinct code points. The Unicode Character Database marks a set of them with the White_Space property, and text specifications such as the WHATWG Infra Standard define a much narrower "ASCII whitespace" set of five characters. A tool, a programming language, and a layout engine can each use a different definition, which is why text can still look wrong after you believe every space has been removed.

Two properties matter for cleanup. The first is visible width: does the character draw a gap, and how wide. The second is line-break behavior: does the character allow, forbid, or force a wrap at that point. The line-breaking algorithm is specified in Unicode Standard Annex #14. A non-breaking space has the width of a normal space but forbids a wrap; a zero-width space has no width but permits one. Knowing both properties tells you whether to convert a character to a plain space or delete it.

Horizontal space characters

These characters separate words or align text within a line. They never start a new line.

Code pointNameWidthWrapTypical source
U+0020SpaceOne spaceAllowedThe spacebar; almost every text source.
U+0009Character Tabulation (Tab)To next tab stopAllowedCode indentation, TSV files, aligned plain text.
U+00A0No-Break Space (NBSP)One spaceForbiddenHTML  , word processors, pasted web text.
U+202FNarrow No-Break SpaceNarrowForbiddenFrench punctuation spacing, clock times, some currencies.
U+2007Figure SpaceWidth of a digitForbiddenPadding numbers so columns of figures align.
U+2009Thin SpaceThinAllowedTypographic spacing around punctuation and units.
U+2002 / U+2003En Space / Em SpaceHalf em / one emAllowedTypesetting, pasted design or publishing content.
U+3000Ideographic SpaceFull widthAllowedCJK text, full-width form input, indented Asian prose.
U+00ADSoft HyphenZero unless line breaksBreak opportunityWord processors and CMS hyphenation; not whitespace, but often found beside it.

Tab, line-ending, and separator characters

These characters control vertical structure. Removing or converting them changes how many lines the text has.

Code pointNameEscapeTypical source
U+000ALine Feed (LF)\nUnix, Linux, modern macOS, most programming output.
U+000D U+000ACarriage Return + Line Feed (CRLF)\r\nWindows text files, HTTP headers, many network formats.
U+000DCarriage Return (CR)\rClassic Mac OS files, some legacy exports.
U+000B / U+000CVertical Tab / Form Feed\v / \fOld print workflows, some PDF and RTF extraction.
U+0085Next Line (NEL)—EBCDIC-derived data, some mainframe exports.
U+2028 / U+2029Line Separator / Paragraph Separator—Text copied from design tools; can break JavaScript string parsing.

Zero-width and invisible format characters

These characters usually draw nothing. They are grouped with whitespace during diagnosis because they make two identical-looking strings behave differently, but several of them carry meaning and should not be deleted blindly.

Code pointNamePurposeSafe to delete?
U+200BZero Width SpaceMarks a wrap opportunity without drawing a gap.Usually yes in plain data; review long words and URLs.
U+FEFFByte Order Mark / Zero Width No-Break SpaceEncoding signature at the start of a file; legacy no-break joiner mid-text.Yes at the start of a file; check context mid-text.
U+2060Word JoinerForbids a wrap with no width; modern replacement for a mid-text BOM.Only if wrapping at that point is acceptable.
U+200CZero Width Non-Joiner (ZWNJ)Prevents letters from forming a ligature or joined form.No in Persian, Arabic, Indic scripts; changes spelling.
U+200DZero Width Joiner (ZWJ)Forces a joined form; builds many combined emoji.No; can break emoji and script rendering.

Because of the last two rows, a careful invisible-character cleanup separates U+200B and a stray U+FEFF, which are usually residue, from ZWNJ and ZWJ, which are usually intentional. The zero-width character remover offers a cautious mode that keeps the joining controls.

How these characters reach your text

  • PDF extraction preserves typographic spaces (thin, figure, narrow no-break) and inserts a line ending at every visual row, plus occasional form feeds between pages.
  • HTML and the web turn   into U+00A0, and copying rendered text keeps the Unicode character rather than the entity, as covered in the WHATWG named character reference. Cleaning the markup itself is a different task, covered in the HTML spaces guide.
  • Word processors auto-insert protected spacing around initials, units, and punctuation, and add soft hyphens during hyphenation.
  • Spreadsheets export CRLF line endings and can leave a leading BOM in the first cell of a CSV.
  • Chat and design tools sometimes emit U+2028 or zero-width characters that survive a copy and paste.
  • Input methods for CJK languages can produce full-width U+3000 instead of an ASCII space.

A detection checklist

  1. A short phrase overflows the right edge and never wraps: suspect U+00A0 or U+202F.
  2. An exact-match search or a database join fails on text that looks identical: suspect U+200B, U+FEFF, or a trailing regular space.
  3. Columns line up in one program and collapse in another: suspect U+0009 tabs.
  4. Every sentence sits on its own line: suspect hard LF or CRLF from a PDF or wrapped email.
  5. A script or parser throws an "unexpected token" or "unterminated string": suspect U+2028 or U+2029.
  6. To confirm, paste a small non-sensitive sample into a tool here and read the live audit, or list its characters by code point with the example below.

Inspect invisible characters by code point

JSON.stringify(text) escapes characters such as tabs and line feeds, but normally leaves NBSP, zero-width space, and U+FEFF as the original characters. It is not a general invisible-character detector. This complete JavaScript example lists zero-based code-point indices, U+ values, and names for those three target characters:

const text = 'A\u00A0B\u200BC\uFEFF'; const names = new Map([ [0x00A0, 'NO-BREAK SPACE'], [0x200B, 'ZERO WIDTH SPACE'], [0xFEFF, 'BOM / ZERO WIDTH NO-BREAK SPACE'] ]); const rows = Array.from(text, (character, index) => { const point = character.codePointAt(0); const code = 'U+' + point.toString(16).toUpperCase().padStart(4, '0'); return `${index}\t${code}\t${names.get(point) || 'other character'}`; }); console.log(rows.join('\n'));

Actual output (columns are separated by tabs):

0 U+0041 other character 1 U+00A0 NO-BREAK SPACE 2 U+0042 other character 3 U+200B ZERO WIDTH SPACE 4 U+0043 other character 5 U+FEFF BOM / ZERO WIDTH NO-BREAK SPACE

Array.from iterates by Unicode code point, so these indices are not UTF-16 code-unit offsets when supplementary characters such as many emoji are present. Every character receives a code point; “other character” means only that this small example has no name for it, not that it is safe or visible. U+FEFF at the end of this sample is a character inside the string, not a file-start BOM. Keep real confidential text out of shared consoles and reports, and review the character's purpose before changing it. The escaping behavior is specified in ECMAScript's JSON string serialization algorithm.

Which tool removes which character

CharactersTool
Repeated U+0020, tabs, and mixed Unicode spaces in a lineRemove Spaces
U+00A0, U+202F, U+2007Remove Non-Breaking Spaces
U+200B, U+200C, U+200D, U+2060, U+FEFFRemove Zero-Width Characters
U+0009 tabs (remove or expand)Remove or Expand Tabs
LF, CRLF, CR between content linesRemove Line Breaks
Whitespace-only linesRemove Empty Lines
Leading and trailing whitespace on each lineTrim Lines

For behavior-focused explanations rather than a character list, see the Unicode whitespace guide and Non Breaking Space. To compare this approach with writing code, read Browser Tool Versus Code Methods.