# How to copy annotations so they inherit the destination page coordinate system? (Bluebeam markups jump on color/status change)

**URL:** <https://forum.mupdf.com/t/how-to-copy-annotations-so-they-inherit-the-destination-page-coordinate-system-bluebeam-markups-jump-on-color-status-change/282>\
**Category:** PyMuPDF\
**Created:** [February 3, 2026, 10:52pm UTC](https://forum.mupdf.com/t/how-to-copy-annotations-so-they-inherit-the-destination-page-coordinate-system-bluebeam-markups-jump-on-color-status-change/282 "2026-02-03T22:52:31Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![donovan](https://avatars.discourse-cdn.com/v4/letter/d/ea666f/32.png) [@donovan](https://forum.mupdf.com/u/donovan)\
**Post date:** [February 3, 2026, 10:52pm UTC](https://forum.mupdf.com/t/how-to-copy-annotations-so-they-inherit-the-destination-page-coordinate-system-bluebeam-markups-jump-on-color-status-change/282/1 "2026-02-03T22:52:31Z")

</div>

**Problem:**  
I’m copying Bluebeam markups (annotations) from one PDF to another using PyMuPDF. I **repage/normalize** the destination first so page size/origin matches the source. The annotations look correct after copy, but **when I change color/status in Bluebeam** , some annotations (especially **FreeText callouts** ) jump to a different location. The jump seems to snap to the original coordinate system.

**What I’m doing (high‑level):**

1. Repage destination pages to match the original (size/origin/rotation).

2. Copy annotations from source → destination.

3. Output looks correct.

**Issue:**  
After copying, changing annotation color/status forces Bluebeam to recompute its appearance, and the annotation **moves to old coordinates**.

**Questions:**

- Is there a PyMuPDF‑supported way to copy annotations so they **inherit the destination page’s coordinate system**?

- Are there specific annotation fields that must be updated/reset to “bake in” the new position?

- For FreeText/Callout annotations, what fields are authoritative for position when the appearance is regenerated? (/Rect, /AP, /CL, /RD, etc.)

- Should /AP be removed to force a fresh appearance, or is there a better approach?

[revised\_with\_markups.pdf](https://forum.mupdf.com/uploads/short-url/80AHxGRbYfmwQMjAO49CiZ9ZQVC.pdf) (2.0 MB)

[A202.pdf](https://forum.mupdf.com/uploads/short-url/jJfGiir4H0Slu2EzV5JBKLKSN5h.pdf) (1.8 MB)

repro\_copy\_annots.py

# Script Example (using Codex)

```auto
pip install pymupdf

import fitz

SOURCE = “source.pdf” # has markups (FreeText/callout)
DEST = “dest.pdf” # clean PDF with same page count
OUT = “out_with_markups.pdf”

def copy_annots(src_doc, dst_doc):
for i in range(min(len(src_doc), len(dst_doc))):
src_page = src_doc[i]
dst_page = dst_doc[i]

    annot = src_page.first_annot
    while annot:
        # copy annot by xref
        dst_page.add_annot_from(annot)
        annot = annot.next

def main():
src = fitz.open(SOURCE)
dst = fitz.open(DEST)

copy_annots(src, dst)
dst.save(OUT)

src.close()
dst.close()

if name == “main”:
main()

```

---

<div class="post-metadata">

**Author:** ![Jamie\_Lemon](https://yyz2.discourse-cdn.com/flex004/user_avatar/forum.mupdf.com/jamie_lemon/32/5_2.png) [@Jamie\_Lemon](https://forum.mupdf.com/u/Jamie_Lemon)\
**Post date:** [February 4, 2026, 5:15pm UTC](https://forum.mupdf.com/t/how-to-copy-annotations-so-they-inherit-the-destination-page-coordinate-system-bluebeam-markups-jump-on-color-status-change/282/2 "2026-02-04T17:15:43Z")

</div>

Hi @donovan - welcome to the forum!

I’m not sure if calling [annot.update()](https://pymupdf.readthedocs.io/en/latest/annot.html#Annot.update) would help or not?

In any case I couldn’t find any `Page.add_annot_from(annot)` method in the PyMuPDF API so your code failed for me.

I do this kind of thing when I recreate the annots onto the destination document:

```python
import pymupdf

SOURCE = "source.pdf" # has markups (FreeText/callout)
DEST = "dest.pdf" # clean PDF with same page count
OUT = "out_with_markups.pdf"

def copy_annots(src_doc, dst_doc):
    for i in range(min(len(src_doc), len(dst_doc))):
        src_page = src_doc[i]
        dst_page = dst_doc[i]

        annot = src_page.first_annot
        while annot:
            print("found annot!")

            text = ""

            for index, (key, value) in enumerate(annot.info.items()):
                print(f"{index}: {key} = {value}, type:{annot.type}")
                if key == "content":
                    text = value

            # Copy annotation to destination page
            if annot.type[1] == "Text":
                dst_page.add_text_annot(annot.rect.top_left, text)
            elif annot.type[1] == "FreeText":
                dst_page.add_freetext_annot(annot.rect, text)

            annot = annot.next

src = pymupdf.open(SOURCE)
dst = pymupdf.open(DEST)

copy_annots(src, dst)
dst.save(OUT)

src.close()
dst.close()

```

Hope this helps, please let me know!
