# Why images disappear after python-docx text replacement

> Avoid removing inline drawings when changing DOCX text. Inspect run content, skip unmatched runs, and verify images before and after the edit.

Maintained by Vespper. Updated 2026-09-27.

Canonical page: https://www.vespper.com/guides/python-docx-preserve-images

Topic: [Python DOCX troubleshooting](https://www.vespper.com/guides#python). [Start the learning path](https://www.vespper.com/guides#start-here).

An image can share a Word run with text. Assigning to that run's `.text` replaces the run's content, including any drawing it contained. This can remove a picture even when the assigned text looks unchanged. Replacing an entire paragraph's `.text` can remove its non-text content too.

The failure was reported in [python-docx issue 272](https://github.com/python-openxml/python-docx/issues/272). Its lesson still matters: a text replacement is a structural write, not a harmless string assignment.

## Avoid touching runs that do not match

Consider this pattern:

```python
for run in paragraph.runs:
    run.text = run.text.replace("OLD", "NEW")
```

It writes to every run, including runs with no matching text. Checking for the target before assigning reduces unnecessary writes, but does not make the operation safe for a run that contains both matching text and a drawing.

For a narrow replacement helper, require ordinary text-only runs and reject everything else. The [cross-run replacement example](https://www.vespper.com/guides/python-docx-replace-across-runs) demonstrates this guard. A general implementation needs to edit the appropriate text nodes while retaining drawing elements and their relationships.

## Record what should survive

Before editing, record the location and purpose of the images that matter: a logo in a header, an inline chart in a table cell, or an illustration beside the paragraph being changed. An unchanged number of files under `word/media/` is not sufficient proof that pictures still appear. Unreferenced media can remain in the package after the drawing that displayed it has been removed.

Compare the relevant drawing elements, relationships, and visible output. If you inspect `document.inline_shapes`, remember that inline shapes are only one category of document artwork. Do not interpret that count as a complete inventory of floating shapes, header images, and every other drawing.

## Test the edit next to the image

Use a fixture in which the target text and a picture share a paragraph, plus another fixture with the picture in the same run. Ask for a small text change. Reopen the output and inspect both pictures in the target viewer. Include a control case where no text matches: that run should remain untouched.

For Vespper, read the current document block and preserve unrelated structure when submitting the replacement. Do not reconstruct an image-bearing paragraph from its visible text alone. The [formatting guide](https://www.vespper.com/guides/preserve-docx-formatting) covers using returned HTML and classes as the basis for an edit.

## Next steps

- [Handle phrases split across runs](https://www.vespper.com/guides/python-docx-replace-across-runs): Locate text across formatting boundaries while deciding which run content is safe to change.
- [Check preservation beyond images](https://www.vespper.com/guides/preserve-docx-formatting): Include tables, lists, formatting, and existing review markup in your validation.

## Related guides

- [Build an AI agent that edits existing DOCX documents](https://www.vespper.com/llms/build-docx-editing-agent.md)

