Do tracked changes come back?

Yes, deleted words come back. Nothing marks them. Here is the real output, and how to get the accepted text.

The short answer

Yes, deleted words come back. Nothing marks them. A deleted clause in a Word redline is in the response, next to the clause that replaced it.

In a Word file the deleted words come back in place. They are glued to the inserted words, with no space between them. Moved text comes back twice. A deleted paragraph comes back as a normal paragraph.

In an OpenDocument file the deleted words come back at the start of the document, before the body. The inserted words come back in place.

The response does not say that the file held tracked changes. Accept the changes before you upload. Below are two ways to do it, and one way to check a file first.

The engine is tika-server-standard 3.3.1.

Source: terraform/lambda-layers/build/versions.env (versions.env: TIKA_VERSION), accessed 2026-10-21.

What comes back, case by case

We built one small file for each format. Each change holds a marker word: DELETED, INSERTED or MOVED. You can see which change came back and where. We sent each file to the production API. Every row shows its source. The inputs and the raw responses are in the repo.

What five tracked-change inputs return today
InputWhat comes backSource
A Word file with a deletion, an insertion, a move and a deleted paragraphThe deleted words come back in place. They are glued to the inserted words, with no space and no marker. The moved text comes back twice, once at each place. The deleted paragraph comes back as a normal paragraph. The response has no flag that the file held tracked changes.Production API probe: POST /v1/extract
accessed 2026-10-21
The same Word file as MarkdownThe same words in the same order. Each paragraph becomes a Markdown paragraph. The deleted words are still glued to the inserted words. The json output also gives the same text, one paragraph for each element.Production API probe: POST /v1/extract
accessed 2026-10-21
An OpenDocument text file with a deletion and an insertionThe deleted words come back at the start of the document, before the first body paragraph. The inserted words come back in place, in their paragraph. So the deleted words can come back before the text that replaced them.Production API probe: POST /v1/extract
accessed 2026-10-21
A PDFA PDF has no tracked changes. A revision mark in a PDF is a drawing or a markup note. txtfetch returns the text a page shows. Comments and sticky notes are on /docs/headers-and-notes.Production API probe: POST /v1/extract
accessed 2026-10-21
The Word file after the accept-all scriptThe deleted words and the first copy of the moved text are gone. The inserted words stay, with the right spaces. The moved text comes back once, at its new place. Two empty lines stay: one where the moved text was, and one where the deleted paragraph was.Production API probe: POST /v1/extract
accessed 2026-10-21

Real output

Each block is the full response body, as the API sent it. In the JSON, \n is a line break inside the text.

A Word file with a deletion, an insertion, a move and a deleted paragraph

In

track.docx

Out

{"status":"success","extracted_text":"The fee is DELETED five hundredINSERTED nine hundred dollars.\nMOVED clause text.\nBody three.\nMOVED clause text.\nDELETED whole paragraph.\n","metadata":{"content_type":"application/vnd.openxmlformats-officedocument.wordprocessingml.document","bytes":1194,"chars":137,"ocr":false}}

The same Word file as Markdown

In

track.docx (format=markdown)

Out

{"status":"success","markdown":"The fee is DELETED five hundredINSERTED nine hundred dollars.\n\nMOVED clause text.\n\nBody three.\n\nMOVED clause text.\n\nDELETED whole paragraph.\n","metadata":{"content_type":"application/vnd.openxmlformats-officedocument.wordprocessingml.document","bytes":1194,"ocr":false,"chars":141,"format":"markdown","tier":"standard","pages":null,"vlm":false}}

An OpenDocument text file with a deletion and an insertion

In

track.odt

Out

{"status":"success","extracted_text":"DELETED five hundred\nBody one.\nThe fee is INSERTED nine hundred dollars.\nBody three.\n","metadata":{"content_type":"application/vnd.oasis.opendocument.text","bytes":931,"chars":85,"ocr":false}}

The Word file after the accept-all script

In

accepted.docx

Out

{"status":"success","extracted_text":"The fee is INSERTED nine hundred dollars.\n\nBody three.\nMOVED clause text.\n\n","metadata":{"content_type":"application/vnd.openxmlformats-officedocument.wordprocessingml.document","bytes":1115,"chars":75,"ocr":false}}

What to do

Get the accepted text before you extract. Step 1 and step 2 do that. Step 3 checks a file before you send it.

1. Accept all changes in the editor

In Word, open the Review tab and choose Accept, then Accept All Changes and Stop Tracking. In LibreOffice, choose Edit, Track Changes, Manage, then Accept All. Save the file, then upload it. This is the safest way. The editor handles every kind of change.

2. Run the accept-all script

Use the script below when you have many files, or when no editor is available. Send its output file to the API. We ran it on our Word file and sent the result to production. The last block under it is the response.

The script removes each deletion and each move-from copy. It keeps each insertion and each move-to copy, and removes only the wrapper. It reads the body, the footnotes, the endnotes, the headers and the footers. It keeps each paragraph, so the old place of a move and a deleted paragraph each leave an empty line.

Install

pip install lxml

Python, saved as accept_all.py. Run: python accept_all.py track.docx accepted.docx

import sys, zipfile
from lxml import etree

W = "{http://schemas.openxmlformats.org/wordprocessingml/2006/main}"
PARTS = ("word/document.xml", "word/footnotes.xml", "word/endnotes.xml")


def accept(xml):
    root = etree.fromstring(xml)
    # Deletions and the move-from copy go. Skip flags on a paragraph mark.
    for el in list(root.iter(W + "del", W + "moveFrom")):
        if el.getparent().tag != W + "rPr":
            el.getparent().remove(el)
    # Insertions and the move-to copy stay. Only the wrapper goes.
    for el in list(root.iter(W + "ins", W + "moveTo")):
        if el.getparent().tag != W + "rPr":
            etree.strip_tags(el.getparent(), el.tag)
    return etree.tostring(root, xml_declaration=True, encoding="UTF-8", standalone=True)


src, dst = sys.argv[1], sys.argv[2]
with zipfile.ZipFile(src) as zin, zipfile.ZipFile(dst, "w", zipfile.ZIP_DEFLATED) as zout:
    for item in zin.infolist():
        data = zin.read(item.filename)
        if item.filename in PARTS or item.filename.startswith(("word/header", "word/footer")):
            data = accept(data)
        zout.writestr(item, data)

The API returned, for accepted.docx

{"status":"success","extracted_text":"The fee is INSERTED nine hundred dollars.\n\nBody three.\nMOVED clause text.\n\n","metadata":{"content_type":"application/vnd.openxmlformats-officedocument.wordprocessingml.document","bytes":1115,"chars":75,"ocr":false}}

The deleted words are gone. The moved text comes back once. Two empty lines stay: one at the old place of the move, and one where the deleted paragraph was.

3. Check the file first in the browser

The Word to text tool runs in your browser. It shows the accepted view: it leaves out deleted words. It does not upload your file. Use it to see if a file holds tracked changes before you send it. The API returns the deleted words that the tool leaves out.

What personal data txtfetch returns lists other places where text can hide in a file.

What we did not test

We tested one .docx file and one .odt file that we uploaded. We did not test a page that txtfetch fetches from a URL. We did not test the legacy .doc format or RTF. We did not test a change that only changes formatting. We did not test a change inside a table, a header, a footnote or a comment. We ran the script on the body only. We did not test PowerPoint or Excel files. We make no claim about them.

Read Headers, footers, footnotes and comments for the parts outside the body. Read the Office page for the rest of the format.

Frequently asked questions

Do deleted words in a tracked-changes Word file come back?
Yes. In our probe the deleted words came back in place, glued to the inserted words with no space and no marker. The response does not say that the file held tracked changes. Accept all changes before you upload, or run the accept-all script on this page.
Does moved text come back twice?
Yes, for a Word file. A move is stored as two copies of the text: one where it was and one where it went. Both copies came back. The accept-all script keeps only the copy at the new place.
What happens to tracked changes in an OpenDocument file?
The deleted words came back at the start of the document, before the body. The inserted words came back in place. Accept all changes in LibreOffice before you upload.
Will a deleted clause show up in my RAG answers?
It can. txtfetch returns the deleted text with the rest. Your index then holds the deleted clause and the new clause, and a search can return either one. Remove the changes before you extract.
Can the API tell me that a file has tracked changes?
No. The metadata object holds content_type, bytes, chars and ocr. It has no field for tracked changes. Check the file first in the Word to text tool, which shows the accepted view.
Does the in-browser Word to text tool show the same text as the API?
No. The in-browser tool leaves out deleted words, so it shows the accepted view. The API returns them. Use the tool to check what a file holds before you upload it.
Did you test the old .doc format or RTF?
No. We tested one .docx file and one .odt file. We did not test .doc, RTF, formatting-only changes, or changes inside tables, headers, footnotes or comments. We make no claim about them.

Watch it run, then take a key.

The playground replays a real recorded response for every sample document.

Open the playground →

Get an API key →