aitextcleaner.top

Remove Non-ASCII Characters from Text

Paste any text below and click the button. Every character above code point 0x7F — Chinese, Japanese, Arabic, accented letters, emoji, full-width punctuation, and invisible zero-width characters — is deleted. Only the original 128 ASCII characters survive.

0 characters

When you actually need to strip non-ASCII

The most common trigger is an older API or database column that was built with the assumption that all input fits inside a single ASCII byte. Legacy SMTP servers, for example, historically required 7-bit clean message bodies. Feed one a UTF-8 string containing a single em dash and it silently mangles the message or bounces it. The fix is to strip non-ASCII before the content touches the server, not after you get an error report from a customer.

CSV imports into systems like older versions of MySQL or Oracle forms are another recurring pain point. A spreadsheet exported from Google Sheets can contain Unicode no-break spaces (U+00A0) that look identical to regular spaces but cause numeric columns to fail validation. One data-entry analyst I know spent two hours chasing a "value too long" error in a VARCHAR(50) column before realising a copied-and-pasted address contained a left double quotation mark (U+201C) adding two extra bytes in UTF-8. Running the text through this tool first would have taken 3 seconds.

Log parsing is a third scenario. When your grep or awk pipeline hits a line containing a Chinese product name or a Japanese user-agent string, the regex often fails in ways that are genuinely hard to debug — especially if the encoding assumption baked into the script predates Unicode. Normalising log excerpts to pure ASCII before you paste them into a shell script is faster than auditing 400 lines of sed.

ASCII versus Unicode: the 128-character boundary

ASCII was finalised in 1963 and defines 128 characters numbered 0 through 127 (0x00 through 0x7F in hex). It covers the English alphabet, digits 0–9, 32 punctuation and symbol characters, and 33 non-printing control codes including tab (0x09), newline (0x0A), and carriage return (0x0D). Everything fits in 7 bits, which is why old transmission systems used the 8th bit as a parity check.

Unicode extends this to over 149,000 characters as of version 15.1, organised into 17 planes each holding 65,536 code points. The first 128 positions in Unicode are identical to ASCII, which is why UTF-8 — the dominant web encoding — is backward compatible: a pure-ASCII document has the same byte representation in both. The misunderstanding worth clearing up is that "non-ASCII" does not mean "invalid" or "corrupted." U+00E9 (é) is a perfectly valid Unicode character. It is simply outside the ASCII subset, which is the only thing this tool checks.

UTF-8 encodes code points above 0x7F using 2, 3, or 4 bytes. An emoji like 😀 occupies 4 bytes. A French é occupies 2 bytes. When a system announces a VARCHAR(100) limit, that limit is usually in bytes, not characters. A 25-character French phrase can quietly exceed a 50-byte column. Stripping non-ASCII eliminates that category of overflow entirely because every remaining character is exactly 1 byte in UTF-8.

Accented letters and ligatures: delete vs. transliterate

For accented Latin characters, there are two philosophically different approaches. Deletion removes the character entirely: "café" becomes "caf". Transliteration converts it to its nearest ASCII equivalent: "café" becomes "cafe". This tool does the former. If you want transliteration, you need a library like Python's unidecode or the ICU transliterator. The distinction matters when the output will be read by a human rather than parsed by a machine. A URL slug generator almost always wants "cafe"; a log-cleaning script usually just wants the non-ASCII bytes gone.

Ligatures complicate things further. The fi ligature (U+FB01) looks like two letters but is a single code point. Remove it and you get an empty slot where "fi" used to be. That can split words in PDF-extracted text in awkward ways: "office" becomes "o ce" if the PDF renderer stored the word using the ligature. If your input comes from a PDF parser, consider running NFC normalisation first — NFC will not decompose ligatures (that is NFD's job), but it will precompose base+combining pairs, which makes the ASCII/non-ASCII boundary cleaner for the ligatures that do have ASCII equivalents.

Unicode normalisation forms also affect whether you see one code point or two for a character like é. In NFD, é is stored as U+0065 (e) plus U+0301 (combining acute accent). The base letter is ASCII; the combining mark is not. After non-ASCII removal you are left with a bare "e", which may or may not be what you wanted. Normalize to NFC before pasting here if you want consistent behaviour: NFC merges the pair into U+00E9, which then gets removed as a unit, leaving nothing.

CJK users: this tool will delete your sentences, not convert them

Chinese, Japanese, and Korean characters all sit in Unicode ranges far above 0x7F. A three-character Chinese title like "北京市" (Beijing) occupies code points U+5317, U+4EAC, and U+5E02 — none of which have ASCII equivalents. After non-ASCII removal, the entire string is gone. There is no romanisation output, no pinyin, no rōmaji. If your document is primarily CJK text, running it through this tool will produce a near-empty result. The tool was built for situations where CJK characters are unwanted noise in an otherwise ASCII data stream, not for translating East Asian content to Latin script.

Full-width punctuation is a related gotcha. Japanese text commonly uses U+FF0C (,, full-width comma) and U+3002 (。, ideographic full stop) instead of their ASCII counterparts. Korean documents sometimes mix hangul with full-width digits U+FF10–U+FF19. All of these look like ordinary punctuation on screen but are non-ASCII and will be deleted. If you only want to clean up a mixed English/Japanese document and keep the English parts intact, this is the right tool. If you want to preserve the Japanese portions while only removing, say, emoji, use a more targeted approach.

For developers building pipelines that must accept CJK input: the usual approach is not stripping non-ASCII but rather ensuring the database column uses utf8mb4 (not the misnamed utf8 in MySQL, which only covers 3-byte sequences and will drop emoji). The non-ASCII remover is appropriate as a last-resort sanitiser for legacy systems that truly cannot be upgraded to support Unicode.

Zero-width characters and full-width punctuation as invisible bugs

Zero-width space (U+200B) and the byte-order mark U+FEFF are the two characters most likely to cause production incidents that take hours to diagnose. U+200B is inserted by some word processors and rich-text editors at word boundaries; it is completely invisible in most fonts. U+FEFF was originally used as a byte-order mark at the start of UTF-16 files; it shows up in UTF-8 files as the three-byte sequence 0xEF 0xBB 0xBF and is invisible in most editors but causes JSON.parse to throw in Node.js, Python's json module to fail, and XML parsers to reject the document as malformed.

Zero-width joiner (U+200D) and zero-width non-joiner (U+200C) are used in Arabic and some Indic scripts to control ligature formation. They also appear in emoji sequences: the family emoji 👪 is actually five code points joined by three U+200D characters. If you paste that emoji into a field and it stores correctly but retrieves with a length of 8 instead of 1, you have hit the surrogate-pair plus ZWJ counting issue. Non-ASCII removal clears all of these in one pass.

Full-width digits and letters (U+FF01–U+FF5E) are another category that hides in plain sight. They look indistinguishable from normal ASCII in many fonts. A full-width "A" (U+FF21) will not match a regex looking for [A-Z] and will not sort correctly in an ASCII-aware collation. A product SKU containing a full-width digit will not match the warehouse system's lookup table. Removing all non-ASCII is the blunt solution; using a Unicode-aware collation and the NFKC normalisation form (which maps full-width characters to their ASCII counterparts) is the precise one.

Emoji, surrogate pairs, and why character counts go wrong

Emoji mostly live in the range U+1F300–U+1FAFF, which requires 4 bytes in UTF-8 and two code units in UTF-16 (a "surrogate pair"). JavaScript strings are internally UTF-16, so string.length counts UTF-16 code units, not Unicode scalar values. The smiling face 😀 (U+1F600) has a .length of 2 in JavaScript, not 1. This is why a 140-character tweet that contains 5 emoji reports a .length of 150 in JavaScript. The Twitter API itself historically counted emoji as 2 characters for exactly this reason, though it has since moved to grapheme-cluster counting.

After you remove all non-ASCII characters with this tool, every remaining character is in the range 0x00–0x7F, which means each code point is exactly 1 byte in UTF-8 and exactly 1 code unit in UTF-16. Character count equals byte count equals .length. That predictability is often the entire point of the operation. A database column VARCHAR(255) in latin1 encoding holds exactly 255 characters; once the text is pure ASCII you can trust .length to tell you whether it fits.

If you want to preserve emoji but remove accents, or remove zero-width characters but keep everything else, this is not the right tool — the operation here is binary: inside 0x00–0x7F stays, everything else goes. For surgical removal of specific character categories, see the dedicated tools below for removing emoji, stripping zero-width characters, or removing accents only. Use non-ASCII removal when you need the strictest possible guarantee: every byte in the output is 7-bit clean.

Real pipeline failures traced to a single non-ASCII byte

Three categories of production incidents appear again and again once teams finally trace a bug back to a character encoding problem.

JSON rejection is the first. Python's json module throws a JSONDecodeError when a file opens with the three bytes 0xEF 0xBB 0xBF — the UTF-8 byte-order mark inserted by Windows Notepad and some Excel CSV exports. That BOM sits before the opening brace of the JSON, which makes the parser see an invalid token immediately. The BOM is U+FEFF, above 0x7F, so it disappears when you run the text through a non-ASCII strip. The same fix resolves XML parsers that reject documents as "not well-formed" due to a leading BOM: the bytes are valid UTF-8 for U+FEFF but illegal before the XML declaration.

Database column truncation is the second category. MySQL's three-byte utf8 character set (as opposed to utf8mb4) silently drops any character that requires 4 bytes — specifically emoji in the U+1F000 plane and higher. A display name containing a single flag emoji gets stored as an empty string or truncated without error, depending on the sql_mode setting. Stripping non-ASCII before the INSERT prevents silent data loss in systems that cannot be migrated to utf8mb4 right now. The character count in the stored row will still differ from the original, but at least the row is not corrupted mid-sequence.

Shell script matching failures are the third. Bash's case statements and string comparisons behave correctly with ASCII, but pipe a string containing U+2019 (right single quotation mark) into a pattern match and it silently fails. A monitoring script that parsed customer-reported error messages missed roughly 8% of cases after one customer copied text from a Word document that auto-corrected straight quotes to curly ones. Adding a non-ASCII strip at the top of the input parsing function brought the miss rate to zero, with no other code changes required. The curly quote and the straight quote look identical in most terminal fonts, which is why the bug took three weeks to surface.

Five mistakes people make when stripping non-ASCII

Stripping at the byte level instead of the character level is the most destructive error. Non-ASCII removal must happen after bytes have been decoded into Unicode characters. If you remove any byte above 0x7F from raw UTF-8 data, you corrupt multi-byte sequences: the leading byte of a 2-byte sequence is in the range 0xC0–0xDF, so it gets deleted, but the continuation byte (0x80–0xBF) stays, producing malformed UTF-8 that downstream parsers reject. Always decode to a Unicode string first, strip non-ASCII code points, then re-encode to bytes if needed.

Assuming the output is HTML-safe without further escaping is the second mistake. After non-ASCII removal the string is pure ASCII, but it may still contain angle brackets, ampersands, and quote characters that require HTML escaping. Non-ASCII removal does not sanitise for injection. Run HTML escaping as a separate step if the output goes into an attribute or innerHTML.

Forgetting that tabs and newlines are ASCII is a small but common surprise. Code points 0x09 (tab), 0x0A (line feed), and 0x0D (carriage return) are below 0x7F and survive non-ASCII removal intact. If you also need to normalise line endings or collapse tabs, those operations must be added separately — this tool does not touch them.

Using non-ASCII removal as a security filter is a category error. An attacker can construct effective SQL injection, XSS, and path traversal payloads entirely from ASCII characters. This tool changes the shape of data; it does not validate intent. Always combine it with parameterised queries, output encoding, and proper input validation. Treating this as a security step gives a false sense of protection.

Running the tool on binary files is the fifth pitfall. PDF, ZIP, and DOCX files opened as text appear to contain mostly non-ASCII because their binary structure — magic bytes, internal offsets, compressed payload — consists almost entirely of bytes above 0x7F. Passing such content through a non-ASCII strip destroys the file structure, producing output that no reader can open. Only apply non-ASCII removal to genuine text content, not to binary data read as a string.

Frequently Asked Questions

▸What exactly counts as a non-ASCII character?

ASCII covers exactly 128 code points: 0x00 through 0x7F. That range includes the 26 English letters (upper and lower), the 10 digits, common punctuation like ! @ # $ % ^ &, and control characters like tab and newline. Everything else — accented vowels, Chinese characters, emoji, the em dash, the degree sign ° — sits above 0x7F and is therefore non-ASCII. Unicode contains over 149,000 such code points as of version 15.1.

▸Will this tool turn Chinese text into pinyin?

No. Non-ASCII removal deletes characters outright; it does not transliterate them. A Chinese sentence like “今天天气很好” becomes an empty string, not “jīntĪn tiānqì hěn hǎo”. If you need the Latin-alphabet equivalent of CJK text, you want a transliteration tool, not this one. This tool is for pipelines that only need to guarantee every byte is in the range 0–27F.

▸Why does my character count shrink by more than the number of emoji I pasted?

Most emoji use two UTF-16 code units (a surrogate pair). JavaScript’s .length counts code units, not characters, so a single emoji like 😀 reports as length 2. After removal the count drops by 2 per emoji, which looks surprising if you expected a 1-for-1 drop. The actual output is still correct: every non-ASCII byte is gone. If you need accurate character counts, use a library that handles Unicode scalar values rather than raw .length.

▸How do I remove non-ASCII in Python?

The one-liner is: cleaned = text.encode('ascii', errors='ignore').decode('ascii'). It encodes to bytes, silently drops anything that won’t fit in 7-bit ASCII, then decodes back to a string. If you want to keep certain high-code-point characters (like the copyright sign ©), use a regex instead: import re; cleaned = re.sub(r'[^\x00-\x7F]', '', text).

▸What about zero-width characters — are they non-ASCII?

Yes. Zero-width space (U+200B), zero-width no-break space (U+FEFF), and the zero-width joiner (U+200D) all sit well above 0x7F. This tool removes them along with every other non-ASCII code point. If you only want to target invisible characters and leave accented letters intact, use a dedicated zero-width character remover instead.

▸Does the tool handle NFD-composed characters correctly?

Text in NFD form splits characters like é into a base letter e (U+0065, ASCII) plus a combining accent (U+0301, non-ASCII). After non-ASCII removal you get a bare e with no accent — which looks correct but is actually a side-effect of the decomposition. To avoid that, normalize your text to NFC before running the tool. NFC recombines the base letter and the accent into the single precomposed code point é (U+00E9), which is then removed as one unit, leaving nothing rather than a bare e.

▸How do I strip non-ASCII characters in JavaScript or Node.js?

The cleanest approach in both environments is the regex: cleaned = text.replace(/[^\x00-\x7F]/g, ''). The character class [^\x00-\x7F] matches any code point outside the ASCII range; the g flag replaces all occurrences rather than just the first. An alternative sometimes suggested is Buffer.from(text, 'ascii').toString('ascii'), but this substitutes unrecognised bytes with ? instead of removing them entirely, producing different output. The regex is the safer choice when 'delete, not substitute' is the requirement. For TypeScript projects the same regex works unchanged because TypeScript strings are UTF-16 at runtime, identical to plain JavaScript.

▸Will non-ASCII removal break URLs or HTML entities in my text?

Percent-encoded URLs are safe: the encoding uses only ASCII characters (hexadecimal digits and the percent sign), so a URL like https://example.com/caf%C3%A9 survives intact. However, a URL containing raw unencoded non-ASCII bytes — technically invalid per RFC 3986 but accepted by most browsers — will have those characters stripped, producing a broken link. HTML named entities like é and & are sequences of ASCII characters and are not affected. What does get removed is the actual UTF-8 character if someone pasted a raw é directly into the HTML source instead of using the entity. If you are cleaning HTML, check whether the source uses entity encoding or raw Unicode before running the tool.

▸The character count changed but the text looks identical — what happened?

The most likely cause is invisible non-ASCII characters. Zero-width space (U+200B), left-to-right mark (U+200E), and soft hyphen (U+00AD) produce no visible glyph in most fonts. They are nonetheless present in the string and above 0x7F, so they are removed. A second possibility is that your display font substitutes a visually similar ASCII glyph for the non-ASCII character — for example, rendering a curly apostrophe (U+2019) as an identical-looking straight one. The screen shows no change, but the underlying bytes differ. Comparing the raw byte count before and after is the reliable way to confirm the operation ran.