Skip to content
Ghostchars

Guide

Find hidden characters in VS Code

Turn on Unicode highlighting, search zero-width codepoints with an escaped regex, and clean the file before an invisible byte breaks a build or pollutes a diff.

By Kris Vinters · Published · 3 minute read

Use VS Code Unicode highlighting first

Open Settings and search for Unicode Highlight. VS Code groups warnings into invisible characters, ambiguous characters, and non-basic ASCII characters. Hover a highlight to see why the editor marked it. Defaults can depend on workspace trust, comments, strings, fonts, and allowed locales, so inspect the effective settings for the workspace you are reviewing.

The three main settings control the classes separately. Turn on the class you need instead of treating all Unicode as an error. Non-ASCII letters are legitimate in localized source, names, and test fixtures; invisible format characters deserve a narrower review.

  • editor.unicodeHighlight.invisibleCharacters
  • editor.unicodeHighlight.ambiguousCharacters
  • editor.unicodeHighlight.nonBasicASCII

Unicode highlighting is a review aid, not an exhaustive security scan. VS Code documents the ambiguous class as heuristic, and locale or font choices affect what appears suspicious.

Search the file with an escaped regex

Open Find, turn on regular-expression search, and enter the escaped pattern shown here. It contains printable ASCII only, but it searches for U+200B through U+200D and U+FEFF. Review each match in context before replacing it.

Regex: [\u200B-\u200D\uFEFF]

That range covers zero-width space, zero-width non-joiner, zero-width joiner, and the byte-order mark character when it appears in text. Search for \u2060 separately when you also need WORD JOINER. Do not delete a joiner automatically inside emoji or a joining script, where it can be load-bearing.

Hidden characters can split an identifier, make two keys compare unequal, defeat an exact search, alter a parser token, or produce a diff on a line that looks unchanged. A leading byte-order mark can also matter differently from the same codepoint embedded in the middle of a file, so check position as well as name.

U+200B ZERO WIDTH SPACEU+200D ZERO WIDTH JOINERU+FEFF ZERO WIDTH NO-BREAK SPACEU+2060 WORD JOINER

Clean the whole text, then inspect the findings

For a text file, select all, copy it into the cleaner, and review the findings before copying the clean version back. The standard pass removes free-floating zero-width characters, but keeps a joiner when the engine sees it doing real work in emoji or a joining script.

For a supported .html file, or for .docx and .odt documents stored beside a project, use the document report to inspect the whole file in the browser. It does not accept arbitrary source formats, so use the pasted-text cleaner for source such as .js, .ts, .json, or .md.

Open the zero-width character cleanerOpen the document report

A hidden character can explain a build or diff failure. It cannot explain who wrote the surrounding code or prose. The cleaner reports and changes codepoints; the prose report returns measurements without an authorship verdict.

VS Code hidden-character questions

Does VS Code highlight every invisible character by default?

No single promise covers every workspace. Defaults and exceptions can depend on workspace trust, comments, strings, allowed characters, and locales. Search Settings for Unicode Highlight and inspect the effective values.

Does the regex find every hidden Unicode character?

No. It targets U+200B through U+200D and U+FEFF. Add codepoints such as \u2060 for WORD JOINER, or use the cleaner to scan the broader character table.

Why can one zero-width character break a build?

Parsers, identifiers, checksums, and exact comparisons operate on codepoints, not on what the glyph looks like. An invisible codepoint can split a token or make two visually identical strings unequal.

Continue with all practical guides to hidden characters and the limits of cleaning.

Anonymous usage stats?

Ghostchars processes your text in the browser and never uploads it. We would like to count page views with a self-hosted, cookie-light analytics endpoint. No content, ever.