Find non-ASCII characters
Detect accented letters, emoji, or other non-ASCII characters hiding in a file — useful for encoding and i18n checks.
Last updated
Matches
- Café résumé
- Price: 100€
Doesn’t match
- Plain ASCII text only
- 1234 Main Street, USA
Why it’s written this way
\x00-\x7F covers every code point from 0 to 127, the full 7-bit ASCII range, so the negated class [^\x00-\x7F] matches any single character that falls outside it, one code unit at a time.
Matching per character rather than per grapheme makes this a fast way to flag the presence of non-ASCII content in a file without pulling in a full Unicode-aware library.
Edge cases to know
- →Many emoji and other characters outside the Basic Multilingual Plane are stored as two UTF-16 code units, a surrogate pair, so this pattern reports two matches for what looks like one character on screen.
- →It flags legitimate content just as readily as mistakes — accented names, currency symbols, and curly quotes are all 'non-ASCII' even though they're perfectly valid text.
- →It says nothing about which script or character is present, only that something outside ASCII exists at that position.
Part by part
- [^\x00-\x7F]
- A negated class covering everything outside the ASCII range. The escapes are hexadecimal code points: 00 is null and 7F is the last ASCII character.
Common mistakes
[^\x00-\xFF]Extending the range to FF makes it Latin-1 rather than ASCII, so accented Western European characters are treated as safe. That is a defensible choice, but it is not what "non-ASCII" means.
[\x80-\xFF]A positive range for the high half of a byte only finds characters in that narrow band, missing everything above it — which is most of unicode, including emoji and every non-Latin script.
[^a-zA-Z0-9]Excluding only alphanumerics flags every space, comma and full stop as non-ASCII. It is a common substitution and it makes the results useless on ordinary prose.
Questions
Why look for non-ASCII characters at all?
Usually to find things that will break elsewhere: a smart quote pasted from a word processor into code, a non-breaking space that looks identical to a normal one, or a look-alike character in a domain name.
Does it match emoji correctly?
It matches them, but an emoji outside the basic plane is two UTF-16 units, so it registers as two matches without the u flag. Add u to treat each code point as one unit.
Is a non-ASCII character a problem?
Not in itself — most of the world's text is non-ASCII and perfectly correct. It is a flag for review rather than a fault, which matters most in identifiers, filenames and code where the surrounding system may assume ASCII.
How do I find only the invisible ones?
Those are a small, specific set — zero-width spaces, joiners and directional marks — rather than everything non-ASCII. The character-inspector tool on this site names each one it finds, which is more useful than a raw match.
Why does the count differ between my editor and my script?
Almost always because one is counting code points and the other UTF-16 units. A character outside the basic plane, such as most emoji, is one code point but two units, so a naive length check reports two where a person sees one. Add the u flag to make the pattern count the way a reader does.