disarm

Tools

Unicode text tools

Each tool is disarm itself, compiled to WebAssembly and run inside your browser. No text is uploaded, and every one of them reports precisely what it changed — because on hostile Unicode the before and after usually look identical.

Start from what went wrong

The cards below are organised by mechanism, which is useful once you know what you are looking at. Most people arrive knowing only the symptom.

Available tools

Is this safe to write to a log?

A newline in a username ends the entry and starts a forged one. An escape sequence leaves every byte in the file and changes what tail shows. See which one your value does, and the line once it is clean.

Logs · strip_log_injection

Which of these names are the same name?

A collision is not a property of one string. Paste a list of usernames or filenames and see which entries reduce to one identity key — under each of the six reducers, so the reach of a stronger key sits beside its cost.

Identity · find_key_collisions

Slugify any language

Київ becomes kyiv if something knows it is Ukrainian and kiyiv if nothing does. Language-aware romanization, plus the character that gave the language away.

Slugs · slugify, detect_scripts

Which cleanup do I need?

Every preset against one string, side by side — and the case where the order is not a matter of taste, because normalising manufactures the very characters a validator was looking for.

Composition · canonicalize, strip_obfuscation, search_key

Why don't these two strings match?

Paste both. See which codepoints differ, then which single call makes them equal — normalization, case, whitespace, invisibles or lookalikes. The one to reach for when you have a mismatch and no idea why.

Comparison · normalize, fold_case, canonicalize

Remove invisible characters

Strips zero-width spaces, bidi overrides, tag characters, variation selectors, private-use and noncharacters — and names every codepoint it removed.

Invisible characters · strip_zero_width_chars, strip_bidi, strip_tags

Detect Trojan Source

Finds the bidirectional controls that make source render differently from how it compiles, with line and column for each — and flags the direction conflict that stripping them cannot fix.

Bidi · strip_bidi, has_bidi_conflict

Check confusable characters

Folds homoglyphs toward Latin under both digit policies at once, and shows character by character where the two disagree — because one reading is a number and the other is a word.

Confusables · normalize_confusables

Detect zalgo text

Shows how deep combining marks stack per base character, and where that count stops telling abuse from ordinary orthography — Vietnamese needs two marks on one letter.

Combining marks · is_zalgo, strip_zalgo

Detect script spoofing

Reads a hostname label by label for mixed-script and whole-script confusables — the signal that separates a Cyrillic imitation of a brand from an ordinary Russian domain, which one flag cannot.

Domains · analyze_hostname, detect_scripts

Normalize Unicode whitespace

Folds no-break, ideographic and hair spaces to ordinary ones — along with the Braille blanks and Hangul fillers that render as a gap and that strip(), trim() and \s all miss.

Text hygiene · collapse_whitespace

Sanitize a filename

Turns any string into a name that is legal on Windows, macOS and Linux — and identical on all three, which matters because macOS stores filenames decomposed and the other two do not.

Filenames · sanitize_filename

Truncate text without breaking emoji

A family emoji is 25 bytes, 7 codepoints and 1 character. Cut by the wrong measure and the family becomes one man. Compare all four cuts.

Graphemes · grapheme_truncate, grapheme_len, terminal_width