Skip to content
Ghostchars

Clean a document

DOCX, ODT, HTML, Markdown or plain text. The file is opened in your browser and never uploaded — there is no server to upload it to.

  • Runs in your browser
  • DOCX · ODT · HTML · MD · TXT
  • Your original file is never modified

Drop a file here

DOCX, ODT, HTML, Markdown or plain text — up to 25 MB.

What gets inspected, per format

Text nodes are cleaned in every format. What else is reported depends on what the format can hide.

FormatCleansReports
DOCXText in document, headers, footers, footnotes, endnotes and comments — including characters written as numeric entities.Hidden runs, white-on-white and tiny text, tracked changes, comments, rsid sessions, authoring metadata, custom properties, macros, media.
ODTEvery text node of content.xml. Attributes are never touched.Annotations, tracked-change regions, hidden styles, generator, creators, editing cycles, user-defined fields.
HTMLText nodes only. Tags, attributes, comments, script and style pass through byte-identical.Comments, display:none / hidden / font-size:0 elements, the generator meta tag, suspicious characters in alt/title/aria attributes.
Markdown · TXTThe whole file. Line endings are preserved unless you ask for them to be folded.Nothing to report beyond the characters themselves — plain text has no structure to hide in.

How it works

  1. Choose a file

    Drop a .docx, .odt, .html, .md or .txt onto the page, or pick one with the file button. It is read by the browser; nothing is sent anywhere.

  2. Read the report

    Every hidden character is listed with its position, codepoint and Unicode name, alongside what the file hides around the text: invisible runs, comments, tracked changes, authoring metadata.

  3. Choose what to remove

    The defaults strip characters that are contraband anywhere in prose. The twelve advanced switches, plus metadata and rsids, are opt-in because each one changes something visible.

  4. Download the cleaned copy

    A new file is produced in memory and offered as a download. Your original is never modified.

What this does not do

  • PDF. Text in a PDF is not safely rewritable in place; inspection and metadata stripping are planned, editing is not.
  • Images. EXIF, XMP and C2PA metadata are a different problem and a different tool.
  • It never deletes a hidden run, a tracked change or a comment. Those are reported so you can decide.
  • Statistical watermarks such as SynthID-Text live in word choice, not characters. Nothing here touches them.

The same thing, on the command line

clean_file.py is the reference implementation this page is a port of. It runs offline, takes the same flags, and has a --check mode for pre-commit hooks.

./clean_file.py --show essay.docx
./clean_file.py -i --metadata --rsids essay.docx
./clean_file.py -s --punct essay.docx

Questions about documents

Is my document uploaded anywhere?

No. Ghostchars is a static site with no backend. The file is read by your browser with the FileReader API, processed in the tab, and the cleaned copy is created in memory. Nothing is transmitted, and there is no server that could receive it.

Which formats are supported?

DOCX, ODT, HTML, Markdown and plain text. DOCX and ODT are ZIP packages of XML, which the browser unpacks and repacks; HTML is cleaned in its text nodes only; Markdown and plain text are cleaned as a whole.

Why not PDF?

A PDF stores glyph positions, not editable text runs, so replacing a character can change the layout or break the file. Reporting on a PDF and stripping its metadata are feasible and planned; rewriting its text is not something a tool should do quietly.

Why are hidden runs and comments reported instead of removed?

Because removing them changes the document. A hidden run may be a template placeholder, a comment may be the reason the document exists. Ghostchars tells you they are there and how many; deleting them is an editorial decision that belongs to you.

What is an rsid, and why would I remove it?

Word stamps every editing session with a random 8-hex-digit revision-save id and writes it onto the runs typed in that session. A document with one or two distinct rsids across the whole body was pasted in in one go rather than written over time. Removing them removes that inference.

Will Word still open the cleaned file?

Yes. Every part of the package keeps its position and its compression method; only the text inside the nodes that changed is rewritten, and xml:space="preserve" is added where cleaning would otherwise have let Word drop an edge space. With --metadata the custom-properties part is dropped, which leaves a dangling relationship that Word tolerates — the same trade the command-line tool makes.

What if a hidden character is written as an entity?

It is still caught. Every text node is entity-decoded before it is cleaned and re-escaped afterwards, so a zero-width space written as ​ is removed exactly like a literal one.