# GroupDocs.Watermark for Python via .NET — Complete Documentation > Native Python library that adds, searches, and removes text and image watermarks across PDF, Word, Excel, PowerPoint, Visio, email, and image formats on Windows, Linux, and macOS. No Microsoft Office or OpenOffice required. --- ## Add text watermarks Path: https://docs.groupdocs.com/watermark/python-net/add-text/ One of the main features of GroupDocs.Watermark is adding text watermarks to documents. You can add watermarks to documents or images from a local path, as well as from a stream. For a full list of supported formats, check [Supported document formats]({{< ref "watermark/python-net/getting-started/supported-document-formats.md" >}}). ## Add a text watermark To add a text watermark, follow these steps: 1. Open the document by passing its path (or a stream) to the [Watermarker](https://reference.groupdocs.com/watermark/python-net/) class, using a `with` block so the document is released automatically. 2. Create a `TextWatermark` with the desired text and `Font`. 3. Style the watermark — for example, set `foreground_color` and alignment. 4. Call `add()` to apply the watermark and `save()` to write the result. {{< tabs "code-example-add-text">}} {{< tab "add_text_watermark.py" >}} ```python from groupdocs.watermark import Watermarker from groupdocs.watermark.watermarks import TextWatermark, Font, Color from groupdocs.watermark.common import HorizontalAlignment, VerticalAlignment def add_text_watermark(): with Watermarker("./sample.pdf") as watermarker: # Build the text watermark and style it watermark = TextWatermark("Top Secret", Font("Arial", 36.0)) watermark.foreground_color = Color.red watermark.horizontal_alignment = HorizontalAlignment.CENTER watermark.vertical_alignment = VerticalAlignment.CENTER watermark.rotate_angle = 45.0 watermark.opacity = 0.4 watermarker.add(watermark) watermarker.save("./output.pdf") if __name__ == "__main__": add_text_watermark() ``` {{< /tab >}} {{< tab "sample.pdf" >}} {{< tab-text >}} `sample.pdf` is the sample file used in this example. Click [here](https://docs.groupdocs.com/watermark/python-net/_sample_files/developer-guide/basic-usage/add-text/sample.pdf) to download it. {{< /tab-text >}} {{< /tab >}} {{< tab "output.pdf" >}} ```text Binary file (PDF, 352 KB) ``` [Download full output](https://docs.groupdocs.com/watermark/python-net/_output_files/developer-guide/basic-usage/add-text/add_text_watermark/output.pdf) {{< /tab >}} {{< /tabs >}} Run the program. A new watermarked document appears at the specified path. ## What's next GroupDocs.Watermark offers many more capabilities for text watermarks — background and foreground colors, custom fonts, opacity, rotation, tiling, and absolute or relative positioning. See [Adding text watermarks]({{< ref "watermark/python-net/developer-guide/advanced-usage/adding-watermarks/adding-text-watermarks.md" >}}) in the advanced guide. --- ## Attachments in PDF document Path: https://docs.groupdocs.com/watermark/python-net/attachments-in-pdf-document/ A PDF can carry embedded file attachments. `Watermarker.get_content()` returns a `PdfContent` whose `attachments` collection lets you add, extract, and remove them — and you can even open an attachment in its own `Watermarker` to watermark it. ## Add an attachment The example embeds a Word document into the PDF as an attachment. {{< tabs "code-example-add-pdf-attachment">}} {{< tab "add_attachment.py" >}} ```python from groupdocs.watermark import Watermarker from groupdocs.watermark.options.pdf import PdfLoadOptions def add_attachment(): with Watermarker("./document.pdf", PdfLoadOptions()) as watermarker: content = watermarker.get_content() with open("./sample.docx", "rb") as f: data = f.read() content.attachments.add(data, "sample.docx", "Attached Word document") watermarker.save("./output.pdf") if __name__ == "__main__": add_attachment() ``` {{< /tab >}} {{< tab "document.pdf" >}} {{< tab-text >}} `document.pdf` and `sample.docx` are the sample files used in this example. Download [document.pdf](https://docs.groupdocs.com/watermark/python-net/_sample_files/developer-guide/advanced-usage/adding-watermarks/attachments-in-pdf-document/document.pdf) and [sample.docx](https://docs.groupdocs.com/watermark/python-net/_sample_files/developer-guide/advanced-usage/adding-watermarks/attachments-in-pdf-document/sample.docx). {{< /tab-text >}} {{< /tab >}} {{< tab "output.pdf" >}} ```text Binary file (PDF, 512 KB) ``` [Download full output](https://docs.groupdocs.com/watermark/python-net/_output_files/developer-guide/advanced-usage/adding-watermarks/add-watermarks-to-pdf-documents/attachments-in-pdf-document/add_attachment/output.pdf) {{< /tab >}} {{< /tabs >}} ## Extract attachments Iterate the `attachments` collection to read each attachment's metadata and content. ```python from groupdocs.watermark import Watermarker from groupdocs.watermark.options.pdf import PdfLoadOptions with Watermarker("./document.pdf", PdfLoadOptions()) as watermarker: content = watermarker.get_content() print("Attachments:", len(content.attachments)) for attachment in content.attachments: info = attachment.get_document_info() print(f"- name={attachment.name!r} type={info.file_type} size={len(attachment.content)} bytes") # Save the attachment's bytes to disk with open(f"./{attachment.name}", "wb") as f: f.write(attachment.content) ``` For the example PDF produced above, this prints: ```text Attachments: 1 - name='sample.docx' type=Docx (.docx) - WordProcessing size=14752 bytes ``` Use `content.attachments.remove_at(index)` or `content.attachments.remove(attachment)` to delete an attachment, and open an attachment in its own `Watermarker` (from its `content` bytes) to add a watermark to the attached document itself. --- ## Email attachments Path: https://docs.groupdocs.com/watermark/python-net/email-attachments/ `EmailContent.attachments` is the collection of files attached to an email message. Each attachment exposes its `name`, `content` (bytes), and `get_document_info()`, and you can add and remove attachments. ## Extract all attachments {{< tabs "code-example-extract-email-attachments">}} {{< tab "extract_attachments.py" >}} ```python from groupdocs.watermark import Watermarker from groupdocs.watermark.options.email import EmailLoadOptions def extract_attachments(): with Watermarker("./message.msg", EmailLoadOptions()) as watermarker: content = watermarker.get_content() print("Attachments:", len(content.attachments)) for attachment in content.attachments: info = attachment.get_document_info() print(f"- {attachment.name!r} type={info.file_type}") with open(f"./{attachment.name}", "wb") as f: f.write(attachment.content) if __name__ == "__main__": extract_attachments() ``` {{< /tab >}} {{< tab "message.msg" >}} {{< tab-text >}} `message.msg` is the sample file used in this example. Click [here](https://docs.groupdocs.com/watermark/python-net/_sample_files/developer-guide/advanced-usage/adding-watermarks/add-watermarks-to-email-attachments/email-attachments/message.msg) to download it. {{< /tab-text >}} {{< /tab >}} {{< tab "sample.docx" >}} ```text Binary file (DOCX, 118 KB) ``` [Download full output](https://docs.groupdocs.com/watermark/python-net/_output_files/developer-guide/advanced-usage/adding-watermarks/add-watermarks-to-email-attachments/email-attachments/extract_attachments/sample.docx) {{< /tab >}} {{< /tabs >}} ## Add an attachment {{< tabs "code-example-add-email-attachment">}} {{< tab "add_attachment.py" >}} ```python from groupdocs.watermark import Watermarker from groupdocs.watermark.options.email import EmailLoadOptions def add_attachment(): with Watermarker("./message.msg", EmailLoadOptions()) as watermarker: content = watermarker.get_content() with open("./sample.docx", "rb") as f: data = f.read() content.attachments.add(data, "sample.docx") watermarker.save("./output.msg") if __name__ == "__main__": add_attachment() ``` {{< /tab >}} {{< tab "message.msg" >}} {{< tab-text >}} `message.msg` and `sample.docx` are the sample files used in this example. Download [message.msg](https://docs.groupdocs.com/watermark/python-net/_sample_files/developer-guide/advanced-usage/adding-watermarks/add-watermarks-to-email-attachments/email-attachments/message.msg) and [sample.docx](https://docs.groupdocs.com/watermark/python-net/_sample_files/developer-guide/advanced-usage/adding-watermarks/add-watermarks-to-email-attachments/email-attachments/sample.docx). {{< /tab-text >}} {{< /tab >}} {{< tab "output.msg" >}} ```text Binary file (MSG, 254 KB) ``` [Download full output](https://docs.groupdocs.com/watermark/python-net/_output_files/developer-guide/advanced-usage/adding-watermarks/add-watermarks-to-email-attachments/email-attachments/add_attachment/output.msg) {{< /tab >}} {{< /tabs >}} ## Remove an attachment The `attachments` collection supports `remove_at(index)` and `remove(attachment)`. Iterate in reverse when removing by index: {{< tabs "code-example-remove-email-attachment">}} {{< tab "remove_attachment.py" >}} ```python from groupdocs.watermark import Watermarker from groupdocs.watermark.options.email import EmailLoadOptions def remove_attachment(): with Watermarker("./message.msg", EmailLoadOptions()) as watermarker: content = watermarker.get_content() for i in range(len(content.attachments) - 1, -1, -1): if "sample" in content.attachments[i].name: content.attachments.remove_at(i) watermarker.save("./output.msg") if __name__ == "__main__": remove_attachment() ``` {{< /tab >}} {{< tab "message.msg" >}} {{< tab-text >}} `message.msg` is the sample file used in this example. Click [here](https://docs.groupdocs.com/watermark/python-net/_sample_files/developer-guide/advanced-usage/adding-watermarks/add-watermarks-to-email-attachments/email-attachments/message.msg) to download it. {{< /tab-text >}} {{< /tab >}} {{< tab "output.msg" >}} ```text Binary file (MSG, 12 KB) ``` [Download full output](https://docs.groupdocs.com/watermark/python-net/_output_files/developer-guide/advanced-usage/adding-watermarks/add-watermarks-to-email-attachments/email-attachments/remove_attachment/output.msg) {{< /tab >}} {{< /tabs >}} To watermark an attached document, open `attachment.content` in its own `Watermarker` (via `io.BytesIO`), add the watermark, and write the bytes back — the same pattern shown for [spreadsheet attachments]({{< ref "watermark/python-net/developer-guide/advanced-usage/adding-watermarks/add-watermarks-to-spreadsheet-documents/working-with-spreadsheet-document-attachments.md" >}}). --- ## Existing objects in diagrams Path: https://docs.groupdocs.com/watermark/python-net/existing-objects-in-diagram-document/ `Watermarker.get_content()` returns a `DiagramContent` whose `pages` expose the diagram's `shapes` and headers/footers. You can iterate the shapes to read their properties, modify them, or remove them. ## Extract information about shapes The example reports the shapes on the first page of a Visio diagram. {{< tabs "code-example-diagram-existing-objects">}} {{< tab "extract_shapes.py" >}} ```python from groupdocs.watermark import Watermarker def extract_shapes(): with Watermarker("./diagram.vsdx") as watermarker: content = watermarker.get_content() page = content.pages[0] print(f"Pages: {len(content.pages)}; page 1 shapes: {len(page.shapes)}") for shape in page.shapes: text = (shape.text or "").strip() print(f" shape name={shape.name!r} text={text!r} " f"size={round(shape.width)}x{round(shape.height)}") if __name__ == "__main__": extract_shapes() ``` {{< /tab >}} {{< tab "diagram.vsdx" >}} {{< tab-text >}} `diagram.vsdx` is the sample file used in this example. Click [here](https://docs.groupdocs.com/watermark/python-net/_sample_files/developer-guide/advanced-usage/adding-watermarks/existing-objects-in-diagram-document/diagram.vsdx) to download it. {{< /tab-text >}} {{< /tab >}} {{< tab "extract-shapes.txt" >}} ```text Pages: 2; page 1 shapes: 12 shape name='Rectangle' text='' size=108x72 shape name='Circle' text='' size=108x108 shape name='Square' text='' size=108x108 shape name='Octagon' text='' size=108x108 shape name='Sheet.20' text='' size=216x63 shape name='Sheet.21' text='' size=216x54 shape name='Triangle' text='' size=108x94 shape name='Sheet.33' text='' size=85x0 shape name='Sheet.34' text='' size=108x0 [TRUNCATED] ``` [Download full output](https://docs.groupdocs.com/watermark/python-net/_output_files/developer-guide/advanced-usage/adding-watermarks/add-watermarks-to-diagram-documents/existing-objects-in-diagram-document/extract_shapes/extract-shapes.txt) {{< /tab >}} {{< /tabs >}} Each shape exposes `name`, `text`, `image`, `x`, `y`, `width`, `height`, and `rotate_angle`. ## Remove and modify shapes The `shapes` collection supports `remove_at(index)` and `remove(shape)`. Iterate in reverse when removing by index: {{< tabs "code-example-diagram-remove-shapes">}} {{< tab "remove_and_modify_shapes.py" >}} ```python from groupdocs.watermark import Watermarker def remove_and_modify_shapes(): with Watermarker("./diagram.vsdx") as watermarker: content = watermarker.get_content() for page in content.pages: for i in range(len(page.shapes) - 1, -1, -1): if page.shapes[i].name == "Rectangle": page.shapes.remove_at(i) watermarker.save("./output.vsdx") if __name__ == "__main__": remove_and_modify_shapes() ``` {{< /tab >}} {{< tab "diagram.vsdx" >}} {{< tab-text >}} `diagram.vsdx` is the sample file used in this example. Click [here](https://docs.groupdocs.com/watermark/python-net/_sample_files/developer-guide/advanced-usage/adding-watermarks/existing-objects-in-diagram-document/diagram.vsdx) to download it. {{< /tab-text >}} {{< /tab >}} {{< tab "output.vsdx" >}} ```text Binary file (VSDX, 29 KB) ``` [Download full output](https://docs.groupdocs.com/watermark/python-net/_output_files/developer-guide/advanced-usage/adding-watermarks/add-watermarks-to-diagram-documents/existing-objects-in-diagram-document/remove_and_modify_shapes/output.vsdx) {{< /tab >}} {{< /tabs >}} You can replace a shape's text by assigning to `shape.text`, replace its image by assigning a `DiagramWatermarkableImage` to `shape.image`, and modify its position and size through `x`, `y`, `width`, `height`, and `rotate_angle`. --- ## Existing objects in word processing document Path: https://docs.groupdocs.com/watermark/python-net/existing-objects-in-word-processing-document/ `Watermarker.get_content()` returns a `WordProcessingContent` whose `sections` each expose a `shapes` collection. Watermarks added to a Word document are shapes, so this is how you find, modify, and remove watermarks that already exist in a document. ## Extract information about shapes {{< tabs "code-example-word-existing-objects">}} {{< tab "extract_shapes.py" >}} ```python from groupdocs.watermark import Watermarker from groupdocs.watermark.options.word_processing import WordProcessingLoadOptions def extract_shapes(): with Watermarker("./document.docx", WordProcessingLoadOptions()) as watermarker: content = watermarker.get_content() for i, section in enumerate(content.sections): print(f"Section {i}: shapes={len(section.shapes)}") for shape in section.shapes: text = (shape.text or "").strip() print(f" shape text={text!r} size={round(shape.width)}x{round(shape.height)} name={shape.name!r}") if __name__ == "__main__": extract_shapes() ``` {{< /tab >}} {{< tab "document.docx" >}} {{< tab-text >}} `document.docx` is the sample file used in this example. Click [here](https://docs.groupdocs.com/watermark/python-net/_sample_files/developer-guide/advanced-usage/adding-watermarks/existing-objects-in-word-processing-document/document.docx) to download it. {{< /tab-text >}} {{< /tab >}} {{< tab "extract-shapes.txt" >}} ```text Section 0: shapes=3 shape text='' size=230x69 name='' shape text='' size=90x3 name='Rectangle 100004' shape text='' size=460x287 name='' ``` [Download full output](https://docs.groupdocs.com/watermark/python-net/_output_files/developer-guide/advanced-usage/adding-watermarks/add-watermarks-to-word-processing-documents/existing-objects-in-word-processing-document/extract_shapes/extract-shapes.txt) {{< /tab >}} {{< /tabs >}} Each shape exposes `text`, `image`, `name`, `alternative_text`, `x`, `y`, `width`, `height`, `rotate_angle`, `is_word_art`, and `behind_text`. ## Remove and modify shapes The `shapes` collection supports `remove_at(index)` and `remove(shape)`. Iterate in reverse when removing by index: {{< tabs "code-example-word-remove-shapes">}} {{< tab "remove_and_modify_shapes.py" >}} ```python from groupdocs.watermark import Watermarker from groupdocs.watermark.options.word_processing import WordProcessingLoadOptions def remove_and_modify_shapes(): with Watermarker("./document.docx", WordProcessingLoadOptions()) as watermarker: content = watermarker.get_content() for section in content.sections: for i in range(len(section.shapes) - 1, -1, -1): if section.shapes[i].text == "CONFIDENTIAL": section.shapes.remove_at(i) watermarker.save("./output.docx") if __name__ == "__main__": remove_and_modify_shapes() ``` {{< /tab >}} {{< tab "document.docx" >}} {{< tab-text >}} `document.docx` is the sample file used in this example. Click [here](https://docs.groupdocs.com/watermark/python-net/_sample_files/developer-guide/advanced-usage/adding-watermarks/existing-objects-in-word-processing-document/document.docx) to download it. {{< /tab-text >}} {{< /tab >}} {{< tab "output.docx" >}} ```text Binary file (DOCX, 118 KB) ``` [Download full output](https://docs.groupdocs.com/watermark/python-net/_output_files/developer-guide/advanced-usage/adding-watermarks/add-watermarks-to-word-processing-documents/existing-objects-in-word-processing-document/remove_and_modify_shapes/output.docx) {{< /tab >}} {{< /tabs >}} You can replace a shape's text by assigning to `shape.text`, replace its image by assigning a `WordProcessingWatermarkableImage` to `shape.image`, set or clear a hyperlink via `shape.hyperlink`, and modify its position, size, and `rotate_angle`. Headers and footers are available through `section.headers_footers`. --- ## Features Overview Path: https://docs.groupdocs.com/watermark/python-net/features-overview/ GroupDocs.Watermark for Python via .NET adds, searches, and removes watermarks across a wide range of [supported document formats]({{< ref "watermark/python-net/getting-started/supported-document-formats.md" >}}). Every operation follows the same workflow: open a document with `Watermarker`, call `add()`, `search()`, or `remove()`, then `save()` the result back to its original format. The capabilities below can be combined freely in a single pass. ## Text and image watermarks Add styled text or image watermarks with full control over font, color, opacity, rotation, alignment, and sizing. Image watermarks can be loaded from a file or a stream. See [Add text watermarks]({{< ref "watermark/python-net/developer-guide/basic-usage/add-text.md" >}}) and [Add image watermarks]({{< ref "watermark/python-net/developer-guide/basic-usage/add-image.md" >}}). ## Customization and tiling Position a watermark with absolute coordinates or parent-relative alignment and margins, scale it relative to the page, rotate it, and tile it across the whole page in a repeating pattern. See [Customize watermarks]({{< ref "watermark/python-net/developer-guide/basic-usage/customize.md" >}}), [Adding repeated watermarks]({{< ref "watermark/python-net/developer-guide/basic-usage/adding-repeated-watermarks.md" >}}), and [Adding text watermarks]({{< ref "watermark/python-net/developer-guide/advanced-usage/adding-watermarks/adding-text-watermarks.md" >}}). ## Format-specific placement Place watermarks using the options that fit each format — PDF artifacts, annotations, and print-only annotations; presentation slides, masters, layouts, and notes; spreadsheet worksheets, backgrounds, and header/footers; Visio pages; and locked Word sections and pages. See [Add watermarks to PDF documents]({{< ref "watermark/python-net/developer-guide/advanced-usage/adding-watermarks/add-watermarks-to-pdf-documents" >}}) and the other format topics in the [Developer Guide]({{< ref "watermark/python-net/developer-guide/advanced-usage/adding-watermarks" >}}). ## Searching, modifying, and removing Find watermarks already present in a document — including ones added by third-party tools — by exact text, regular expression, image similarity, or text formatting, and combine criteria with `and_`/`or_`/`not_`. Once found, replace their text or image, or remove them. See [Searching watermarks]({{< ref "watermark/python-net/developer-guide/advanced-usage/searching-and-modifying-watermarks/searching-watermarks.md" >}}), [Modifying found watermark properties]({{< ref "watermark/python-net/developer-guide/advanced-usage/searching-and-modifying-watermarks/modifying-found-watermark-properties.md" >}}), and [Removing found watermarks]({{< ref "watermark/python-net/developer-guide/advanced-usage/searching-and-modifying-watermarks/removing-found-watermarks.md" >}}). ## Working with existing content `Watermarker.get_content()` exposes a format-specific content tree so you can inspect and edit existing shapes, PDF XObjects/artifacts/annotations, attachments, backgrounds, and headers/footers — and you can watermark the images embedded inside a document with `get_images()`. See [Adding watermark to images inside a document]({{< ref "watermark/python-net/developer-guide/advanced-usage/adding-watermarks/add-watermarks-to-images/adding-watermark-to-images-inside-a-document.md" >}}). ## Tamper resistance Make watermarks hard to remove by locking them, protecting Word documents, adding print-only PDF annotations, or rasterizing PDF pages so the watermark cannot be edited out. See [Locking watermark in word processing document]({{< ref "watermark/python-net/developer-guide/advanced-usage/adding-watermarks/add-watermarks-to-word-processing-documents/locking-watermark-in-word-processing-document.md" >}}) and [Rasterize document or page]({{< ref "watermark/python-net/developer-guide/advanced-usage/adding-watermarks/add-watermarks-to-pdf-documents/rasterize-document-or-page.md" >}}). ## Document inspection Read a document's file type, page count, and size without modifying it, and list every file format the library supports. See [Get document info]({{< ref "watermark/python-net/developer-guide/basic-usage/get-document-info.md" >}}) and [Get supported file formats]({{< ref "watermark/python-net/developer-guide/basic-usage/get-supported-file-formats.md" >}}). ## On-premise GroupDocs.Watermark for Python via .NET runs entirely on your own infrastructure — your documents never leave your environment. The package is a self-contained wheel that bundles everything it needs, so no Microsoft Office, OpenOffice, or separate runtime has to be installed. See [System Requirements]({{< ref "watermark/python-net/getting-started/system-requirements.md" >}}) for the supported platforms and native dependencies. --- ## Install GroupDocs.Watermark for Python via .NET Path: https://docs.groupdocs.com/watermark/python-net/installation/ GroupDocs.Watermark for Python via .NET is distributed as a pre-built wheel on [PyPI](https://pypi.org/project/groupdocs-watermark-net/). The PyPI index hosts a separate wheel for each supported platform, and `pip` picks the correct one automatically. Each wheel is self-contained: it bundles the embedded runtime and every managed dependency, so no Microsoft Office, OpenOffice, or separate runtime install is required. Before installing, confirm your environment matches the supported platforms and Python versions listed in the [System Requirements]({{< ref "watermark/python-net/getting-started/system-requirements.md" >}}) topic. ## Install Package from PyPI Open a terminal and run the install command for your platform: {{< tabs "install-pypi">}} {{< tab "Windows" >}} ```ps py -m pip install groupdocs-watermark-net ``` {{< /tab >}} {{< tab "Linux" >}} ```bash python3 -m pip install groupdocs-watermark-net ``` {{< /tab >}} {{< tab "macOS" >}} ```bash python3 -m pip install groupdocs-watermark-net ``` {{< /tab >}} {{< /tabs >}} After running the command you should see output similar to: ```bash Collecting groupdocs-watermark-net Downloading groupdocs_watermark_net-26.6.0-py3-none-win_amd64.whl (135.8 MB) ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 135.8/135.8 MB 3.1 MB/s eta 0:00:00 Installing collected packages: groupdocs-watermark-net Successfully installed groupdocs-watermark-net-26.6.0 ``` The wheel file name will include a platform suffix that matches your operating system — for example `manylinux1_x86_64` on Ubuntu/Debian, `macosx_11_0_arm64` on Apple Silicon, or `win_amd64` on 64-bit Windows. ## Add the Package to `requirements.txt` For reproducible environments, pin the package version in your `requirements.txt`: ```txt groupdocs-watermark-net==26.6.0 ``` Then install all dependencies in one step: ```bash pip install -r requirements.txt ``` ## Install from a Pre-Downloaded Wheel If your build environment cannot reach PyPI, download the appropriate wheel from the [GroupDocs Releases website](https://releases.groupdocs.com/watermark/python-net/) and install it locally. Wheels are published for the following four platforms: - **Windows 64-bit**: file name ends with `win_amd64.whl` - **Linux x64 (glibc)**: file name ends with `manylinux1_x86_64.whl` - **macOS Intel**: file name ends with `macosx_10_14_x86_64.whl` - **macOS Apple Silicon**: file name ends with `macosx_11_0_arm64.whl` Place the downloaded wheel into your project folder, then install it: {{< tabs "install-wheel">}} {{< tab "Windows (64-bit)" >}} ```ps py -m pip install ./groupdocs_watermark_net-26.6.0-py3-none-win_amd64.whl ``` {{< /tab >}} {{< tab "Linux (glibc)" >}} ```bash python3 -m pip install ./groupdocs_watermark_net-26.6.0-py3-none-manylinux1_x86_64.whl ``` {{< /tab >}} {{< tab "macOS (Intel)" >}} ```bash python3 -m pip install ./groupdocs_watermark_net-26.6.0-py3-none-macosx_10_14_x86_64.whl ``` {{< /tab >}} {{< tab "macOS (Apple Silicon)" >}} ```bash python3 -m pip install ./groupdocs_watermark_net-26.6.0-py3-none-macosx_11_0_arm64.whl ``` {{< /tab >}} {{< /tabs >}} Expected output: ```bash Processing ./groupdocs_watermark_net-26.6.0-py3-none-*.whl Installing collected packages: groupdocs-watermark-net Successfully installed groupdocs-watermark-net-26.6.0 ``` ## Platform Prerequisites On Windows no extra steps are required. On Linux and macOS, install the native libraries the rendering engine depends on: {{< tabs "platform-prereqs">}} {{< tab "Linux" >}} ```bash apt install libgdiplus libfontconfig1 libicu-dev ttf-mscorefonts-installer ``` {{< /tab >}} {{< tab "macOS" >}} ```bash brew install mono-libgdiplus ``` {{< /tab >}} {{< /tabs >}} ## Verify the Installation Confirm the package imported correctly and check the installed version: ```bash python -c "import groupdocs.watermark; print('GroupDocs.Watermark is ready')" ``` You can also list the installed package with `pip show groupdocs-watermark-net` to confirm the version and location. ## Next Steps - Follow the [Hello, World!]({{< ref "watermark/python-net/getting-started/hello-world.md" >}}) guide to add your first watermark. - Read the [Features Overview]({{< ref "watermark/python-net/getting-started/features-overview.md" >}}) to see everything you can do. - Clone the [examples repository](https://github.com/groupdocs-watermark/GroupDocs.Watermark-for-Python-via-.NET) and read [How to Run Examples]({{< ref "watermark/python-net/getting-started/how-to-run-examples.md" >}}) to try every documented scenario locally. --- ## GroupDocs.Watermark for Python via .NET Overview Path: https://docs.groupdocs.com/watermark/python-net/product-overview/ ## What is GroupDocs.Watermark? GroupDocs.Watermark for Python via .NET is a native Python library that adds, searches, and removes **text and image watermarks** across PDF, Word, Excel, PowerPoint, Visio, email, and image formats. It runs entirely on-premise, requires no Microsoft Office installation, and ships as a pre-built wheel for Windows, Linux, and macOS. Typical uses include: - **Document security** — stamp every file in a pipeline with a "Confidential" or "Draft" mark that is hard to remove with third-party tools. - **Branding** — overlay a logo or seal on documents and on the images embedded inside them. - **Cleanup and migration** — find and remove outdated labels or third-party watermarks before sharing or re-publishing. - **Compliance and tamper-resistance** — lock watermarks, add print-only PDF annotations, or rasterize pages so the watermark cannot be edited out. - **Auditing** — search documents for existing watermarks by text, image similarity, or formatting, and report or modify them. ## Key Capabilities | Capability | Description | |---|---| | **Text and image watermarks** | [Add styled text or image watermarks]({{< ref "watermark/python-net/developer-guide/basic-usage/add-text.md" >}}) with color, opacity, rotation, alignment, and sizing. | | **Customize and tile** | [Customize]({{< ref "watermark/python-net/developer-guide/basic-usage/customize.md" >}}) appearance and position, or [tile a watermark]({{< ref "watermark/python-net/developer-guide/basic-usage/adding-repeated-watermarks.md" >}}) across the whole page. | | **Advanced positioning** | [Absolute and relative positioning, margins, sizing, and rotation]({{< ref "watermark/python-net/developer-guide/advanced-usage/adding-watermarks/adding-text-watermarks.md" >}}). | | **Format-specific placement** | PDF [artifacts/annotations]({{< ref "watermark/python-net/developer-guide/advanced-usage/adding-watermarks/add-watermarks-to-pdf-documents/watermarks-in-pdf-document.md" >}}), [presentation slides]({{< ref "watermark/python-net/developer-guide/advanced-usage/adding-watermarks/add-watermarks-to-presentation-documents" >}}), [worksheets]({{< ref "watermark/python-net/developer-guide/advanced-usage/adding-watermarks/add-watermarks-to-spreadsheet-documents" >}}), [Visio pages]({{< ref "watermark/python-net/developer-guide/advanced-usage/adding-watermarks/add-watermarks-to-diagram-documents" >}}), and [Word sections]({{< ref "watermark/python-net/developer-guide/advanced-usage/adding-watermarks/add-watermarks-to-word-processing-documents" >}}). | | **Search and modify** | [Find watermarks by text, image, or formatting]({{< ref "watermark/python-net/developer-guide/advanced-usage/searching-and-modifying-watermarks/searching-watermarks.md" >}}), then [modify]({{< ref "watermark/python-net/developer-guide/advanced-usage/searching-and-modifying-watermarks/modifying-found-watermark-properties.md" >}}) or [remove]({{< ref "watermark/python-net/developer-guide/advanced-usage/searching-and-modifying-watermarks/removing-found-watermarks.md" >}}) them. | | **Content-tree access** | Work with existing shapes, attachments, backgrounds, and headers/footers via `get_content()`. | | **Images inside documents** | [Watermark the images embedded inside a document]({{< ref "watermark/python-net/developer-guide/advanced-usage/adding-watermarks/add-watermarks-to-images/adding-watermark-to-images-inside-a-document.md" >}}). | | **Tamper resistance** | [Lock watermarks]({{< ref "watermark/python-net/developer-guide/advanced-usage/adding-watermarks/add-watermarks-to-word-processing-documents/locking-watermark-in-word-processing-document.md" >}}), protect documents, and [rasterize PDF pages]({{< ref "watermark/python-net/developer-guide/advanced-usage/adding-watermarks/add-watermarks-to-pdf-documents/rasterize-document-or-page.md" >}}). | | **Document inspection** | [Read file type, page count, and size]({{< ref "watermark/python-net/developer-guide/basic-usage/get-document-info.md" >}}) without modifying the document. | | **Streams** | Load input from file-like objects — handy for cloud blobs and HTTP bodies. | | **On-premise** | No cloud calls, no Microsoft Office install, no network traffic. | ## Quick Example Add a text watermark to a document and save the result with just a few lines of code: {{< tabs "product-overview-add-watermark" >}} {{< tab "quick_example.py" >}} ```python from groupdocs.watermark import Watermarker from groupdocs.watermark.watermarks import TextWatermark, Font, Color def quick_example(): # Open the document, add a text watermark, and save the result with Watermarker("./document.docx") as watermarker: watermark = TextWatermark("CONFIDENTIAL", Font("Arial", 36)) watermark.foreground_color = Color.red watermark.opacity = 0.5 watermarker.add(watermark) watermarker.save("./watermarked.docx") if __name__ == "__main__": quick_example() ``` {{< /tab >}} {{< tab "document.docx" >}} {{< tab-text >}} `document.docx` is the sample file used in this example. Click [here](https://docs.groupdocs.com/watermark/python-net/_sample_files/product-overview/document.docx) to download it. {{< /tab-text >}} {{< /tab >}} {{< tab "watermarked.docx" >}} ```text Binary file (DOCX, 13 KB) ``` [Download full output](https://docs.groupdocs.com/watermark/python-net/_output_files/product-overview/quick_example/watermarked.docx) {{< /tab >}} {{< /tabs >}} For finer control, scale, rotate, and center the watermark: {{< tabs "product-overview-add-watermark-options" >}} {{< tab "watermark_with_options.py" >}} ```python from groupdocs.watermark import Watermarker from groupdocs.watermark.watermarks import TextWatermark, Font, Color, SizingType from groupdocs.watermark.common import HorizontalAlignment, VerticalAlignment def watermark_with_options(): with Watermarker("./document.docx") as watermarker: watermark = TextWatermark("CONFIDENTIAL", Font("Arial", 36)) watermark.foreground_color = Color.red watermark.opacity = 0.5 watermark.rotate_angle = 45.0 # Scale the watermark relative to the page and center it watermark.sizing_type = SizingType.SCALE_TO_PARENT_DIMENSIONS watermark.scale_factor = 0.8 watermark.horizontal_alignment = HorizontalAlignment.CENTER watermark.vertical_alignment = VerticalAlignment.CENTER watermarker.add(watermark) watermarker.save("./watermarked.docx") if __name__ == "__main__": watermark_with_options() ``` {{< /tab >}} {{< tab "document.docx" >}} {{< tab-text >}} `document.docx` is the sample file used in this example. Click [here](https://docs.groupdocs.com/watermark/python-net/_sample_files/product-overview/document.docx) to download it. {{< /tab-text >}} {{< /tab >}} {{< tab "watermarked.docx" >}} ```text Binary file (DOCX, 13 KB) ``` [Download full output](https://docs.groupdocs.com/watermark/python-net/_output_files/product-overview/watermark_with_options/watermarked.docx) {{< /tab >}} {{< /tabs >}} ## Where to next 1. **Install the package** — [Installation]({{< ref "watermark/python-net/getting-started/installation" >}}) walks through PyPI and offline wheel installation for Windows, Linux, and macOS. 2. **Add your first watermark** — [Quick Start Guide]({{< ref "watermark/python-net/getting-started/quick-start-guide" >}}) stamps a document in five minutes. 3. **Explore the examples** — [How to Run Examples]({{< ref "watermark/python-net/getting-started/how-to-run-examples.md" >}}) clones the runnable repository and runs every documented scenario locally or in Docker. 4. **Use it in depth** — the [Developer Guide]({{< ref "watermark/python-net/developer-guide" >}}) covers adding, customizing, searching, modifying, and removing watermarks across every supported format. 5. **Licensing** — [Licensing and Subscription]({{< ref "watermark/python-net/getting-started/licensing-and-subscription.md" >}}) explains evaluation mode and how to apply a license. --- ## Searching watermarks Path: https://docs.groupdocs.com/watermark/python-net/searching-watermarks/ Use `Watermarker.search()` to scan a document for objects that can be treated as watermarks — including watermarks added by third-party tools. Without criteria, `search()` returns a subset such as backgrounds and floating objects; pass a criteria object to narrow the results. ## Search for possible watermarks The example below searches a watermarked PDF and prints the text, page, and size of each possible watermark. {{< tabs "code-example-searching-watermarks">}} {{< tab "search_watermarks.py" >}} ```python from groupdocs.watermark import Watermarker def search_watermarks(): with Watermarker("./document.pdf") as watermarker: possible = watermarker.search() print(f"Found {len(possible)} possible watermark(s).") for wm in possible: text = (wm.text or "").strip() print(f"- page={wm.page_number} text={text!r} size={round(wm.width)}x{round(wm.height)}") if __name__ == "__main__": search_watermarks() ``` {{< /tab >}} {{< tab "document.pdf" >}} {{< tab-text >}} `document.pdf` is the sample file used in this example. Click [here](https://docs.groupdocs.com/watermark/python-net/_sample_files/developer-guide/advanced-usage/searching-and-modifying-watermarks/searching-watermarks/document.pdf) to download it. {{< /tab-text >}} {{< /tab >}} {{< tab "search-watermarks.txt" >}} ```text Found 8 possible watermark(s). - page=1 text='CONFIDENTIAL' size=268x36 - page=1 text='' size=230x69 - page=1 text='' size=460x287 - page=2 text='CONFIDENTIAL' size=268x36 - page=3 text='CONFIDENTIAL' size=268x36 - page=None text='https://auroravisuals.example/legal/msa' size=128x14 - page=None text='https://auroravisuals.example/legal/licensing' size=173x14 - page=None text='https://auroravisuals.example/portfolio' size=76x14 ``` [Download full output](https://docs.groupdocs.com/watermark/python-net/_output_files/developer-guide/advanced-usage/searching-and-modifying-watermarks/searching-watermarks/search_watermarks/search-watermarks.txt) {{< /tab >}} {{< /tabs >}} Each possible watermark exposes `text`, `image_data`, `x`, `y`, `width`, `height`, `rotate_angle`, and `page_number`. ## Search criteria Large documents may contain many candidates. Use dedicated criteria to find exactly what you need. ### Text search criteria Find watermarks by exact text. {{< tabs "code-example-search-by-text">}} {{< tab "search_by_text.py" >}} ```python from groupdocs.watermark import Watermarker from groupdocs.watermark.search.search_criteria import TextSearchCriteria def search_by_text(): with Watermarker("./document.pdf") as watermarker: possible = watermarker.search(TextSearchCriteria("CONFIDENTIAL")) print("Found", len(possible), "possible watermark(s)") if __name__ == "__main__": search_by_text() ``` {{< /tab >}} {{< tab "document.pdf" >}} {{< tab-text >}} `document.pdf` is the sample file used in this example. Click [here](https://docs.groupdocs.com/watermark/python-net/_sample_files/developer-guide/advanced-usage/searching-and-modifying-watermarks/searching-watermarks/document.pdf) to download it. {{< /tab-text >}} {{< /tab >}} {{< tab "search-by-text.txt" >}} ```text Found 6 possible watermark(s) ``` [Download full output](https://docs.groupdocs.com/watermark/python-net/_output_files/developer-guide/advanced-usage/searching-and-modifying-watermarks/searching-watermarks/search_by_text/search-by-text.txt) {{< /tab >}} {{< /tabs >}} ### Regular expression search criteria Pass a compiled regular expression to `TextSearchCriteria`. {{< tabs "code-example-search-by-regex">}} {{< tab "search_by_regex.py" >}} ```python import re from groupdocs.watermark import Watermarker from groupdocs.watermark.search.search_criteria import TextSearchCriteria def search_by_regex(): with Watermarker("./document.pdf") as watermarker: possible = watermarker.search(TextSearchCriteria(re.compile(r"^CONFIDENTIAL$"))) print("Found", len(possible), "possible watermark(s)") if __name__ == "__main__": search_by_regex() ``` {{< /tab >}} {{< tab "document.pdf" >}} {{< tab-text >}} `document.pdf` is the sample file used in this example. Click [here](https://docs.groupdocs.com/watermark/python-net/_sample_files/developer-guide/advanced-usage/searching-and-modifying-watermarks/searching-watermarks/document.pdf) to download it. {{< /tab-text >}} {{< /tab >}} {{< tab "search-by-regex.txt" >}} ```text Found 6 possible watermark(s) ``` [Download full output](https://docs.groupdocs.com/watermark/python-net/_output_files/developer-guide/advanced-usage/searching-and-modifying-watermarks/searching-watermarks/search_by_regex/search-by-regex.txt) {{< /tab >}} {{< /tabs >}} {{< alert style="info" >}} When a `TextSearchCriteria` is provided, the API also scans the main document text along with shapes, XObjects, annotations, and other objects. {{< /alert >}} ### Image search criteria Find image watermarks that are visually similar to a sample image using perceptual hashing (DCT hash). Control sensitivity with `max_difference` (0–1). {{< tabs "code-example-search-by-image">}} {{< tab "search_by_image.py" >}} ```python from groupdocs.watermark import Watermarker from groupdocs.watermark.search.search_criteria import ImageDctHashSearchCriteria def search_by_image(): with Watermarker("./document.pdf") as watermarker: criteria = ImageDctHashSearchCriteria("./logo.png") criteria.max_difference = 0.9 possible = watermarker.search(criteria) print("Found", len(possible), "possible watermark(s)") if __name__ == "__main__": search_by_image() ``` {{< /tab >}} {{< tab "document.pdf" >}} {{< tab-text >}} `document.pdf` and `logo.png` are the sample files used in this example. Download [document.pdf](https://docs.groupdocs.com/watermark/python-net/_sample_files/developer-guide/advanced-usage/searching-and-modifying-watermarks/searching-watermarks/document.pdf) and [logo.png](https://docs.groupdocs.com/watermark/python-net/_sample_files/developer-guide/advanced-usage/searching-and-modifying-watermarks/searching-watermarks/logo.png). {{< /tab-text >}} {{< /tab >}} {{< tab "search-by-image.txt" >}} ```text Found 2 possible watermark(s) ``` [Download full output](https://docs.groupdocs.com/watermark/python-net/_output_files/developer-guide/advanced-usage/searching-and-modifying-watermarks/searching-watermarks/search_by_image/search-by-image.txt) {{< /tab >}} {{< /tabs >}} Other image criteria: - `ImageColorHistogramSearchCriteria` — robust to rotation, scaling, and translation. - `ImageThumbnailSearchCriteria` — robust to rotation, scaling, and minor color changes. ### Combined search criteria Combine criteria with `and_()`, `or_()`, and `not_()`. {{< tabs "code-example-search-combined">}} {{< tab "search_combined.py" >}} ```python from groupdocs.watermark import Watermarker from groupdocs.watermark.search.search_criteria import ( ImageDctHashSearchCriteria, TextSearchCriteria, RotateAngleSearchCriteria, ) def search_combined(): with Watermarker("./document.pdf") as watermarker: image_criteria = ImageDctHashSearchCriteria("./logo.png") image_criteria.max_difference = 0.9 text_criteria = TextSearchCriteria("CONFIDENTIAL") angle_criteria = RotateAngleSearchCriteria(30, 60) combined = image_criteria.or_(text_criteria).and_(angle_criteria) possible = watermarker.search(combined) print("Found", len(possible), "possible watermark(s)") if __name__ == "__main__": search_combined() ``` {{< /tab >}} {{< tab "document.pdf" >}} {{< tab-text >}} `document.pdf` and `logo.png` are the sample files used in this example. Download [document.pdf](https://docs.groupdocs.com/watermark/python-net/_sample_files/developer-guide/advanced-usage/searching-and-modifying-watermarks/searching-watermarks/document.pdf) and [logo.png](https://docs.groupdocs.com/watermark/python-net/_sample_files/developer-guide/advanced-usage/searching-and-modifying-watermarks/searching-watermarks/logo.png). {{< /tab-text >}} {{< /tab >}} {{< tab "search-combined.txt" >}} ```text Found 3 possible watermark(s) ``` [Download full output](https://docs.groupdocs.com/watermark/python-net/_output_files/developer-guide/advanced-usage/searching-and-modifying-watermarks/searching-watermarks/search_combined/search-combined.txt) {{< /tab >}} {{< /tabs >}} ### Text formatting search criteria Find watermarks by text formatting such as font, size, and color ranges. {{< tabs "code-example-search-by-formatting">}} {{< tab "search_by_formatting.py" >}} ```python from groupdocs.watermark import Watermarker from groupdocs.watermark.search.search_criteria import TextFormattingSearchCriteria, ColorRange def search_by_formatting(): with Watermarker("./document.pdf") as watermarker: criteria = TextFormattingSearchCriteria() criteria.foreground_color_range = ColorRange() criteria.foreground_color_range.min_hue = -15 criteria.foreground_color_range.max_hue = 15 criteria.foreground_color_range.min_brightness = 0.01 criteria.foreground_color_range.max_brightness = 0.99 criteria.min_font_size = 19 criteria.max_font_size = 42 possible = watermarker.search(criteria) print("Found", len(possible), "possible watermark(s)") if __name__ == "__main__": search_by_formatting() ``` {{< /tab >}} {{< tab "document.pdf" >}} {{< tab-text >}} `document.pdf` is the sample file used in this example. Click [here](https://docs.groupdocs.com/watermark/python-net/_sample_files/developer-guide/advanced-usage/searching-and-modifying-watermarks/searching-watermarks/document.pdf) to download it. {{< /tab-text >}} {{< /tab >}} {{< tab "search-by-formatting.txt" >}} ```text Found 3 possible watermark(s) ``` [Download full output](https://docs.groupdocs.com/watermark/python-net/_output_files/developer-guide/advanced-usage/searching-and-modifying-watermarks/searching-watermarks/search_by_formatting/search-by-formatting.txt) {{< /tab >}} {{< /tabs >}} {{< alert style="info" >}} Searching by **color and size** is the most robust way to match a text watermark. You can also constrain `font_name` and `font_bold`, but bold fonts are often embedded under a fused subset name (for example `ArialBold`) rather than `Arial` with a separate bold flag, so a `font_name = "Arial"` filter may miss them. {{< /alert >}} ## Search watermarks in particular objects Limit the search to specific object types to improve performance — either globally via `WatermarkerSettings.searchable_objects`, or per instance via `Watermarker.searchable_objects`. The flags live in `groupdocs.watermark.search.objects`. {{< tabs "code-example-search-in-objects">}} {{< tab "search_in_objects.py" >}} ```python from groupdocs.watermark import Watermarker, WatermarkerSettings from groupdocs.watermark.search.objects import ( SearchableObjects, WordProcessingSearchableObjects, PdfSearchableObjects, ) def search_in_objects(): settings = WatermarkerSettings() settings.searchable_objects = SearchableObjects( word_processing_searchable_objects=WordProcessingSearchableObjects.HYPERLINKS | WordProcessingSearchableObjects.TEXT, pdf_searchable_objects=PdfSearchableObjects.ALL, ) with Watermarker("./document.pdf", settings) as watermarker: possible = watermarker.search() print("Found", len(possible), "possible watermark(s)") if __name__ == "__main__": search_in_objects() ``` {{< /tab >}} {{< tab "document.pdf" >}} {{< tab-text >}} `document.pdf` is the sample file used in this example. Click [here](https://docs.groupdocs.com/watermark/python-net/_sample_files/developer-guide/advanced-usage/searching-and-modifying-watermarks/searching-watermarks/document.pdf) to download it. {{< /tab-text >}} {{< /tab >}} {{< tab "search-in-objects.txt" >}} ```text Found 8 possible watermark(s) ``` [Download full output](https://docs.groupdocs.com/watermark/python-net/_output_files/developer-guide/advanced-usage/searching-and-modifying-watermarks/searching-watermarks/search_in_objects/search-in-objects.txt) {{< /tab >}} {{< /tabs >}} ### Search for hyperlink watermarks Restrict the search to hyperlinks for a single `Watermarker` instance: {{< tabs "code-example-search-hyperlinks">}} {{< tab "search_hyperlinks.py" >}} ```python from groupdocs.watermark import Watermarker from groupdocs.watermark.search.objects import PdfSearchableObjects def search_hyperlinks(): with Watermarker("./document.pdf") as watermarker: watermarker.searchable_objects.pdf_searchable_objects = PdfSearchableObjects.HYPERLINKS possible = watermarker.search() print("Found", len(possible), "hyperlink watermark(s)") if __name__ == "__main__": search_hyperlinks() ``` {{< /tab >}} {{< tab "document.pdf" >}} {{< tab-text >}} `document.pdf` is the sample file used in this example. Click [here](https://docs.groupdocs.com/watermark/python-net/_sample_files/developer-guide/advanced-usage/searching-and-modifying-watermarks/searching-watermarks/document.pdf) to download it. {{< /tab-text >}} {{< /tab >}} {{< tab "search-hyperlinks.txt" >}} ```text Found 3 hyperlink watermark(s) ``` [Download full output](https://docs.groupdocs.com/watermark/python-net/_output_files/developer-guide/advanced-usage/searching-and-modifying-watermarks/searching-watermarks/search_hyperlinks/search-hyperlinks.txt) {{< /tab >}} {{< /tabs >}} ## Search text while skipping unreadable characters Enable tolerant matching when text contains unreadable characters between letters. {{< tabs "code-example-search-skip-unreadable">}} {{< tab "search_skip_unreadable.py" >}} ```python from groupdocs.watermark import Watermarker from groupdocs.watermark.search.search_criteria import TextSearchCriteria def search_skip_unreadable(): with Watermarker("./document.pdf") as watermarker: criterion = TextSearchCriteria("CONFIDENTIAL") criterion.skip_unreadable_characters = True possible = watermarker.search(criterion) print("Found", len(possible), "possible watermark(s)") if __name__ == "__main__": search_skip_unreadable() ``` {{< /tab >}} {{< tab "document.pdf" >}} {{< tab-text >}} `document.pdf` is the sample file used in this example. Click [here](https://docs.groupdocs.com/watermark/python-net/_sample_files/developer-guide/advanced-usage/searching-and-modifying-watermarks/searching-watermarks/document.pdf) to download it. {{< /tab-text >}} {{< /tab >}} {{< tab "search-skip-unreadable.txt" >}} ```text Found 6 possible watermark(s) ``` [Download full output](https://docs.groupdocs.com/watermark/python-net/_output_files/developer-guide/advanced-usage/searching-and-modifying-watermarks/searching-watermarks/search_skip_unreadable/search-skip-unreadable.txt) {{< /tab >}} {{< /tabs >}} --- ## Shapes in spreadsheet document Path: https://docs.groupdocs.com/watermark/python-net/shapes-in-spreadsheet-document/ `Watermarker.get_content()` returns a `SpreadsheetContent` whose `worksheets` each expose a `shapes` collection (along with `charts`, `attachments`, and `background_image`). You can iterate the shapes to read their properties, modify them, or remove them. ## Extract information about shapes {{< tabs "code-example-spreadsheet-shapes">}} {{< tab "extract_shapes.py" >}} ```python from groupdocs.watermark import Watermarker from groupdocs.watermark.options.spreadsheet import SpreadsheetLoadOptions def extract_shapes(): with Watermarker("./spreadsheet.xlsx", SpreadsheetLoadOptions()) as watermarker: content = watermarker.get_content() for i, worksheet in enumerate(content.worksheets): print(f"Worksheet {i}: shapes={len(worksheet.shapes)}") for shape in worksheet.shapes: text = (shape.text or "").strip() print(f" shape text={text!r} size={round(shape.width)}x{round(shape.height)} " f"word_art={shape.is_word_art}") if __name__ == "__main__": extract_shapes() ``` {{< /tab >}} {{< tab "spreadsheet.xlsx" >}} {{< tab-text >}} `spreadsheet.xlsx` is the sample file used in this example. Click [here](https://docs.groupdocs.com/watermark/python-net/_sample_files/developer-guide/advanced-usage/adding-watermarks/shapes-in-spreadsheet-document/spreadsheet.xlsx) to download it. {{< /tab-text >}} {{< /tab >}} {{< tab "extract-shapes.txt" >}} ```text Worksheet 0: shapes=0 Worksheet 1: shapes=0 ``` [Download full output](https://docs.groupdocs.com/watermark/python-net/_output_files/developer-guide/advanced-usage/adding-watermarks/add-watermarks-to-spreadsheet-documents/shapes-in-spreadsheet-document/extract_shapes/extract-shapes.txt) {{< /tab >}} {{< /tabs >}} Each shape exposes `text`, `image`, `name`, `alternative_text`, `x`, `y`, `width`, `height`, `rotate_angle`, and `is_word_art`. ## Remove and modify shapes The `shapes` collection supports `remove_at(index)` and `remove(shape)`. Iterate in reverse when removing by index: {{< tabs "code-example-spreadsheet-remove-shapes">}} {{< tab "remove_and_modify_shapes.py" >}} ```python from groupdocs.watermark import Watermarker from groupdocs.watermark.options.spreadsheet import SpreadsheetLoadOptions def remove_and_modify_shapes(): with Watermarker("./spreadsheet.xlsx", SpreadsheetLoadOptions()) as watermarker: content = watermarker.get_content() for worksheet in content.worksheets: for i in range(len(worksheet.shapes) - 1, -1, -1): if worksheet.shapes[i].text == "CONFIDENTIAL": worksheet.shapes.remove_at(i) watermarker.save("./output.xlsx") if __name__ == "__main__": remove_and_modify_shapes() ``` {{< /tab >}} {{< tab "spreadsheet.xlsx" >}} {{< tab-text >}} `spreadsheet.xlsx` is the sample file used in this example. Click [here](https://docs.groupdocs.com/watermark/python-net/_sample_files/developer-guide/advanced-usage/adding-watermarks/shapes-in-spreadsheet-document/spreadsheet.xlsx) to download it. {{< /tab-text >}} {{< /tab >}} {{< tab "output.xlsx" >}} ```text Binary file (XLSX, 9 KB) ``` [Download full output](https://docs.groupdocs.com/watermark/python-net/_output_files/developer-guide/advanced-usage/adding-watermarks/add-watermarks-to-spreadsheet-documents/shapes-in-spreadsheet-document/remove_and_modify_shapes/output.xlsx) {{< /tab >}} {{< /tabs >}} You can replace a shape's text by assigning to `shape.text`, replace its image by assigning a `SpreadsheetWatermarkableImage` to `shape.image`, set a hyperlink via `shape.hyperlink`, and modify its position and size. --- ## Adding text watermarks Path: https://docs.groupdocs.com/watermark/python-net/adding-text-watermarks/ Using text watermarks is an effective way to protect document content. By overlaying sensitive documents with watermarks such as "Confidential" or "Draft", you can deter unauthorized distribution and reinforce data security. The following example shows how to add a scaled, rotated text watermark to a document and save the result. {{< tabs "code-example-adding-text-watermarks">}} {{< tab "add_text_watermark.py" >}} ```python from groupdocs.watermark import Watermarker from groupdocs.watermark.watermarks import TextWatermark, Font, Color, SizingType from groupdocs.watermark.common import HorizontalAlignment, VerticalAlignment def add_text_watermark(): with Watermarker("./sample.pdf") as watermarker: watermark = TextWatermark("CONFIDENTIAL", Font("Arial", 36.0)) watermark.foreground_color = Color.red watermark.horizontal_alignment = HorizontalAlignment.CENTER watermark.vertical_alignment = VerticalAlignment.CENTER watermark.sizing_type = SizingType.SCALE_TO_PARENT_DIMENSIONS watermark.scale_factor = 0.9 watermark.rotate_angle = 45.0 watermark.opacity = 0.5 watermarker.add(watermark) watermarker.save("./output.pdf") if __name__ == "__main__": add_text_watermark() ``` {{< /tab >}} {{< tab "sample.pdf" >}} {{< tab-text >}} `sample.pdf` is the sample file used in this example. Click [here](https://docs.groupdocs.com/watermark/python-net/_sample_files/developer-guide/advanced-usage/adding-watermarks/adding-text-watermarks/sample.pdf) to download it. {{< /tab-text >}} {{< /tab >}} {{< tab "output.pdf" >}} ```text Binary file (PDF, 352 KB) ``` [Download full output](https://docs.groupdocs.com/watermark/python-net/_output_files/developer-guide/advanced-usage/adding-watermarks/adding-text-watermarks/add_text_watermark/output.pdf) {{< /tab >}} {{< /tabs >}} If a document consists of multiple parts (pages, worksheets, slides, frames, etc.), the watermark is added to each of them. You can target specific parts via the `PagesSetup` property: {{< tabs "code-example-add-watermark-to-pages">}} {{< tab "add_watermark_to_pages.py" >}} ```python from groupdocs.watermark import Watermarker from groupdocs.watermark.watermarks import TextWatermark, Font, PagesSetup def add_watermark_to_pages(): with Watermarker("./sample.pdf") as watermarker: watermark = TextWatermark("Test watermark", Font("Arial", 19.0)) watermark.pages_setup = PagesSetup() watermark.pages_setup.pages = [1, 3] watermarker.add(watermark) watermarker.save("./output.pdf") if __name__ == "__main__": add_watermark_to_pages() ``` {{< /tab >}} {{< tab "sample.pdf" >}} {{< tab-text >}} `sample.pdf` is the sample file used in this example. Click [here](https://docs.groupdocs.com/watermark/python-net/_sample_files/developer-guide/advanced-usage/adding-watermarks/adding-text-watermarks/sample.pdf) to download it. {{< /tab-text >}} {{< /tab >}} {{< tab "output.pdf" >}} ```text Binary file (PDF, 353 KB) ``` [Download full output](https://docs.groupdocs.com/watermark/python-net/_output_files/developer-guide/advanced-usage/adding-watermarks/adding-text-watermarks/add_watermark_to_pages/output.pdf) {{< /tab >}} {{< /tabs >}} ## Sizing and positioning of a watermark ### Absolute watermark positioning You can place a watermark at an absolute position by setting `x`, `y`, `width`, and `height`. Values are measured in the default units of the document. {{< tabs "code-example-absolute-positioning">}} {{< tab "add_watermark_absolute.py" >}} ```python from groupdocs.watermark import Watermarker from groupdocs.watermark.watermarks import TextWatermark, Font def add_watermark_absolute(): with Watermarker("./sample.pdf") as watermarker: watermark = TextWatermark("Test watermark", Font("Times New Roman", 8.0)) watermark.x = 10 watermark.y = 20 watermark.width = 100 watermark.height = 40 watermarker.add(watermark) watermarker.save("./output.pdf") if __name__ == "__main__": add_watermark_absolute() ``` {{< /tab >}} {{< tab "sample.pdf" >}} {{< tab-text >}} `sample.pdf` is the sample file used in this example. Click [here](https://docs.groupdocs.com/watermark/python-net/_sample_files/developer-guide/advanced-usage/adding-watermarks/adding-text-watermarks/sample.pdf) to download it. {{< /tab-text >}} {{< /tab >}} {{< tab "output.pdf" >}} ```text Binary file (PDF, 357 KB) ``` [Download full output](https://docs.groupdocs.com/watermark/python-net/_output_files/developer-guide/advanced-usage/adding-watermarks/adding-text-watermarks/add_watermark_absolute/output.pdf) {{< /tab >}} {{< /tabs >}} {{< alert style="warning" >}}The origin of coordinates differs across document types (relative positioning doesn't have these specifics and can be used as a unified positioning approach).{{< /alert >}} The following table lists the unit of measure and origin of coordinates for each document format: | Document Format | Unit of Measure | Origin of Coordinates | | --- | --- | --- | | PDF | Point | Left bottom corner of page | | WordProcessing | Point | Left top corner of page | | Spreadsheet | Point | Left top corner of worksheet | | Presentation | Point | Left top corner of slide | | Image | Pixel | Left top corner of image (frame) | | Diagram | Point | Left top corner of page | ### Relative watermark positioning Instead of exact coordinates, use parent-relative alignment and set offsets with `margins`. {{< tabs "code-example-relative-positioning">}} {{< tab "add_watermark_relative.py" >}} ```python from groupdocs.watermark import Watermarker from groupdocs.watermark.watermarks import TextWatermark, Font from groupdocs.watermark.common import HorizontalAlignment, VerticalAlignment def add_watermark_relative(): with Watermarker("./sample.pdf") as watermarker: watermark = TextWatermark("Test watermark", Font("Calibri", 12.0)) watermark.horizontal_alignment = HorizontalAlignment.RIGHT watermark.vertical_alignment = VerticalAlignment.BOTTOM watermark.margins.right = 10 watermark.margins.bottom = 5 watermarker.add(watermark) watermarker.save("./output.pdf") if __name__ == "__main__": add_watermark_relative() ``` {{< /tab >}} {{< tab "sample.pdf" >}} {{< tab-text >}} `sample.pdf` is the sample file used in this example. Click [here](https://docs.groupdocs.com/watermark/python-net/_sample_files/developer-guide/advanced-usage/adding-watermarks/adding-text-watermarks/sample.pdf) to download it. {{< /tab-text >}} {{< /tab >}} {{< tab "output.pdf" >}} ```text Binary file (PDF, 536 KB) ``` [Download full output](https://docs.groupdocs.com/watermark/python-net/_output_files/developer-guide/advanced-usage/adding-watermarks/adding-text-watermarks/add_watermark_relative/output.pdf) {{< /tab >}} {{< /tabs >}} {{< alert style="warning" >}}Excel worksheets don't have explicit borders, therefore the most bottom-right non-empty cell is used to determine the working-area size.{{< /alert >}} ### Using the MarginType property Set relative margins using `MarginType`, where the values are interpreted as a portion of the parent size (0.0–1.0). {{< tabs "code-example-margin-type">}} {{< tab "add_watermark_margin_type.py" >}} ```python from groupdocs.watermark import Watermarker from groupdocs.watermark.watermarks import TextWatermark, Font, MarginType from groupdocs.watermark.common import HorizontalAlignment, VerticalAlignment def add_watermark_margin_type(): with Watermarker("./sample.pdf") as watermarker: watermark = TextWatermark("Test watermark", Font("Calibri", 12.0)) watermark.horizontal_alignment = HorizontalAlignment.RIGHT watermark.vertical_alignment = VerticalAlignment.BOTTOM watermark.margins.margin_type = MarginType.RELATIVE_TO_PARENT_DIMENSIONS watermark.margins.right = 0.1 watermark.margins.bottom = 0.2 watermarker.add(watermark) watermarker.save("./output.pdf") if __name__ == "__main__": add_watermark_margin_type() ``` {{< /tab >}} {{< tab "sample.pdf" >}} {{< tab-text >}} `sample.pdf` is the sample file used in this example. Click [here](https://docs.groupdocs.com/watermark/python-net/_sample_files/developer-guide/advanced-usage/adding-watermarks/adding-text-watermarks/sample.pdf) to download it. {{< /tab-text >}} {{< /tab >}} {{< tab "output.pdf" >}} ```text Binary file (PDF, 537 KB) ``` [Download full output](https://docs.groupdocs.com/watermark/python-net/_output_files/developer-guide/advanced-usage/adding-watermarks/adding-text-watermarks/add_watermark_margin_type/output.pdf) {{< /tab >}} {{< /tabs >}} ### Size types Scale the watermark relative to the parent size using `sizing_type` and `scale_factor`. {{< tabs "code-example-size-types">}} {{< tab "add_watermark_size_type.py" >}} ```python from groupdocs.watermark import Watermarker from groupdocs.watermark.watermarks import TextWatermark, Font, SizingType def add_watermark_size_type(): with Watermarker("./sample.pdf") as watermarker: watermark = TextWatermark("This is a test watermark", Font("Calibri", 12.0)) watermark.sizing_type = SizingType.SCALE_TO_PARENT_DIMENSIONS watermark.scale_factor = 0.5 watermarker.add(watermark) watermarker.save("./output.pdf") if __name__ == "__main__": add_watermark_size_type() ``` {{< /tab >}} {{< tab "sample.pdf" >}} {{< tab-text >}} `sample.pdf` is the sample file used in this example. Click [here](https://docs.groupdocs.com/watermark/python-net/_sample_files/developer-guide/advanced-usage/adding-watermarks/adding-text-watermarks/sample.pdf) to download it. {{< /tab-text >}} {{< /tab >}} {{< tab "output.pdf" >}} ```text Binary file (PDF, 537 KB) ``` [Download full output](https://docs.groupdocs.com/watermark/python-net/_output_files/developer-guide/advanced-usage/adding-watermarks/adding-text-watermarks/add_watermark_size_type/output.pdf) {{< /tab >}} {{< /tabs >}} {{< alert style="info" >}}Using relative size and positioning is the simplest way to add a watermark to a document of any type.{{< /alert >}} ### Watermark rotation Rotate a watermark by setting `rotate_angle` in degrees. Positive values mean clockwise. {{< tabs "code-example-watermark-rotation">}} {{< tab "add_watermark_rotated.py" >}} ```python from groupdocs.watermark import Watermarker from groupdocs.watermark.watermarks import TextWatermark, Font, SizingType from groupdocs.watermark.common import HorizontalAlignment, VerticalAlignment def add_watermark_rotated(): with Watermarker("./sample.pdf") as watermarker: watermark = TextWatermark("Test watermark", Font("Calibri", 8.0)) watermark.horizontal_alignment = HorizontalAlignment.RIGHT watermark.vertical_alignment = VerticalAlignment.TOP watermark.sizing_type = SizingType.SCALE_TO_PARENT_DIMENSIONS watermark.scale_factor = 0.5 watermark.rotate_angle = 45 watermarker.add(watermark) watermarker.save("./output.pdf") if __name__ == "__main__": add_watermark_rotated() ``` {{< /tab >}} {{< tab "sample.pdf" >}} {{< tab-text >}} `sample.pdf` is the sample file used in this example. Click [here](https://docs.groupdocs.com/watermark/python-net/_sample_files/developer-guide/advanced-usage/adding-watermarks/adding-text-watermarks/sample.pdf) to download it. {{< /tab-text >}} {{< /tab >}} {{< tab "output.pdf" >}} ```text Binary file (PDF, 537 KB) ``` [Download full output](https://docs.groupdocs.com/watermark/python-net/_output_files/developer-guide/advanced-usage/adding-watermarks/adding-text-watermarks/add_watermark_rotated/output.pdf) {{< /tab >}} {{< /tabs >}} When a rotation angle is set, the watermark size is taken to be the axis-aligned bounding-box size. The picture below shows the result of the snippet above — the actual watermark bounds are blue and the bounding box is red. The bounding-box size is used to calculate the watermark's relative size. ![adding-text-watermarks](https://docs.groupdocs.com/watermark/python-net/images/adding-text-watermarks.png) ### Using custom fonts You can use custom TrueType fonts by specifying a folder path in the `Font` constructor. {{< tabs "code-example-custom-fonts">}} {{< tab "add_custom_font_watermark.py" >}} ```python from groupdocs.watermark import Watermarker from groupdocs.watermark.watermarks import TextWatermark, Font, Color def add_custom_font_watermark(): # Point fonts_folder at a directory containing your TrueType (.ttf) fonts fonts_folder = r"c:\CustomFonts" with Watermarker("./sample.pdf") as watermarker: watermark = TextWatermark("Test watermark", Font("CustomFontName", fonts_folder, 36.0)) watermark.foreground_color = Color.blue watermark.opacity = 0.5 watermark.x = 10 watermark.y = 10 watermarker.add(watermark) watermarker.save("./output.pdf") if __name__ == "__main__": add_custom_font_watermark() ``` {{< /tab >}} {{< tab "sample.pdf" >}} {{< tab-text >}} `sample.pdf` is the sample file used in this example. Click [here](https://docs.groupdocs.com/watermark/python-net/_sample_files/developer-guide/advanced-usage/adding-watermarks/adding-text-watermarks/sample.pdf) to download it. Supply your own TrueType fonts in the folder referenced by `fonts_folder`. {{< /tab-text >}} {{< /tab >}} {{< /tabs >}} ### Considering parent margins By default, page margins are ignored and the maximum available space is used. To align the watermark with the page margins, set `consider_parent_margins` to `True`. ![adding-text-watermarks_1](https://docs.groupdocs.com/watermark/python-net/images/adding-text-watermarks_1.png) As you can see, the watermark goes beyond the page margins. To change this behavior, set the [consider_parent_margins](https://reference.groupdocs.com/watermark/python-net/) property to `True` (as shown below). {{< tabs "code-example-parent-margins">}} {{< tab "add_watermark_parent_margins.py" >}} ```python from groupdocs.watermark import Watermarker from groupdocs.watermark.watermarks import TextWatermark, Font, Color, SizingType from groupdocs.watermark.common import HorizontalAlignment, VerticalAlignment def add_watermark_parent_margins(): with Watermarker("./sample.pdf") as watermarker: watermark = TextWatermark("Test watermark", Font("Arial", 42.0)) watermark.horizontal_alignment = HorizontalAlignment.RIGHT watermark.vertical_alignment = VerticalAlignment.TOP watermark.sizing_type = SizingType.SCALE_TO_PARENT_DIMENSIONS watermark.scale_factor = 1.0 watermark.rotate_angle = 45 watermark.foreground_color = Color.red watermark.background_color = Color.aqua watermark.consider_parent_margins = True watermarker.add(watermark) watermarker.save("./output.pdf") if __name__ == "__main__": add_watermark_parent_margins() ``` {{< /tab >}} {{< tab "sample.pdf" >}} {{< tab-text >}} `sample.pdf` is the sample file used in this example. Click [here](https://docs.groupdocs.com/watermark/python-net/_sample_files/developer-guide/advanced-usage/adding-watermarks/adding-text-watermarks/sample.pdf) to download it. {{< /tab-text >}} {{< /tab >}} {{< tab "output.pdf" >}} ```text Binary file (PDF, 355 KB) ``` [Download full output](https://docs.groupdocs.com/watermark/python-net/_output_files/developer-guide/advanced-usage/adding-watermarks/adding-text-watermarks/add_watermark_parent_margins/output.pdf) {{< /tab >}} {{< /tabs >}} Now the watermark is aligned with respect to the page margins. ![adding-text-watermarks_2](https://docs.groupdocs.com/watermark/python-net/images/adding-text-watermarks_2.png) ## Watermarks in documents of different types Watermarks are represented by different objects in different formats, and some properties may not be supported for a specific format (for example, background color for WordArt in Word documents). See [Features Overview]({{< ref "watermark/python-net/getting-started/features-overview.md" >}}) for details. --- ## Adding watermark to images inside a document Path: https://docs.groupdocs.com/watermark/python-net/adding-watermark-to-images-inside-a-document/ Beyond watermarking a document's pages, you can watermark the **images embedded inside** it. `Watermarker.get_images()` returns a collection of every raster image in the document, regardless of format, and each image accepts its own watermark via `add()`. ## Watermark every embedded image The example finds all embedded images, watermarks the larger ones (over 100×100), and saves the result. {{< tabs "code-example-watermark-images-inside">}} {{< tab "watermark_images_inside.py" >}} ```python from groupdocs.watermark import Watermarker from groupdocs.watermark.watermarks import TextWatermark, Font, Color, SizingType from groupdocs.watermark.options.pdf import PdfLoadOptions def watermark_images_inside(): with Watermarker("./document.pdf", PdfLoadOptions()) as watermarker: watermark = TextWatermark("PROTECTED", Font("Arial", 8.0)) watermark.foreground_color = Color.red watermark.sizing_type = SizingType.SCALE_TO_PARENT_DIMENSIONS watermark.scale_factor = 1.0 # Every raster image embedded in the document for image in watermarker.get_images(): # Skip tiny images such as icons or bullets if image.width > 100 and image.height > 100: image.add(watermark) watermarker.save("./output.pdf") if __name__ == "__main__": watermark_images_inside() ``` {{< /tab >}} {{< tab "document.pdf" >}} {{< tab-text >}} `document.pdf` is the sample file used in this example. Click [here](https://docs.groupdocs.com/watermark/python-net/_sample_files/developer-guide/advanced-usage/adding-watermarks/adding-watermark-to-images-inside-a-document/document.pdf) to download it. {{< /tab-text >}} {{< /tab >}} {{< tab "output.pdf" >}} ```text Binary file (PDF, 1596 KB) ``` [Download full output](https://docs.groupdocs.com/watermark/python-net/_output_files/developer-guide/advanced-usage/adding-watermarks/adding-watermark-to-images-inside-a-document/watermark_images_inside/output.pdf) {{< /tab >}} {{< /tabs >}} For the example document (10 embedded images), 8 images larger than 100×100 are watermarked. `get_images()` works the same way for Word, Excel, PowerPoint, and other formats — open the document and iterate the returned collection. You can also pass an `ImageWatermark` to `image.add(...)` to stamp a logo onto each embedded image. --- ## Working with slide backgrounds Path: https://docs.groupdocs.com/watermark/python-net/working-with-slide-backgrounds/ `Watermarker.get_content()` returns a `PresentationContent` whose `slides` each expose an `image_fill_format` with a `background_image`, `tile_as_texture`, and `transparency`. The background image is `None` when the slide has no image fill. ## Extract information about slide backgrounds {{< tabs "code-example-extract-slide-backgrounds">}} {{< tab "extract_slide_backgrounds.py" >}} ```python from groupdocs.watermark import Watermarker from groupdocs.watermark.options.presentation import PresentationLoadOptions def extract_slide_backgrounds(): with Watermarker("./presentation.pptx", PresentationLoadOptions()) as watermarker: content = watermarker.get_content() for i, slide in enumerate(content.slides): background = slide.image_fill_format.background_image if background is not None: print(f"Slide {i}: background {background.width}x{background.height}") else: print(f"Slide {i}: no background image") if __name__ == "__main__": extract_slide_backgrounds() ``` {{< /tab >}} {{< tab "presentation.pptx" >}} {{< tab-text >}} `presentation.pptx` is the sample file used in this example. Click [here](https://docs.groupdocs.com/watermark/python-net/_sample_files/developer-guide/advanced-usage/adding-watermarks/add-watermarks-to-presentation-documents/working-with-slide-backgrounds/presentation.pptx) to download it. {{< /tab-text >}} {{< /tab >}} {{< tab "extract-slide-backgrounds.txt" >}} ```text Slide 0: no background image Slide 1: no background image Slide 2: no background image Slide 3: no background image ``` [Download full output](https://docs.groupdocs.com/watermark/python-net/_output_files/developer-guide/advanced-usage/adding-watermarks/add-watermarks-to-presentation-documents/working-with-slide-backgrounds/extract_slide_backgrounds/extract-slide-backgrounds.txt) {{< /tab >}} {{< /tabs >}} ## Remove a slide background Set the `background_image` to `None`: {{< tabs "code-example-remove-slide-background">}} {{< tab "remove_slide_background.py" >}} ```python from groupdocs.watermark import Watermarker from groupdocs.watermark.options.presentation import PresentationLoadOptions def remove_slide_background(): with Watermarker("./presentation.pptx", PresentationLoadOptions()) as watermarker: content = watermarker.get_content() content.slides[0].image_fill_format.background_image = None watermarker.save("./output.pptx") if __name__ == "__main__": remove_slide_background() ``` {{< /tab >}} {{< tab "presentation.pptx" >}} {{< tab-text >}} `presentation.pptx` is the sample file used in this example. Click [here](https://docs.groupdocs.com/watermark/python-net/_sample_files/developer-guide/advanced-usage/adding-watermarks/add-watermarks-to-presentation-documents/working-with-slide-backgrounds/presentation.pptx) to download it. {{< /tab-text >}} {{< /tab >}} {{< tab "output.pptx" >}} ```text Binary file (PPTX, 196 KB) ``` [Download full output](https://docs.groupdocs.com/watermark/python-net/_output_files/developer-guide/advanced-usage/adding-watermarks/add-watermarks-to-presentation-documents/working-with-slide-backgrounds/remove_slide_background/output.pptx) {{< /tab >}} {{< /tabs >}} ## Watermark existing slide backgrounds {{< tabs "code-example-watermark-slide-backgrounds">}} {{< tab "watermark_slide_backgrounds.py" >}} ```python from groupdocs.watermark import Watermarker from groupdocs.watermark.watermarks import TextWatermark, Font, Color from groupdocs.watermark.options.presentation import PresentationLoadOptions def watermark_slide_backgrounds(): with Watermarker("./presentation.pptx", PresentationLoadOptions()) as watermarker: watermark = TextWatermark("CONFIDENTIAL", Font("Arial", 19.0)) watermark.foreground_color = Color.red content = watermarker.get_content() for slide in content.slides: if slide.image_fill_format.background_image is not None: slide.image_fill_format.background_image.add(watermark) watermarker.save("./output.pptx") if __name__ == "__main__": watermark_slide_backgrounds() ``` {{< /tab >}} {{< tab "presentation.pptx" >}} {{< tab-text >}} `presentation.pptx` is the sample file used in this example. Click [here](https://docs.groupdocs.com/watermark/python-net/_sample_files/developer-guide/advanced-usage/adding-watermarks/add-watermarks-to-presentation-documents/working-with-slide-backgrounds/presentation.pptx) to download it. {{< /tab-text >}} {{< /tab >}} {{< tab "output.pptx" >}} ```text Binary file (PPTX, 196 KB) ``` [Download full output](https://docs.groupdocs.com/watermark/python-net/_output_files/developer-guide/advanced-usage/adding-watermarks/add-watermarks-to-presentation-documents/working-with-slide-backgrounds/watermark_slide_backgrounds/output.pptx) {{< /tab >}} {{< /tabs >}} You can also tune `image_fill_format.transparency` (0.0–1.0) and `image_fill_format.tile_as_texture` when setting a background image. The same `image_fill_format` is available on chart objects. --- ## Add image watermarks Path: https://docs.groupdocs.com/watermark/python-net/add-image/ One of the main features of GroupDocs.Watermark is adding image watermarks to documents. You can add watermarks to documents or images from a local path, as well as from a stream. For a full list of supported formats, check [Supported document formats]({{< ref "watermark/python-net/getting-started/supported-document-formats.md" >}}). ## Add an image watermark To add an image watermark, follow these steps: 1. Open the document by passing its path (or a stream) to the `Watermarker` class. 2. Create an `ImageWatermark` from the watermark image file (or a stream). 3. Position the watermark — for example, set `horizontal_alignment`, `vertical_alignment`, and `opacity`. 4. Call `add()` to apply the watermark and `save()` to write the result. {{< tabs "code-example-add-image">}} {{< tab "add_image_watermark.py" >}} ```python from groupdocs.watermark import Watermarker from groupdocs.watermark.watermarks import ImageWatermark from groupdocs.watermark.common import HorizontalAlignment, VerticalAlignment def add_image_watermark(): with Watermarker("./sample.docx") as watermarker: # Build an image watermark from a logo file and center it watermark = ImageWatermark("./logo.png") watermark.horizontal_alignment = HorizontalAlignment.CENTER watermark.vertical_alignment = VerticalAlignment.CENTER watermark.opacity = 0.7 watermarker.add(watermark) watermarker.save("./output.docx") if __name__ == "__main__": add_image_watermark() ``` {{< /tab >}} {{< tab "sample.docx" >}} {{< tab-text >}} `sample.docx` and `logo.png` are the sample files used in this example. Download [sample.docx](https://docs.groupdocs.com/watermark/python-net/_sample_files/developer-guide/basic-usage/add-image/sample.docx) and [logo.png](https://docs.groupdocs.com/watermark/python-net/_sample_files/developer-guide/basic-usage/add-image/logo.png). {{< /tab-text >}} {{< /tab >}} {{< tab "output.docx" >}} ```text Binary file (DOCX, 125 KB) ``` [Download full output](https://docs.groupdocs.com/watermark/python-net/_output_files/developer-guide/basic-usage/add-image/add_image_watermark/output.docx) {{< /tab >}} {{< /tabs >}} ## What's next GroupDocs.Watermark offers more capabilities for image watermarks — loading from streams, scaling, tiling, and absolute or relative positioning. See [Adding image watermarks]({{< ref "watermark/python-net/developer-guide/advanced-usage/adding-watermarks/adding-image-watermarks.md" >}}) in the advanced guide. --- ## Email messages Path: https://docs.groupdocs.com/watermark/python-net/email-messages/ `Watermarker.get_content()` returns an `EmailContent` for an email message (MSG, EML, EMLX). It exposes the message `body`, `html_body`, and `subject`, the `embedded_objects` (inline images), the recipient lists (`to`, `cc`, `bcc`), and the `attachments`. ## Modify the body and subject {{< tabs "code-example-modify-email-message">}} {{< tab "modify_message.py" >}} ```python from groupdocs.watermark import Watermarker from groupdocs.watermark.options.email import EmailLoadOptions def modify_message(): with Watermarker("./message.msg", EmailLoadOptions()) as watermarker: content = watermarker.get_content() content.subject = content.subject + " [CONFIDENTIAL]" content.body = content.body + "\n\nThis message is confidential." watermarker.save("./output.msg") if __name__ == "__main__": modify_message() ``` {{< /tab >}} {{< tab "message.msg" >}} {{< tab-text >}} `message.msg` is the sample file used in this example. Click [here](https://docs.groupdocs.com/watermark/python-net/_sample_files/developer-guide/advanced-usage/adding-watermarks/add-watermarks-to-email-attachments/email-messages/message.msg) to download it. {{< /tab-text >}} {{< /tab >}} {{< tab "output.msg" >}} ```text Binary file (MSG, 134 KB) ``` [Download full output](https://docs.groupdocs.com/watermark/python-net/_output_files/developer-guide/advanced-usage/adding-watermarks/add-watermarks-to-email-attachments/email-messages/modify_message/output.msg) {{< /tab >}} {{< /tabs >}} ## Embed an image into the body Add the image to `embedded_objects`, then reference it from the HTML body by its content id: {{< tabs "code-example-embed-email-image">}} {{< tab "embed_image.py" >}} ```python from groupdocs.watermark import Watermarker from groupdocs.watermark.options.email import EmailLoadOptions def embed_image(): with Watermarker("./message.msg", EmailLoadOptions()) as watermarker: content = watermarker.get_content() with open("./logo.png", "rb") as f: data = f.read() content.embedded_objects.add(data, "logo.png") embedded = content.embedded_objects[len(content.embedded_objects) - 1] content.html_body = content.html_body.replace( "", f'') watermarker.save("./output.msg") if __name__ == "__main__": embed_image() ``` {{< /tab >}} {{< tab "message.msg" >}} {{< tab-text >}} `message.msg` and `logo.png` are the sample files used in this example. Download [message.msg](https://docs.groupdocs.com/watermark/python-net/_sample_files/developer-guide/advanced-usage/adding-watermarks/add-watermarks-to-email-attachments/email-messages/message.msg) and [logo.png](https://docs.groupdocs.com/watermark/python-net/_sample_files/developer-guide/advanced-usage/adding-watermarks/add-watermarks-to-email-attachments/email-messages/logo.png). {{< /tab-text >}} {{< /tab >}} {{< tab "output.msg" >}} ```text Binary file (MSG, 142 KB) ``` [Download full output](https://docs.groupdocs.com/watermark/python-net/_output_files/developer-guide/advanced-usage/adding-watermarks/add-watermarks-to-email-attachments/email-messages/embed_image/output.msg) {{< /tab >}} {{< /tabs >}} ## Search the message text Limit the search to the subject and body, then search with a `TextSearchCriteria`: {{< tabs "code-example-search-email-text">}} {{< tab "search_message_text.py" >}} ```python from groupdocs.watermark import Watermarker, WatermarkerSettings from groupdocs.watermark.search.search_criteria import TextSearchCriteria from groupdocs.watermark.search.objects import SearchableObjects, EmailSearchableObjects def search_message_text(): settings = WatermarkerSettings() settings.searchable_objects = SearchableObjects( email_searchable_objects=EmailSearchableObjects.SUBJECT | EmailSearchableObjects.PLAIN_TEXT_BODY) with Watermarker("./message.msg", settings) as watermarker: possible = watermarker.search(TextSearchCriteria("confidential")) print("Found", len(possible), "match(es)") if __name__ == "__main__": search_message_text() ``` {{< /tab >}} {{< tab "message.msg" >}} {{< tab-text >}} `message.msg` is the sample file used in this example. Click [here](https://docs.groupdocs.com/watermark/python-net/_sample_files/developer-guide/advanced-usage/adding-watermarks/add-watermarks-to-email-attachments/email-messages/message.msg) to download it. {{< /tab-text >}} {{< /tab >}} {{< tab "search-message-text.txt" >}} ```text Found 0 match(es) ``` [Download full output](https://docs.groupdocs.com/watermark/python-net/_output_files/developer-guide/advanced-usage/adding-watermarks/add-watermarks-to-email-attachments/email-messages/search_message_text/search-message-text.txt) {{< /tab >}} {{< /tabs >}} ## List recipients {{< tabs "code-example-list-recipients">}} {{< tab "list_recipients.py" >}} ```python from groupdocs.watermark import Watermarker from groupdocs.watermark.options.email import EmailLoadOptions def list_recipients(): with Watermarker("./message.msg", EmailLoadOptions()) as watermarker: content = watermarker.get_content() for recipient in list(content.to) + list(content.cc) + list(content.bcc): print(recipient.address) if __name__ == "__main__": list_recipients() ``` {{< /tab >}} {{< tab "message.msg" >}} {{< tab-text >}} `message.msg` is the sample file used in this example. Click [here](https://docs.groupdocs.com/watermark/python-net/_sample_files/developer-guide/advanced-usage/adding-watermarks/add-watermarks-to-email-attachments/email-messages/message.msg) to download it. {{< /tab-text >}} {{< /tab >}} {{< tab "list-recipients.txt" >}} ```text alex.chen@northwind.example tomas.reyes@auroravisuals.example ``` [Download full output](https://docs.groupdocs.com/watermark/python-net/_output_files/developer-guide/advanced-usage/adding-watermarks/add-watermarks-to-email-attachments/email-messages/list_recipients/list-recipients.txt) {{< /tab >}} {{< /tabs >}} --- ## Existing objects in PDF document Path: https://docs.groupdocs.com/watermark/python-net/existing-objects-in-pdf-document/ `Watermarker.get_content()` returns a `PdfContent` whose `pages` expose three collections of existing objects: `xobjects`, `artifacts`, and `annotations`. You can iterate them to read their properties, modify them, or remove them. ## Extract information about page objects The example below reports the objects on the first page of a watermarked PDF. {{< tabs "code-example-pdf-existing-objects">}} {{< tab "extract_objects.py" >}} ```python from groupdocs.watermark import Watermarker from groupdocs.watermark.options.pdf import PdfLoadOptions def extract_objects(): with Watermarker("./document.pdf", PdfLoadOptions()) as watermarker: content = watermarker.get_content() page = content.pages[0] print(f"Page 1: xobjects={len(page.xobjects)} " f"artifacts={len(page.artifacts)} annotations={len(page.annotations)}") for artifact in page.artifacts: text = (artifact.text or "").strip() print(f" artifact text={text!r} size={round(artifact.width)}x{round(artifact.height)}") for annotation in page.annotations: text = (annotation.text or "").strip() print(f" annotation text={text!r} size={round(annotation.width)}x{round(annotation.height)}") if __name__ == "__main__": extract_objects() ``` {{< /tab >}} {{< tab "document.pdf" >}} {{< tab-text >}} `document.pdf` is the sample file used in this example. Click [here](https://docs.groupdocs.com/watermark/python-net/_sample_files/developer-guide/advanced-usage/adding-watermarks/existing-objects-in-pdf-document/document.pdf) to download it. {{< /tab-text >}} {{< /tab >}} {{< tab "extract-objects.txt" >}} ```text Page 1: xobjects=2 artifacts=2 annotations=0 artifact text='CONFIDENTIAL' size=268x36 artifact text='' size=135x40 ``` [Download full output](https://docs.groupdocs.com/watermark/python-net/_output_files/developer-guide/advanced-usage/adding-watermarks/add-watermarks-to-pdf-documents/existing-objects-in-pdf-document/extract_objects/extract-objects.txt) {{< /tab >}} {{< /tabs >}} Each object exposes `text`, `image`, `x`, `y`, `width`, `height`, and `rotate_angle` (artifacts also expose `opacity`, `artifact_type`, and `artifact_subtype`). ## Remove and modify objects Each collection supports `remove_at(index)` and `remove(object)`. Iterate in reverse when removing by index: {{< tabs "code-example-pdf-remove-objects">}} {{< tab "remove_and_modify_objects.py" >}} ```python from groupdocs.watermark import Watermarker from groupdocs.watermark.options.pdf import PdfLoadOptions def remove_and_modify_objects(): with Watermarker("./document.pdf", PdfLoadOptions()) as watermarker: content = watermarker.get_content() for page in content.pages: for i in range(len(page.artifacts) - 1, -1, -1): if page.artifacts[i].text and "watermark" in page.artifacts[i].text.lower(): page.artifacts.remove_at(i) watermarker.save("./output.pdf") if __name__ == "__main__": remove_and_modify_objects() ``` {{< /tab >}} {{< tab "document.pdf" >}} {{< tab-text >}} `document.pdf` is the sample file used in this example. Click [here](https://docs.groupdocs.com/watermark/python-net/_sample_files/developer-guide/advanced-usage/adding-watermarks/existing-objects-in-pdf-document/document.pdf) to download it. {{< /tab-text >}} {{< /tab >}} {{< tab "output.pdf" >}} ```text Binary file (PDF, 394 KB) ``` [Download full output](https://docs.groupdocs.com/watermark/python-net/_output_files/developer-guide/advanced-usage/adding-watermarks/add-watermarks-to-pdf-documents/existing-objects-in-pdf-document/remove_and_modify_objects/output.pdf) {{< /tab >}} {{< /tabs >}} You can replace an object's text by assigning to `obj.text`, replace its image by assigning bytes to `obj.image_data`, and add a watermark to an image object via `image.add(watermark)` after locating it with `page.find_images()`. --- ## Hello, World! Path: https://docs.groupdocs.com/watermark/python-net/hello-world/ ## Introduction A "Hello, World!" example is often the first step when exploring GroupDocs.Watermark for Python via .NET. It serves as a simple test to confirm that your development environment is correctly set up and that the library is functioning as expected. ## Overview GroupDocs.Watermark for Python via .NET lets you add, search, and remove watermarks in various document formats. A wide range of [supported formats](https://docs.groupdocs.com/watermark/python-net/getting-started/supported-document-formats.md) makes it versatile for different use cases. ## How to add a watermark The following steps demonstrate how to add a text watermark to a document using GroupDocs.Watermark for Python via .NET: 1. Import the `groupdocs.watermark` classes you need. 2. Open a `Watermarker` with the path to the sample document. 3. Create a `TextWatermark` with the desired text and font, and style it. 4. Apply the watermark with `add()`. 5. Save the result. ## Complete example The example below adds a semi-transparent, diagonal "Hello, Watermark!" text watermark and saves the result: {{< tabs "code-example-hello-world" >}} {{< tab "hello_world.py" >}} ```python from groupdocs.watermark import Watermarker from groupdocs.watermark.watermarks import TextWatermark, Font, Color def hello_world(): # Open the document, add a single text watermark, and save the result with Watermarker("./sample.pdf") as watermarker: watermark = TextWatermark("Hello, Watermark!", Font("Arial", 36.0)) watermark.foreground_color = Color.red watermark.opacity = 0.5 watermark.rotate_angle = 45.0 watermarker.add(watermark) watermarker.save("./output.pdf") print("Watermark added successfully. Output saved to ./output.pdf.") if __name__ == "__main__": hello_world() ``` {{< /tab >}} {{< tab "sample.pdf" >}} {{< tab-text >}} `sample.pdf` is the sample file used in this example. Click [here](https://docs.groupdocs.com/watermark/python-net/_sample_files/getting-started/hello-world/sample.pdf) to download it. {{< /tab-text >}} {{< /tab >}} {{< tab "output.pdf" >}} ```text Binary file (PDF, 354 KB) ``` [Download full output](https://docs.groupdocs.com/watermark/python-net/_output_files/getting-started/hello-world/hello_world/output.pdf) {{< /tab >}} {{< /tabs >}} The watermark is saved back to the same PDF format as `output.pdf`. To stamp a different document, change the input path and the output extension — GroupDocs.Watermark saves in the input document's format. ## Additional resources This demo references the GroupDocs.Watermark for Python via .NET [code samples](https://github.com/groupdocs-watermark/GroupDocs.Watermark-for-Python-via-.NET/). --- ## Adding image watermarks Path: https://docs.groupdocs.com/watermark/python-net/adding-image-watermarks/ GroupDocs.Watermark supports adding the following image formats as watermarks: - BMP - PNG - GIF - JPEG ## Add an image watermark from a local file The following example adds an `ImageWatermark` to a document. If the document consists of multiple parts (pages, worksheets, slides, frames, etc.), the watermark is added to each of them. {{< tabs "code-example-adding-image-watermarks">}} {{< tab "add_image_watermark.py" >}} ```python from groupdocs.watermark import Watermarker from groupdocs.watermark.watermarks import ImageWatermark, SizingType from groupdocs.watermark.common import HorizontalAlignment, VerticalAlignment def add_image_watermark(): with Watermarker("./sample.docx") as watermarker: with ImageWatermark("./logo.png") as watermark: watermark.horizontal_alignment = HorizontalAlignment.CENTER watermark.vertical_alignment = VerticalAlignment.CENTER watermark.sizing_type = SizingType.SCALE_TO_PARENT_DIMENSIONS watermark.scale_factor = 0.5 watermark.opacity = 0.7 watermarker.add(watermark) watermarker.save("./output.docx") if __name__ == "__main__": add_image_watermark() ``` {{< /tab >}} {{< tab "sample.docx" >}} {{< tab-text >}} `sample.docx` and `logo.png` are the sample files used in this example. Download [sample.docx](https://docs.groupdocs.com/watermark/python-net/_sample_files/developer-guide/advanced-usage/adding-watermarks/adding-image-watermarks/sample.docx) and [logo.png](https://docs.groupdocs.com/watermark/python-net/_sample_files/developer-guide/advanced-usage/adding-watermarks/adding-image-watermarks/logo.png). {{< /tab-text >}} {{< /tab >}} {{< tab "output.docx" >}} ```text Binary file (DOCX, 125 KB) ``` [Download full output](https://docs.groupdocs.com/watermark/python-net/_output_files/developer-guide/advanced-usage/adding-watermarks/adding-image-watermarks/add_image_watermark/output.docx) {{< /tab >}} {{< /tabs >}} ## Add an image watermark from a stream You can also initialize an `ImageWatermark` from a stream — pass it as the `stream` argument. {{< tabs "code-example-adding-image-watermarks-stream">}} {{< tab "add_image_watermark_from_stream.py" >}} ```python import io from groupdocs.watermark import Watermarker from groupdocs.watermark.watermarks import ImageWatermark def add_image_watermark_from_stream(): with open("./logo.png", "rb") as f: data = f.read() with Watermarker("./sample.docx") as watermarker: with ImageWatermark(stream=io.BytesIO(data)) as watermark: watermarker.add(watermark) watermarker.save("./output.docx") if __name__ == "__main__": add_image_watermark_from_stream() ``` {{< /tab >}} {{< tab "sample.docx" >}} {{< tab-text >}} `sample.docx` and `logo.png` are the sample files used in this example. Download [sample.docx](https://docs.groupdocs.com/watermark/python-net/_sample_files/developer-guide/advanced-usage/adding-watermarks/adding-image-watermarks/sample.docx) and [logo.png](https://docs.groupdocs.com/watermark/python-net/_sample_files/developer-guide/advanced-usage/adding-watermarks/adding-image-watermarks/logo.png). {{< /tab-text >}} {{< /tab >}} {{< tab "output.docx" >}} ```text Binary file (DOCX, 120 KB) ``` [Download full output](https://docs.groupdocs.com/watermark/python-net/_output_files/developer-guide/advanced-usage/adding-watermarks/adding-image-watermarks/add_image_watermark_from_stream/output.docx) {{< /tab >}} {{< /tabs >}} For advanced watermark properties (tiling, alignment, sizing, rotation, and margins), the same techniques shown for text watermarks apply to image watermarks. See [Adding text watermarks]({{< ref "watermark/python-net/developer-guide/advanced-usage/adding-watermarks/adding-text-watermarks.md" >}}). --- ## Locking watermark in word processing document Path: https://docs.groupdocs.com/watermark/python-net/locking-watermark-in-word-processing-document/ To make a watermark harder to remove, you can lock it by setting `is_locked` and a `lock_type` on the watermark option (`WordProcessingWatermarkSectionOptions` or `WordProcessingWatermarkPagesOptions`). An optional `password` is also supported. ## Add a locked watermark {{< tabs "code-example-add-locked-word-watermark">}} {{< tab "add_locked_watermark.py" >}} ```python from groupdocs.watermark import Watermarker from groupdocs.watermark.watermarks import TextWatermark, Font, Color from groupdocs.watermark.options.word_processing import ( WordProcessingLoadOptions, WordProcessingWatermarkSectionOptions, WordProcessingLockType, ) def add_locked_watermark(): with Watermarker("./document.docx", WordProcessingLoadOptions()) as watermarker: watermark = TextWatermark("CONFIDENTIAL", Font("Arial", 19.0)) watermark.foreground_color = Color.red options = WordProcessingWatermarkSectionOptions() options.is_locked = True options.lock_type = WordProcessingLockType.ALLOW_ONLY_FORM_FIELDS # options.password = "p@ssw0rd" # optional watermarker.add(watermark, options) watermarker.save("./output.docx") if __name__ == "__main__": add_locked_watermark() ``` {{< /tab >}} {{< tab "document.docx" >}} {{< tab-text >}} `document.docx` is the sample file used in this example. Click [here](https://docs.groupdocs.com/watermark/python-net/_sample_files/developer-guide/advanced-usage/adding-watermarks/add-watermarks-to-word-processing-documents/document.docx) to download it. {{< /tab-text >}} {{< /tab >}} {{< tab "output.docx" >}} ```text Binary file (DOCX, 125 KB) ``` [Download full output](https://docs.groupdocs.com/watermark/python-net/_output_files/developer-guide/advanced-usage/adding-watermarks/add-watermarks-to-word-processing-documents/locking-watermark-in-word-processing-document/add_locked_watermark/output.docx) {{< /tab >}} {{< /tabs >}} Available `WordProcessingLockType` values: `ALLOW_ONLY_FORM_FIELDS`, `ALLOW_ONLY_COMMENTS`, `ALLOW_ONLY_REVISIONS`, `READ_ONLY`, `READ_ONLY_WITH_EDITABLE_CONTENT`, and `NO_LOCK`. --- ## Modifying found watermark properties Path: https://docs.groupdocs.com/watermark/python-net/modifying-found-watermark-properties/ GroupDocs.Watermark lets you replace the text or image of watermarks that already exist in a document. Search for the watermarks first, then assign a new value to each match. ## Replace text The example below opens a document that contains a "CONFIDENTIAL" watermark, finds it, and replaces the text with "APPROVED". {{< tabs "code-example-modify-watermark">}} {{< tab "modify_watermark.py" >}} ```python from groupdocs.watermark import Watermarker from groupdocs.watermark.search.search_criteria import TextSearchCriteria def modify_watermark(): with Watermarker("./watermarked-document.pdf") as watermarker: possible = watermarker.search(TextSearchCriteria("CONFIDENTIAL")) for wm in possible: try: wm.text = "APPROVED" except Exception: # The entity may not support text editing, or the value is invalid pass watermarker.save("./output.pdf") if __name__ == "__main__": modify_watermark() ``` {{< /tab >}} {{< tab "watermarked-document.pdf" >}} {{< tab-text >}} `watermarked-document.pdf` is the sample file used in this example. Click [here](https://docs.groupdocs.com/watermark/python-net/_sample_files/developer-guide/advanced-usage/searching-and-modifying-watermarks/modifying-found-watermark-properties/watermarked-document.pdf) to download it. {{< /tab-text >}} {{< /tab >}} {{< tab "output.pdf" >}} ```text Binary file (PDF, 479 KB) ``` [Download full output](https://docs.groupdocs.com/watermark/python-net/_output_files/developer-guide/advanced-usage/searching-and-modifying-watermarks/modifying-found-watermark-properties/modify_watermark/output.pdf) {{< /tab >}} {{< /tabs >}} ## Replace text with formatting Use `formatted_text_fragments` to replace the text with styled fragments — choose the font, foreground color, and background color. {{< tabs "code-example-modify-watermark-formatting">}} {{< tab "modify_watermark_with_formatting.py" >}} ```python from groupdocs.watermark import Watermarker from groupdocs.watermark.watermarks import Font, FontStyle, Color from groupdocs.watermark.search.search_criteria import TextSearchCriteria def modify_watermark_with_formatting(): with Watermarker("./watermarked-document.pdf") as watermarker: possible = watermarker.search(TextSearchCriteria("CONFIDENTIAL")) for wm in possible: try: wm.formatted_text_fragments.clear() wm.formatted_text_fragments.add( "APPROVED", Font("Calibri", 19.0, FontStyle.BOLD), Color.red, Color.aqua, ) except Exception: # The entity may not support formatted text, or values may be invalid pass watermarker.save("./output.pdf") if __name__ == "__main__": modify_watermark_with_formatting() ``` {{< /tab >}} {{< tab "watermarked-document.pdf" >}} {{< tab-text >}} `watermarked-document.pdf` is the sample file used in this example. Click [here](https://docs.groupdocs.com/watermark/python-net/_sample_files/developer-guide/advanced-usage/searching-and-modifying-watermarks/modifying-found-watermark-properties/watermarked-document.pdf) to download it. {{< /tab-text >}} {{< /tab >}} {{< tab "output.pdf" >}} ```text Binary file (PDF, 662 KB) ``` [Download full output](https://docs.groupdocs.com/watermark/python-net/_output_files/developer-guide/advanced-usage/searching-and-modifying-watermarks/modifying-found-watermark-properties/modify_watermark_with_formatting/output.pdf) {{< /tab >}} {{< /tabs >}} ## Replace image Swap the image data of matched watermarks by assigning new bytes to `image_data`. {{< tabs "code-example-replace-watermark-image">}} {{< tab "replace_watermark_image.py" >}} ```python from groupdocs.watermark import Watermarker from groupdocs.watermark.search.search_criteria import ImageDctHashSearchCriteria def replace_watermark_image(): with open("./stamp.png", "rb") as f: image_data = f.read() with Watermarker("./watermarked-document.docx") as watermarker: criteria = ImageDctHashSearchCriteria("./logo.png") criteria.max_difference = 0.9 possible = watermarker.search(criteria) for wm in possible: try: wm.image_data = image_data except Exception: # The entity may not support image replacement, or the image format is invalid pass watermarker.save("./output.docx") if __name__ == "__main__": replace_watermark_image() ``` {{< /tab >}} {{< tab "watermarked-document.docx" >}} {{< tab-text >}} `watermarked-document.docx`, `logo.png`, and `stamp.png` are the sample files used in this example. Download [watermarked-document.docx](https://docs.groupdocs.com/watermark/python-net/_sample_files/developer-guide/advanced-usage/searching-and-modifying-watermarks/modifying-found-watermark-properties/watermarked-document.docx), [logo.png](https://docs.groupdocs.com/watermark/python-net/_sample_files/developer-guide/advanced-usage/searching-and-modifying-watermarks/modifying-found-watermark-properties/logo.png), and [stamp.png](https://docs.groupdocs.com/watermark/python-net/_sample_files/developer-guide/advanced-usage/searching-and-modifying-watermarks/modifying-found-watermark-properties/stamp.png). {{< /tab-text >}} {{< /tab >}} {{< tab "output.docx" >}} ```text Binary file (DOCX, 18 KB) ``` [Download full output](https://docs.groupdocs.com/watermark/python-net/_output_files/developer-guide/advanced-usage/searching-and-modifying-watermarks/modifying-found-watermark-properties/replace_watermark_image/output.docx) {{< /tab >}} {{< /tabs >}} --- ## Working with spreadsheet document attachments Path: https://docs.groupdocs.com/watermark/python-net/working-with-spreadsheet-document-attachments/ Excel worksheets can embed file attachments (OLE objects). They are available through `SpreadsheetContent.worksheets[i].attachments`. Each attachment exposes `alternative_text`, `is_link`, `source_full_name`, `content`, and `get_document_info()`, and the document it contains can be opened in its own `Watermarker`. ## Extract attachments {{< tabs "code-example-extract-spreadsheet-attachments">}} {{< tab "extract_attachments.py" >}} ```python from groupdocs.watermark import Watermarker from groupdocs.watermark.options.spreadsheet import SpreadsheetLoadOptions def extract_attachments(): with Watermarker("./spreadsheet.xlsx", SpreadsheetLoadOptions()) as watermarker: content = watermarker.get_content() for i, worksheet in enumerate(content.worksheets): for attachment in worksheet.attachments: info = attachment.get_document_info() print(f"Worksheet {i}: {attachment.alternative_text!r} type={info.file_type}") with open(f"./{attachment.alternative_text}", "wb") as f: f.write(attachment.content) if __name__ == "__main__": extract_attachments() ``` {{< /tab >}} {{< tab "spreadsheet.xlsx" >}} {{< tab-text >}} `spreadsheet.xlsx` is the sample file used in this example. Click [here](https://docs.groupdocs.com/watermark/python-net/_sample_files/developer-guide/advanced-usage/adding-watermarks/add-watermarks-to-spreadsheet-documents/working-with-spreadsheet-document-attachments/spreadsheet.xlsx) to download it. {{< /tab-text >}} {{< /tab >}} {{< /tabs >}} ## Remove an attachment The `attachments` collection supports `remove_at(index)` and `remove(attachment)`. Iterate in reverse when removing by index: {{< tabs "code-example-remove-spreadsheet-attachment">}} {{< tab "remove_attachment.py" >}} ```python from groupdocs.watermark import Watermarker from groupdocs.watermark.options.spreadsheet import SpreadsheetLoadOptions def remove_attachment(): with Watermarker("./spreadsheet.xlsx", SpreadsheetLoadOptions()) as watermarker: content = watermarker.get_content() for worksheet in content.worksheets: for i in range(len(worksheet.attachments) - 1, -1, -1): if worksheet.attachments[i].is_link: worksheet.attachments.remove_at(i) watermarker.save("./output.xlsx") if __name__ == "__main__": remove_attachment() ``` {{< /tab >}} {{< tab "spreadsheet.xlsx" >}} {{< tab-text >}} `spreadsheet.xlsx` is the sample file used in this example. Click [here](https://docs.groupdocs.com/watermark/python-net/_sample_files/developer-guide/advanced-usage/adding-watermarks/add-watermarks-to-spreadsheet-documents/working-with-spreadsheet-document-attachments/spreadsheet.xlsx) to download it. {{< /tab-text >}} {{< /tab >}} {{< tab "output.xlsx" >}} ```text Binary file (XLSX, 9 KB) ``` [Download full output](https://docs.groupdocs.com/watermark/python-net/_output_files/developer-guide/advanced-usage/adding-watermarks/add-watermarks-to-spreadsheet-documents/working-with-spreadsheet-document-attachments/remove_attachment/output.xlsx) {{< /tab >}} {{< /tabs >}} ## Watermark the attached documents Open each attachment's bytes in its own `Watermarker`, add a watermark, and write the result back: {{< tabs "code-example-watermark-spreadsheet-attachments">}} {{< tab "watermark_attached_documents.py" >}} ```python import io from groupdocs.watermark import Watermarker from groupdocs.watermark.watermarks import TextWatermark, Font, Color from groupdocs.watermark.options.spreadsheet import SpreadsheetLoadOptions def watermark_attached_documents(): with Watermarker("./spreadsheet.xlsx", SpreadsheetLoadOptions()) as watermarker: content = watermarker.get_content() for worksheet in content.worksheets: for attachment in worksheet.attachments: with Watermarker(io.BytesIO(attachment.content)) as inner: wm = TextWatermark("CONFIDENTIAL", Font("Arial", 19.0)) wm.foreground_color = Color.red inner.add(wm) buffer = io.BytesIO() inner.save(buffer) # write the watermarked attachment bytes back as needed watermarker.save("./output.xlsx") if __name__ == "__main__": watermark_attached_documents() ``` {{< /tab >}} {{< tab "spreadsheet.xlsx" >}} {{< tab-text >}} `spreadsheet.xlsx` is the sample file used in this example. Click [here](https://docs.groupdocs.com/watermark/python-net/_sample_files/developer-guide/advanced-usage/adding-watermarks/add-watermarks-to-spreadsheet-documents/working-with-spreadsheet-document-attachments/spreadsheet.xlsx) to download it. {{< /tab-text >}} {{< /tab >}} {{< tab "output.xlsx" >}} ```text Binary file (XLSX, 9 KB) ``` [Download full output](https://docs.groupdocs.com/watermark/python-net/_output_files/developer-guide/advanced-usage/adding-watermarks/add-watermarks-to-spreadsheet-documents/working-with-spreadsheet-document-attachments/watermark_attached_documents/output.xlsx) {{< /tab >}} {{< /tabs >}} --- ## Protecting word processing documents Path: https://docs.groupdocs.com/watermark/python-net/protecting-word-processing-documents/ Beyond locking an individual watermark, you can protect the whole document. `Watermarker.get_content()` returns a `WordProcessingContent` with `protect()` and `unprotect()` methods. ## Protect a document The example sets read-only protection with a password. {{< tabs "code-example-protect-word-document">}} {{< tab "protect_document.py" >}} ```python from groupdocs.watermark import Watermarker from groupdocs.watermark.options.word_processing import WordProcessingLoadOptions from groupdocs.watermark.contents.word_processing import WordProcessingProtectionType def protect_document(): with Watermarker("./document.docx", WordProcessingLoadOptions()) as watermarker: content = watermarker.get_content() content.protect(WordProcessingProtectionType.READ_ONLY, "p@ssw0rd") watermarker.save("./output.docx") if __name__ == "__main__": protect_document() ``` {{< /tab >}} {{< tab "document.docx" >}} {{< tab-text >}} `document.docx` is the sample file used in this example. Click [here](https://docs.groupdocs.com/watermark/python-net/_sample_files/developer-guide/advanced-usage/adding-watermarks/add-watermarks-to-word-processing-documents/document.docx) to download it. {{< /tab-text >}} {{< /tab >}} {{< tab "output.docx" >}} ```text Binary file (DOCX, 119 KB) ``` [Download full output](https://docs.groupdocs.com/watermark/python-net/_output_files/developer-guide/advanced-usage/adding-watermarks/add-watermarks-to-word-processing-documents/protecting-word-processing-documents/protect_document/output.docx) {{< /tab >}} {{< /tabs >}} Available `WordProcessingProtectionType` values: `READ_ONLY`, `ALLOW_ONLY_FORM_FIELDS`, `ALLOW_ONLY_COMMENTS`, and `ALLOW_ONLY_REVISIONS`. ## Unprotect a document {{< tabs "code-example-unprotect-word-document">}} {{< tab "unprotect_document.py" >}} ```python from groupdocs.watermark import Watermarker from groupdocs.watermark.options.word_processing import WordProcessingLoadOptions def unprotect_document(): with Watermarker("./document.docx", WordProcessingLoadOptions()) as watermarker: content = watermarker.get_content() content.unprotect() watermarker.save("./output.docx") if __name__ == "__main__": unprotect_document() ``` {{< /tab >}} {{< tab "document.docx" >}} {{< tab-text >}} `document.docx` is the sample file used in this example. Click [here](https://docs.groupdocs.com/watermark/python-net/_sample_files/developer-guide/advanced-usage/adding-watermarks/add-watermarks-to-word-processing-documents/document.docx) to download it. {{< /tab-text >}} {{< /tab >}} {{< tab "output.docx" >}} ```text Binary file (DOCX, 118 KB) ``` [Download full output](https://docs.groupdocs.com/watermark/python-net/_output_files/developer-guide/advanced-usage/adding-watermarks/add-watermarks-to-word-processing-documents/protecting-word-processing-documents/unprotect_document/output.docx) {{< /tab >}} {{< /tabs >}} --- ## Rasterize document or page Path: https://docs.groupdocs.com/watermark/python-net/rasterize-document-or-page/ Watermarks in PDFs can be removed by third-party tools. If you need watermarks that are very hard to remove, **rasterize** the document: convert its pages to images so the content — including the watermark — becomes non-editable. Access the PDF content tree with `Watermarker.get_content()` and call `rasterize()`. {{< alert style="warning" >}} Rasterization is irreversible: the original text and vector content cannot be restored afterwards, and the output file size usually increases. {{< /alert >}} ## Rasterize the whole document The example adds a watermark, rasterizes every page to a PNG image at 100 DPI, and saves the result. {{< tabs "code-example-rasterize-document">}} {{< tab "rasterize_document.py" >}} ```python from groupdocs.watermark import Watermarker from groupdocs.watermark.watermarks import TextWatermark, Font, Color from groupdocs.watermark.options.pdf import PdfLoadOptions from groupdocs.watermark.contents.pdf import PdfImageConversionFormat def rasterize_document(): with Watermarker("./document.pdf", PdfLoadOptions()) as watermarker: watermark = TextWatermark("CONFIDENTIAL", Font("Arial", 19.0)) watermark.foreground_color = Color.red watermarker.add(watermark) # Rasterize every page at 100x100 DPI to PNG images content = watermarker.get_content() content.rasterize(100, 100, PdfImageConversionFormat.PNG) watermarker.save("./output.pdf") if __name__ == "__main__": rasterize_document() ``` {{< /tab >}} {{< tab "document.pdf" >}} {{< tab-text >}} `document.pdf` is the sample file used in this example. Click [here](https://docs.groupdocs.com/watermark/python-net/_sample_files/developer-guide/advanced-usage/adding-watermarks/add-watermarks-to-pdf-documents/document.pdf) to download it. {{< /tab-text >}} {{< /tab >}} {{< tab "output.pdf" >}} ```text Binary file (PDF, 1.1 MB) ``` [Download full output](https://docs.groupdocs.com/watermark/python-net/_output_files/developer-guide/advanced-usage/adding-watermarks/add-watermarks-to-pdf-documents/rasterize-document-or-page/rasterize_document/output.pdf) {{< /tab >}} {{< /tabs >}} ## Rasterize a particular page To rasterize a single page, call `rasterize()` on that page instead of the whole content: {{< tabs "code-example-rasterize-page">}} {{< tab "rasterize_page.py" >}} ```python from groupdocs.watermark import Watermarker from groupdocs.watermark.options.pdf import PdfLoadOptions from groupdocs.watermark.contents.pdf import PdfImageConversionFormat def rasterize_page(): with Watermarker("./document.pdf", PdfLoadOptions()) as watermarker: content = watermarker.get_content() content.pages[0].rasterize(100, 100, PdfImageConversionFormat.PNG) watermarker.save("./output.pdf") if __name__ == "__main__": rasterize_page() ``` {{< /tab >}} {{< tab "document.pdf" >}} {{< tab-text >}} `document.pdf` is the sample file used in this example. Click [here](https://docs.groupdocs.com/watermark/python-net/_sample_files/developer-guide/advanced-usage/adding-watermarks/add-watermarks-to-pdf-documents/document.pdf) to download it. {{< /tab-text >}} {{< /tab >}} {{< tab "output.pdf" >}} ```text Binary file (PDF, 570 KB) ``` [Download full output](https://docs.groupdocs.com/watermark/python-net/_output_files/developer-guide/advanced-usage/adding-watermarks/add-watermarks-to-pdf-documents/rasterize-document-or-page/rasterize_page/output.pdf) {{< /tab >}} {{< /tabs >}} --- ## Removing found watermarks Path: https://docs.groupdocs.com/watermark/python-net/removing-found-watermarks/ Search for the watermarks already present in a document — including those added by third-party tools — and remove them. Iterate the results in reverse so that removing an item does not shift the indexes still to visit. ## Remove watermarks The example below finds every possible watermark in a document and removes them all. {{< tabs "code-example-remove-watermark">}} {{< tab "remove_watermark.py" >}} ```python from groupdocs.watermark import Watermarker def remove_watermark(): with Watermarker("./document.pdf") as watermarker: possible = watermarker.search() for i in range(len(possible) - 1, -1, -1): watermarker.remove(possible[i]) watermarker.save("./output.pdf") if __name__ == "__main__": remove_watermark() ``` {{< /tab >}} {{< tab "document.pdf" >}} {{< tab-text >}} `document.pdf` is the sample file used in this example. Click [here](https://docs.groupdocs.com/watermark/python-net/_sample_files/developer-guide/advanced-usage/searching-and-modifying-watermarks/removing-found-watermarks/document.pdf) to download it. {{< /tab-text >}} {{< /tab >}} {{< tab "output.pdf" >}} ```text Binary file (PDF, 394 KB) ``` [Download full output](https://docs.groupdocs.com/watermark/python-net/_output_files/developer-guide/advanced-usage/searching-and-modifying-watermarks/removing-found-watermarks/remove_watermark/output.pdf) {{< /tab >}} {{< /tabs >}} ## Remove watermarks with particular text formatting Search by color and size, then remove every match. {{< tabs "code-example-remove-watermark-formatting">}} {{< tab "remove_watermark_with_formatting.py" >}} ```python from groupdocs.watermark import Watermarker from groupdocs.watermark.search.search_criteria import TextFormattingSearchCriteria, ColorRange def remove_watermark_with_formatting(): with Watermarker("./document.pdf") as watermarker: criteria = TextFormattingSearchCriteria() criteria.foreground_color_range = ColorRange() criteria.foreground_color_range.min_hue = -15 criteria.foreground_color_range.max_hue = 15 criteria.foreground_color_range.min_brightness = 0.01 criteria.foreground_color_range.max_brightness = 0.99 criteria.min_font_size = 19 criteria.max_font_size = 42 possible = watermarker.search(criteria) for i in range(len(possible) - 1, -1, -1): watermarker.remove(possible[i]) watermarker.save("./output.pdf") if __name__ == "__main__": remove_watermark_with_formatting() ``` {{< /tab >}} {{< tab "document.pdf" >}} {{< tab-text >}} `document.pdf` is the sample file used in this example. Click [here](https://docs.groupdocs.com/watermark/python-net/_sample_files/developer-guide/advanced-usage/searching-and-modifying-watermarks/removing-found-watermarks/document.pdf) to download it. {{< /tab-text >}} {{< /tab >}} {{< tab "output.pdf" >}} ```text Binary file (PDF, 394 KB) ``` [Download full output](https://docs.groupdocs.com/watermark/python-net/_output_files/developer-guide/advanced-usage/searching-and-modifying-watermarks/removing-found-watermarks/remove_watermark_with_formatting/output.pdf) {{< /tab >}} {{< /tabs >}} ## Remove hyperlink watermarks Find hyperlinks with a particular URL using a regular expression, and remove only the entities that are hyperlinks. {{< tabs "code-example-remove-hyperlink-watermarks">}} {{< tab "remove_hyperlink_watermarks.py" >}} ```python import re from groupdocs.watermark import Watermarker from groupdocs.watermark.search import HyperlinkPossibleWatermark from groupdocs.watermark.search.search_criteria import TextSearchCriteria def remove_hyperlink_watermarks(): with Watermarker("./document.pdf") as watermarker: possible = watermarker.search(TextSearchCriteria(re.compile(r"someurl\.com"))) for i in range(len(possible) - 1, -1, -1): if isinstance(possible[i], HyperlinkPossibleWatermark): print(possible[i].text) watermarker.remove(possible[i]) watermarker.save("./output.pdf") if __name__ == "__main__": remove_hyperlink_watermarks() ``` {{< /tab >}} {{< tab "document.pdf" >}} {{< tab-text >}} `document.pdf` is the sample file used in this example. Click [here](https://docs.groupdocs.com/watermark/python-net/_sample_files/developer-guide/advanced-usage/searching-and-modifying-watermarks/removing-found-watermarks/document.pdf) to download it. {{< /tab-text >}} {{< /tab >}} {{< tab "output.pdf" >}} ```text Binary file (PDF, 395 KB) ``` [Download full output](https://docs.groupdocs.com/watermark/python-net/_output_files/developer-guide/advanced-usage/searching-and-modifying-watermarks/removing-found-watermarks/remove_hyperlink_watermarks/output.pdf) {{< /tab >}} {{< /tabs >}} --- ## Adding repeated watermarks Path: https://docs.groupdocs.com/watermark/python-net/adding-repeated-watermarks/ Repeated (tiled) watermarks let you cover entire pages with a pattern of text or images. You can control spacing, rotation, offsets, and choose different tiling templates by setting `tile_options` on the watermark. ## Add a repeated text watermark The example below tiles a diagonal text watermark across the whole page. The `line_spacing` and `watermark_spacing` are expressed as a percentage of the page, and `tile_type` selects the tiling template. {{< tabs "code-example-adding-repeated-watermarks">}} {{< tab "add_repeated_watermark.py" >}} ```python from groupdocs.watermark import Watermarker from groupdocs.watermark.watermarks import ( TextWatermark, Font, Color, TextAlignment, TileOptions, TileType, MeasureValue, TileMeasureType, ) def add_repeated_watermark(): with Watermarker("./sample.pdf") as watermarker: watermark = TextWatermark("CONFIDENTIAL", Font("Arial", 19.0)) watermark.foreground_color = Color.gray watermark.opacity = 0.3 watermark.rotate_angle = -45.0 watermark.text_alignment = TextAlignment.CENTER # Spacing between lines and between repeated watermarks, as a percentage of the page line_spacing = MeasureValue() line_spacing.measure_type = TileMeasureType.PERCENT line_spacing.value = 12.0 watermark_spacing = MeasureValue() watermark_spacing.measure_type = TileMeasureType.PERCENT watermark_spacing.value = 10.0 # Tile the watermark across the whole page tile_options = TileOptions() tile_options.tile_type = TileType.ONE_THIRD_OFFSET tile_options.line_spacing = line_spacing tile_options.watermark_spacing = watermark_spacing watermark.tile_options = tile_options watermarker.add(watermark) watermarker.save("./output.pdf") if __name__ == "__main__": add_repeated_watermark() ``` {{< /tab >}} {{< tab "sample.pdf" >}} {{< tab-text >}} `sample.pdf` is the sample file used in this example. Click [here](https://docs.groupdocs.com/watermark/python-net/_sample_files/developer-guide/basic-usage/adding-repeated-watermarks/sample.pdf) to download it. {{< /tab-text >}} {{< /tab >}} {{< tab "output.pdf" >}} ```text Binary file (PDF, 401 KB) ``` [Download full output](https://docs.groupdocs.com/watermark/python-net/_output_files/developer-guide/basic-usage/adding-repeated-watermarks/add_repeated_watermark/output.pdf) {{< /tab >}} {{< /tabs >}} You can replace the `TextWatermark` with an `ImageWatermark` to tile a logo or seal across the page in the same way — set the same `tile_options` on the image watermark. {{< alert style="info" >}} **Use case:** Protect sensitive PDFs by overlaying a tiled "Confidential" text across every page, or reinforce branding by repeating a logo in the background. {{< /alert >}} --- ## Result of added watermarks Path: https://docs.groupdocs.com/watermark/python-net/result-of-added-watermarks/ `Watermarker.add()` returns an `AddWatermarkResult` describing what was added. It exposes `number_applied_watermarks` and a `succeeded` collection; each succeeded item carries a unique identifier (`watermark_id`), the `watermark_type`, the `page_number`, the `watermark_position`, and the placed geometry (`left`, `top`, `width`, `height`). This enables tracing, searching, and removing specific watermarks later. ## Review the result of added watermarks The example below adds a text watermark to a two-page PDF and prints the result for each applied watermark. {{< tabs "code-example-result-of-added-watermarks">}} {{< tab "get_add_result.py" >}} ```python from groupdocs.watermark import Watermarker from groupdocs.watermark.watermarks import TextWatermark, Font from groupdocs.watermark.common import HorizontalAlignment, VerticalAlignment def get_add_result(): with Watermarker("./sample.pdf") as watermarker: watermark = TextWatermark("Test watermark", Font("Arial", 19.0)) watermark.horizontal_alignment = HorizontalAlignment.CENTER watermark.vertical_alignment = VerticalAlignment.CENTER result = watermarker.add(watermark) print("Applied watermarks:", result.number_applied_watermarks) for item in result.succeeded: print(f"- id={item.watermark_id} type={item.watermark_type} " f"page={item.page_number} position={item.watermark_position}") if __name__ == "__main__": get_add_result() ``` {{< /tab >}} {{< tab "sample.pdf" >}} {{< tab-text >}} `sample.pdf` is the two-page sample file used in this example. Click [here](https://docs.groupdocs.com/watermark/python-net/_sample_files/developer-guide/advanced-usage/adding-watermarks/result-of-added-watermarks/sample.pdf) to download it. {{< /tab-text >}} {{< /tab >}} {{< tab "get-add-result.txt" >}} ```text Applied watermarks: 3 - id=655b60a3-9c9e-4a6a-9f84-d78100469157 type=0 page=1 position=1 - id=f72574bf-306a-4b4b-8c71-3634a6080c6c type=0 page=2 position=1 - id=d3cd2017-3b63-4ae1-8e8c-c625c294f58a type=0 page=3 position=1 ``` [Download full output](https://docs.groupdocs.com/watermark/python-net/_output_files/developer-guide/advanced-usage/adding-watermarks/result-of-added-watermarks/get_add_result/get-add-result.txt) {{< /tab >}} {{< /tabs >}} The watermark was added to both pages, so `succeeded` contains two items, each with its own `watermark_id`. The `watermark_type` and `watermark_position` are enum values (here `type=0` corresponds to a text watermark). The `watermark_id` GUIDs let you locate and remove these exact watermarks in a later session. --- ## System Requirements Path: https://docs.groupdocs.com/watermark/python-net/system-requirements/ {{< alert style="info" >}} GroupDocs.Watermark for Python via .NET does not require any external software such as Microsoft Office or third-party document editors. To install the library, follow the steps in the [Installation]({{< ref "watermark/python-net/getting-started/installation" >}}) guide. {{< /alert >}} ## Supported Operating Systems GroupDocs.Watermark for Python via .NET runs on Windows, Linux, and macOS. The package ships as a platform-specific `.whl` on PyPI and `pip` picks the correct one automatically. ### Windows * Microsoft Windows 10 (x64) * Microsoft Windows 11 (x64) * Microsoft Windows Server 2016 and later ### Linux * Ubuntu 20.04+, Debian 11+, CentOS 8+, Fedora 36+ (glibc-based distributions) ### macOS * macOS 12 (Monterey) and later — Intel and Apple Silicon (M-series) ## Python Version GroupDocs.Watermark for Python via .NET supports **Python 3.5 through 3.14**. The wheel uses the `py3-none-{platform}` tag, meaning it works with any Python 3.x version in that range without per-version rebuilds. | Python Version | Supported | | --- | :---: | | 3.5 | Yes | | 3.6 | Yes | | 3.7 | Yes | | 3.8 | Yes | | 3.9 | Yes | | 3.10 | Yes | | 3.11 | Yes | | 3.12 | Yes | | 3.13 | Yes | | 3.14 | Yes | ## Package Manager GroupDocs.Watermark for Python via .NET is distributed via [PyPI](https://pypi.org/project/groupdocs-watermark-net/): ```bash pip install groupdocs-watermark-net ``` The PyPI index hosts one wheel per platform: | Platform | Wheel suffix | | --- | --- | | Windows 64-bit | `py3-none-win_amd64.whl` | | Linux x64 (glibc) | `py3-none-manylinux1_x86_64.whl` | | macOS Apple Silicon | `py3-none-macosx_11_0_arm64.whl` | | macOS Intel | `py3-none-macosx_10_14_x86_64.whl` | ## Optional Platform Dependencies GroupDocs.Watermark uses `libgdiplus` for drawing routines when a document contains images or rasterized output is produced. On Windows no extra setup is required. On Linux install `libgdiplus` and a minimal font set so that image-bearing documents render correctly. ### Linux Install the following packages on Debian / Ubuntu derivatives: ```bash sudo apt-get update sudo apt-get install -y libgdiplus libfontconfig1 libicu-dev ttf-mscorefonts-installer ``` - **libgdiplus** — Mono library providing a GDI+-compatible API on non-Windows operating systems. - **libfontconfig1** — needed for drawing functions (image and font rendering). - **libicu-dev** — required by the .NET runtime. Do **not** set `DOTNET_SYSTEM_GLOBALIZATION_INVARIANT`, as it disables culture-sensitive operations. - **ttf-mscorefonts-installer** — Microsoft-compatible fonts used by many Office-format documents. If it is not available, add the `contrib` component to your apt sources and re-run `apt-get update`. ### macOS Install `libgdiplus` using [Homebrew](https://brew.sh/): ```bash brew install mono-libgdiplus ``` If you see a `DllNotFoundException: libSkiaSharp` error after upgrading, an older system copy of SkiaSharp is shadowing the one bundled with the wheel. Rename it so the bundled copy wins: ```bash sudo mv /usr/local/lib/libSkiaSharp.dylib /usr/local/lib/libSkiaSharp.dylib.bak ``` ### Windows No extra dependencies — the wheel is self-contained. --- ## Working with worksheet backgrounds Path: https://docs.groupdocs.com/watermark/python-net/working-with-worksheet-backgrounds/ Each worksheet can have a background image, available through `SpreadsheetContent.worksheets[i].background_image`. It is `None` when the worksheet has no background. ## Extract information about worksheet backgrounds {{< tabs "code-example-extract-worksheet-backgrounds">}} {{< tab "extract_worksheet_backgrounds.py" >}} ```python from groupdocs.watermark import Watermarker from groupdocs.watermark.options.spreadsheet import SpreadsheetLoadOptions def extract_worksheet_backgrounds(): with Watermarker("./spreadsheet.xlsx", SpreadsheetLoadOptions()) as watermarker: content = watermarker.get_content() for i, worksheet in enumerate(content.worksheets): background = worksheet.background_image if background is not None: print(f"Worksheet {i}: background {background.width}x{background.height}") else: print(f"Worksheet {i}: no background") if __name__ == "__main__": extract_worksheet_backgrounds() ``` {{< /tab >}} {{< tab "spreadsheet.xlsx" >}} {{< tab-text >}} `spreadsheet.xlsx` is the sample file used in this example. Click [here](https://docs.groupdocs.com/watermark/python-net/_sample_files/developer-guide/advanced-usage/adding-watermarks/add-watermarks-to-spreadsheet-documents/working-with-worksheet-backgrounds/spreadsheet.xlsx) to download it. {{< /tab-text >}} {{< /tab >}} {{< tab "extract-worksheet-backgrounds.txt" >}} ```text Worksheet 0: no background Worksheet 1: no background ``` [Download full output](https://docs.groupdocs.com/watermark/python-net/_output_files/developer-guide/advanced-usage/adding-watermarks/add-watermarks-to-spreadsheet-documents/working-with-worksheet-backgrounds/extract_worksheet_backgrounds/extract-worksheet-backgrounds.txt) {{< /tab >}} {{< /tabs >}} ## Remove a background Set `background_image` to `None`: {{< tabs "code-example-remove-worksheet-background">}} {{< tab "remove_worksheet_background.py" >}} ```python from groupdocs.watermark import Watermarker from groupdocs.watermark.options.spreadsheet import SpreadsheetLoadOptions def remove_worksheet_background(): with Watermarker("./spreadsheet.xlsx", SpreadsheetLoadOptions()) as watermarker: content = watermarker.get_content() content.worksheets[0].background_image = None watermarker.save("./output.xlsx") if __name__ == "__main__": remove_worksheet_background() ``` {{< /tab >}} {{< tab "spreadsheet.xlsx" >}} {{< tab-text >}} `spreadsheet.xlsx` is the sample file used in this example. Click [here](https://docs.groupdocs.com/watermark/python-net/_sample_files/developer-guide/advanced-usage/adding-watermarks/add-watermarks-to-spreadsheet-documents/working-with-worksheet-backgrounds/spreadsheet.xlsx) to download it. {{< /tab-text >}} {{< /tab >}} {{< tab "output.xlsx" >}} ```text Binary file (XLSX, 9 KB) ``` [Download full output](https://docs.groupdocs.com/watermark/python-net/_output_files/developer-guide/advanced-usage/adding-watermarks/add-watermarks-to-spreadsheet-documents/working-with-worksheet-backgrounds/remove_worksheet_background/output.xlsx) {{< /tab >}} {{< /tabs >}} ## Watermark existing backgrounds Add a watermark to every worksheet that has a background image: {{< tabs "code-example-watermark-worksheet-backgrounds">}} {{< tab "watermark_worksheet_backgrounds.py" >}} ```python from groupdocs.watermark import Watermarker from groupdocs.watermark.watermarks import TextWatermark, Font, Color from groupdocs.watermark.options.spreadsheet import SpreadsheetLoadOptions def watermark_worksheet_backgrounds(): with Watermarker("./spreadsheet.xlsx", SpreadsheetLoadOptions()) as watermarker: watermark = TextWatermark("CONFIDENTIAL", Font("Arial", 19.0)) watermark.foreground_color = Color.red content = watermarker.get_content() for worksheet in content.worksheets: if worksheet.background_image is not None: worksheet.background_image.add(watermark) watermarker.save("./output.xlsx") if __name__ == "__main__": watermark_worksheet_backgrounds() ``` {{< /tab >}} {{< tab "spreadsheet.xlsx" >}} {{< tab-text >}} `spreadsheet.xlsx` is the sample file used in this example. Click [here](https://docs.groupdocs.com/watermark/python-net/_sample_files/developer-guide/advanced-usage/adding-watermarks/add-watermarks-to-spreadsheet-documents/working-with-worksheet-backgrounds/spreadsheet.xlsx) to download it. {{< /tab-text >}} {{< /tab >}} {{< tab "output.xlsx" >}} ```text Binary file (XLSX, 9 KB) ``` [Download full output](https://docs.groupdocs.com/watermark/python-net/_output_files/developer-guide/advanced-usage/adding-watermarks/add-watermarks-to-spreadsheet-documents/working-with-worksheet-backgrounds/watermark_worksheet_backgrounds/output.xlsx) {{< /tab >}} {{< /tabs >}} To add a fresh worksheet background watermark, use `SpreadsheetBackgroundWatermarkOptions` when calling `add()`. --- ## Customize watermarks Path: https://docs.groupdocs.com/watermark/python-net/basic-usage/customize/ GroupDocs.Watermark lets you control how a watermark looks and where it appears. Adjust color, font, alignment, rotation, opacity, and scaling to match your document's style. ## Customize text watermarks Use `TextWatermark` properties such as `foreground_color`, `opacity`, `rotate_angle`, `sizing_type`, `scale_factor`, `horizontal_alignment`, `vertical_alignment`, `x`, `y`, `width`, `height`, and `consider_parent_margins`. The example below scales a "DRAFT" watermark to the page, rotates it 45°, and makes it half-transparent. {{< tabs "code-example-customize">}} {{< tab "customize_watermark.py" >}} ```python from groupdocs.watermark import Watermarker from groupdocs.watermark.watermarks import TextWatermark, Font, Color, SizingType from groupdocs.watermark.common import HorizontalAlignment, VerticalAlignment def customize_watermark(): with Watermarker("./sample.pdf") as watermarker: watermark = TextWatermark("DRAFT", Font("Arial", 42.0)) watermark.foreground_color = Color.dark_orange # Scale the watermark relative to the page and rotate it watermark.sizing_type = SizingType.SCALE_TO_PARENT_DIMENSIONS watermark.scale_factor = 0.7 watermark.rotate_angle = 45.0 watermark.opacity = 0.5 watermark.horizontal_alignment = HorizontalAlignment.CENTER watermark.vertical_alignment = VerticalAlignment.CENTER watermarker.add(watermark) watermarker.save("./output.pdf") if __name__ == "__main__": customize_watermark() ``` {{< /tab >}} {{< tab "sample.pdf" >}} {{< tab-text >}} `sample.pdf` is the sample file used in this example. Click [here](https://docs.groupdocs.com/watermark/python-net/_sample_files/developer-guide/basic-usage/customize/sample.pdf) to download it. {{< /tab-text >}} {{< /tab >}} {{< tab "output.pdf" >}} ```text Binary file (PDF, 351 KB) ``` [Download full output](https://docs.groupdocs.com/watermark/python-net/_output_files/developer-guide/basic-usage/customize/customize_watermark/output.pdf) {{< /tab >}} {{< /tabs >}} {{< alert style="info" >}} **Use case:** Apply branded or legal disclaimers in a consistent style across pages (for example, "Confidential – Do Not Distribute"). {{< /alert >}} ## Customize image watermarks Image watermarks support the same positioning, rotation, and opacity properties. Place a logo, stamp, or seal exactly where you need it: {{< tabs "code-example-customize-image">}} {{< tab "customize_image_watermark.py" >}} ```python from groupdocs.watermark import Watermarker from groupdocs.watermark.watermarks import ImageWatermark from groupdocs.watermark.common import HorizontalAlignment, VerticalAlignment def customize_image_watermark(): with Watermarker("./sample.pdf") as watermarker: with ImageWatermark("./stamp.png") as watermark: watermark.horizontal_alignment = HorizontalAlignment.RIGHT watermark.vertical_alignment = VerticalAlignment.TOP watermark.rotate_angle = 15.0 watermark.opacity = 0.8 watermarker.add(watermark) watermarker.save("./output.pdf") if __name__ == "__main__": customize_image_watermark() ``` {{< /tab >}} {{< tab "sample.pdf" >}} {{< tab-text >}} `sample.pdf` and `stamp.png` are the sample files used in this example. Download [sample.pdf](https://docs.groupdocs.com/watermark/python-net/_sample_files/developer-guide/basic-usage/customize/sample.pdf) and [stamp.png](https://docs.groupdocs.com/watermark/python-net/_sample_files/developer-guide/basic-usage/customize/stamp.png). {{< /tab-text >}} {{< /tab >}} {{< tab "output.pdf" >}} ```text Binary file (PDF, 307 KB) ``` [Download full output](https://docs.groupdocs.com/watermark/python-net/_output_files/developer-guide/basic-usage/customize/customize_image_watermark/output.pdf) {{< /tab >}} {{< /tabs >}} --- ## Quick Start Guide Path: https://docs.groupdocs.com/watermark/python-net/quick-start-guide/ This guide provides a quick overview of how to set up and start using GroupDocs.Watermark for Python via .NET. The library opens a document, lets you add text or image watermarks, search for or remove existing ones, and saves the result back to the original format. ## Prerequisites To proceed, make sure you have: 1. **Configured** environment as described in the [System Requirements]({{< ref "watermark/python-net/getting-started/system-requirements.md" >}}) topic. 2. **Optionally** you may [Get a Temporary License](https://purchase.groupdocs.com/temporary-license/) to test all the product features. ## Set Up Your Development Environment For best practices, use a virtual environment to manage dependencies in Python applications. Learn more about virtual environments at the [Create and Use Virtual Environments](https://packaging.python.org/en/latest/guides/installing-using-pip-and-virtual-environments/#create-and-use-virtual-environments) documentation topic. ### Create and Activate a Virtual Environment Create a virtual environment: {{< tabs "example1">}} {{< tab "Windows" >}} ```ps py -m venv .venv ``` {{< /tab >}} {{< tab "Linux" >}} ```bash python3 -m venv .venv ``` {{< /tab >}} {{< tab "macOS" >}} ```bash python3 -m venv .venv ``` {{< /tab >}} {{< /tabs >}} Activate a virtual environment: {{< tabs "example2">}} {{< tab "Windows" >}} ```ps .venv\Scripts\activate ``` {{< /tab >}} {{< tab "Linux" >}} ```bash source .venv/bin/activate ``` {{< /tab >}} {{< tab "macOS" >}} ```bash source .venv/bin/activate ``` {{< /tab >}} {{< /tabs >}} ### Install `groupdocs-watermark-net` Package After activating the virtual environment, run the following command in your terminal to install the latest version of the package: {{< tabs "example3">}} {{< tab "Windows" >}} ```ps py -m pip install groupdocs-watermark-net ``` {{< /tab >}} {{< tab "Linux" >}} ```bash python3 -m pip install groupdocs-watermark-net ``` {{< /tab >}} {{< tab "macOS" >}} ```bash python3 -m pip install groupdocs-watermark-net ``` {{< /tab >}} {{< /tabs >}} Ensure the package is installed successfully. You should see the message ```bash Successfully installed groupdocs-watermark-net-* ``` ## Example 1: Add a text watermark To quickly test the library, let's open a PDF, add a diagonal "CONFIDENTIAL" text watermark, and save the result. {{< tabs "demo_app_add_text_watermark">}} {{< tab "add_text_watermark.py" >}} ```python import os from groupdocs.watermark import Watermarker, License from groupdocs.watermark.watermarks import TextWatermark, Font, Color def add_text_watermark(): # Optionally set a license license_path = os.path.abspath("./GroupDocs.Watermark.lic") if os.path.exists(license_path): License().set_license(license_path) # Open the document, add a text watermark, and save the result with Watermarker("./sample.pdf") as watermarker: watermark = TextWatermark("CONFIDENTIAL", Font("Arial", 48)) watermark.foreground_color = Color.red watermark.opacity = 0.5 watermark.rotate_angle = 45.0 watermarker.add(watermark) watermarker.save("./watermarked.pdf") if __name__ == "__main__": add_text_watermark() ``` {{< /tab >}} {{< tab "sample.pdf" >}} {{< tab-text >}} `sample.pdf` is the sample file used in this example. Click [here](https://docs.groupdocs.com/watermark/python-net/_sample_files/getting-started/quick-start-guide/sample.pdf) to download it. {{< /tab-text >}} {{< /tab >}} {{< tab "watermarked.pdf" >}} ```text Binary file (PDF, 351 KB) ``` [Download full output](https://docs.groupdocs.com/watermark/python-net/_output_files/getting-started/quick-start-guide/add_text_watermark/watermarked.pdf) {{< /tab >}} {{< /tabs >}} Your folder tree should look similar to the following directory structure: ```Directory 📂 demo-app ├──add_text_watermark.py ├──sample.pdf └──GroupDocs.Watermark.lic (Optionally) ``` ### Run the App {{< tabs "run_the_app_add_text_watermark">}} {{< tab "Windows" >}} ```ps py add_text_watermark.py ``` {{< /tab >}} {{< tab "Linux" >}} ```bash python3 add_text_watermark.py ``` {{< /tab >}} {{< tab "macOS" >}} ```bash python3 add_text_watermark.py ``` {{< /tab >}} {{< /tabs >}} After running the app you can deactivate the virtual environment by executing `deactivate` or closing your shell. ### Explanation - `Watermarker("./sample.pdf")`: Opens the document. Used as a context manager so the native document handle is released. - `TextWatermark("CONFIDENTIAL", Font("Arial", 48))`: Builds a text watermark and its font. - `watermark.foreground_color` / `opacity` / `rotate_angle`: Style the watermark (red, half-transparent, rotated 45°). - `watermarker.add(watermark)` then `watermarker.save("./watermarked.pdf")`: Applies the watermark and writes the result. ## Example 2: Add an image watermark In this example we stamp a logo image onto a Word document. {{< tabs "demo_app_add_image_watermark">}} {{< tab "add_image_watermark.py" >}} ```python import os from groupdocs.watermark import Watermarker, License from groupdocs.watermark.watermarks import ImageWatermark def add_image_watermark(): # Optionally set a license license_path = os.path.abspath("./GroupDocs.Watermark.lic") if os.path.exists(license_path): License().set_license(license_path) # Open the document, add an image watermark, and save the result with Watermarker("./sample.docx") as watermarker: watermark = ImageWatermark("./logo.png") watermark.opacity = 0.5 watermarker.add(watermark) watermarker.save("./watermarked.docx") if __name__ == "__main__": add_image_watermark() ``` {{< /tab >}} {{< tab "sample.docx" >}} {{< tab-text >}} `sample.docx` and `logo.png` are the sample files used in this example. Download [sample.docx](https://docs.groupdocs.com/watermark/python-net/_sample_files/getting-started/quick-start-guide/sample.docx) and [logo.png](https://docs.groupdocs.com/watermark/python-net/_sample_files/getting-started/quick-start-guide/logo.png). {{< /tab-text >}} {{< /tab >}} {{< tab "watermarked.docx" >}} ```text Binary file (DOCX, 125 KB) ``` [Download full output](https://docs.groupdocs.com/watermark/python-net/_output_files/getting-started/quick-start-guide/add_image_watermark/watermarked.docx) {{< /tab >}} {{< /tabs >}} ### Run the App {{< tabs "run_the_app_add_image_watermark">}} {{< tab "Windows" >}} ```ps py add_image_watermark.py ``` {{< /tab >}} {{< tab "Linux" >}} ```bash python3 add_image_watermark.py ``` {{< /tab >}} {{< tab "macOS" >}} ```bash python3 add_image_watermark.py ``` {{< /tab >}} {{< /tabs >}} ### Explanation - `ImageWatermark("./logo.png")`: Builds an image watermark from a logo file. You can also pass a stream. - `watermark.opacity = 0.5`: Makes the logo half-transparent so the underlying content stays readable. - `watermarker.add(watermark)` then `watermarker.save("./watermarked.docx")`: Applies the watermark and writes the result. ## Example 3: Read document information Sometimes you only need a document's metadata. `get_document_info()` returns the file type, page count, and size without modifying the document. {{< tabs "demo_app_get_document_info">}} {{< tab "get_document_info.py" >}} ```python import os from groupdocs.watermark import Watermarker, License def get_document_info(): # Optionally set a license license_path = os.path.abspath("./GroupDocs.Watermark.lic") if os.path.exists(license_path): License().set_license(license_path) # Open the document and read its metadata with Watermarker("./sample.pdf") as watermarker: info = watermarker.get_document_info() print("File type:", info.file_type) print("Pages:", info.page_count) print("Size, bytes:", info.size) if __name__ == "__main__": get_document_info() ``` {{< /tab >}} {{< tab "sample.pdf" >}} {{< tab-text >}} `sample.pdf` is the sample file used in this example. Click [here](https://docs.groupdocs.com/watermark/python-net/_sample_files/getting-started/quick-start-guide/sample.pdf) to download it. {{< /tab-text >}} {{< /tab >}} {{< tab "get-document-info.txt" >}} ```text File type: Pdf (.pdf) - Pdf Pages: 3 Size, bytes: 271889 ``` [Download full output](https://docs.groupdocs.com/watermark/python-net/_output_files/getting-started/quick-start-guide/get_document_info/get-document-info.txt) {{< /tab >}} {{< /tabs >}} ### Run the App {{< tabs "run_the_app_get_document_info">}} {{< tab "Windows" >}} ```ps py get_document_info.py ``` {{< /tab >}} {{< tab "Linux" >}} ```bash python3 get_document_info.py ``` {{< /tab >}} {{< tab "macOS" >}} ```bash python3 get_document_info.py ``` {{< /tab >}} {{< /tabs >}} ### Explanation - `watermarker.get_document_info()`: Returns an `IDocumentInfo` with the document's `file_type`, `page_count`, and `size`. ## Next Steps After completing the basics, explore additional resources to enhance your usage: - [Supported Document Formats]({{< ref "watermark/python-net/getting-started/supported-document-formats.md" >}}): Review the full list of supported file types. - [Licensing and Subscription]({{< ref "watermark/python-net/getting-started/licensing-and-subscription.md" >}}): Check details on licensing and evaluation. - [Developer Guide]({{< ref "watermark/python-net/developer-guide" >}}): Dive into adding, searching, modifying, and removing watermarks across every supported family. - [Technical Support]({{< ref "watermark/python-net/technical-support" >}}): Contact support for assistance if you encounter issues. --- ## Supported file formats Path: https://docs.groupdocs.com/watermark/python-net/supported-document-formats/ ## 🚀 Quick Format Lookup **Popular Formats:** [.docx](#-microsoft-word-formats) | [.pdf](#-pdf-formats) | [.xlsx](#-microsoft-excel-formats) | [.pptx](#-microsoft-powerpoint-formats) | [.png](#-image-formats) | [.jpg](#-image-formats) Each format may support different watermarking capabilities: - ✅ Full support (Add / Search / Remove) - ⚠️ Partial support (some limitations) - ❌ Not supported --- ## 📄 Microsoft Word Formats | Format | Description | Load | Save | Add | Search | Remove | Remarks | |--------|-------------|------|------|-----|--------|--------|---------| | `.doc` | Microsoft Word 97 - 2007 Document | ✅ | ✅ | ✅ | ✅ | ✅ | | | `.dot` | Microsoft Word 97 - 2007 Template | ✅ | ✅ | ✅ | ✅ | ✅ | | | `.docx` | Office Open XML WordprocessingML Document (macro-free) | ✅ | ✅ | ✅ | ✅ | ✅ | | | `.docm` | Office Open XML WordprocessingML Macro-Enabled Document | ✅ | ✅ | ✅ | ✅ | ✅ | | | `.dotx` | Office Open XML WordprocessingML Template (macro-free) | ✅ | ✅ | ✅ | ✅ | ✅ | | | `.dotm` | Word Open XML Macro-Enabled Document | ✅ | ✅ | ✅ | ✅ | ✅ | | | `.rtf` | Rich Text Format File | ✅ | ✅ | ✅ | ✅ | ✅ | | | `.odt` | ODF Text Document | ✅ | ✅ | ✅ | ✅ | ✅ | | 📘 See examples for [Word]({{< ref "/watermark/python-net/developer-guide/advanced-usage/adding-watermarks/add-watermarks-to-word-processing-documents/_index.md" >}}) formats --- ## 📊 Microsoft Excel Formats | Format | Description | Load | Save | Add | Search | Remove | Remarks | |--------|-------------|------|------|-----|--------|--------|---------| | `.xlsx` | OOXML 2007-2010 | ✅ | ✅ | ✅ | ✅ | ✅ | | | `.xlsm` | OOXML Macro Enabled Workbook | ✅ | ✅ | ✅ | ✅ | ✅ | | | `.xltm` | OOXML Macro Enabled Workbook Template | ✅ | ✅ | ✅ | ✅ | ✅ | | | `.xlt` | Microsoft Excel Template File | ✅ | ✅ | ✅ | ✅ | ✅ | | | `.xltx` | Excel Open XML Spreadsheet Template | ✅ | ✅ | ✅ | ✅ | ✅ | | | `.xls` | Excel Workbook 97-2003 | ✅ | ✅ | ✅ | ✅ | ✅ | | 📘 Excel watermarking [examples]({{< ref "/watermark/python-net/developer-guide/advanced-usage/adding-watermarks/add-watermarks-to-spreadsheet-documents/_index.md" >}}) --- ## 📈 Microsoft PowerPoint Formats | Format | Description | Load | Save | Add | Search | Remove | Remarks | |--------|-------------|------|------|-----|--------|--------|---------| | `.pptx` | OOXML Presentation | ✅ | ✅ | ✅ | ✅ | ✅ | | | `.pptm` | OOXML Macro Enabled Presentation | ✅ | ✅ | ✅ | ✅ | ✅ | | | `.ppsx` | OOXML SlideShow | ✅ | ✅ | ✅ | ✅ | ✅ | | | `.ppsm` | OOXML Macros Enabled Presentation | ✅ | ✅ | ✅ | ✅ | ✅ | | | `.potx` | OOXML Presentation Template | ✅ | ✅ | ✅ | ✅ | ✅ | | | `.potm` | OOXML Macro Enabled Presentation Template | ✅ | ✅ | ✅ | ✅ | ✅ | | | `.ppt` | PowerPoint Presentation 97-2003 | ✅ | ✅ | ✅ | ✅ | ✅ | | | `.pps` | PowerPoint SlideShow 97-2003 | ✅ | ✅ | ✅ | ✅ | ✅ | | 📘 PowerPoint watermarking [examples]({{< ref "/watermark/python-net/developer-guide/advanced-usage/adding-watermarks/add-watermarks-to-presentation-documents/_index.md" >}}) --- ## 🧾 PDF Formats | Format | Description | Load | Save | Add | Search | Remove | Remarks | |--------|-------------|------|------|-----|--------|--------|---------| | `.pdf` | PDF (Adobe Portable Document) format | ✅ | ✅ | ✅ | ✅ | ✅ | Watermark searching and removing is not available for rasterized pages | 📘 Add watermark to [PDF]({{< ref "/watermark/python-net/developer-guide/advanced-usage/adding-watermarks/add-watermarks-to-pdf-documents/_index.md" >}}) --- ## ✉️ Email Formats | Format | Description | Load | Save | Add | Search | Remove | Remarks | |--------|-------------|------|------|-----|--------|--------|---------| | `.eml` | Email Message Format | ✅ | ✅ | ⚠️ | ⚠️ | ⚠️ | Watermark management is available for attached documents and images | | `.emlx` | Apple Mail Message | ✅ | ✅ | ⚠️ | ⚠️ | ⚠️ | Watermark management is available for attached documents and images | | `.oft` | Microsoft Outlook Email Template | ✅ | ✅ | ⚠️ | ⚠️ | ⚠️ | Watermark management is available for attached documents and images | | `.msg` | Outlook Email Message Format | ✅ | ✅ | ⚠️ | ⚠️ | ⚠️ | Watermark management is available for attached documents and images | 📘 Add watermark to MSG [files]({{< ref "/watermark/python-net/developer-guide/advanced-usage/adding-watermarks/add-watermarks-to-email-attachments/_index.md" >}}) --- ## 🖼️ Image Formats | Format | Description | Load | Save | Add | Search | Remove | Remarks | |--------|-------------|------|------|-----|--------|--------|---------| | `.bmp` | Bitmap Picture (BMP) | ✅ | ✅ | ✅ | ❌ | ❌ | | | `.gif` | Graphics Interchange Format (GIF) | ✅ | ✅ | ✅ | ❌ | ❌ | | | `.jpg` / `.jpeg` / `.jpe` | Joint Photographic Experts Group (JPEG) | ✅ | ✅ | ✅ | ❌ | ❌ | | | `.jp2` | JPEG2000 Core Image File | ✅ | ✅ | ✅ | ❌ | ❌ | | | `.png` | Portable Network Graphics (PNG) | ✅ | ✅ | ✅ | ❌ | ❌ | | | `.tiff` | Tagged Image File Format (TIFF) | ✅ | ✅ | ✅ | ❌ | ❌ | | | `.webp` | WebP Image | ✅ | ✅ | ✅ | ❌ | ❌ | | 📘 Image watermarking [examples]({{< ref "/watermark/python-net/developer-guide/advanced-usage/adding-watermarks/add-watermarks-to-images/_index.md" >}}) --- ## 🎨 Microsoft Visio Formats | Format | Description | Load | Save | Add | Search | Remove | Remarks | |--------|-------------|------|------|-----|--------|--------|---------| | `.vsd` | Microsoft Visio 2003-2010 Drawing | ✅ | ✅ | ✅ | ✅ | ✅ | | | `.vdx` | Microsoft Visio 2003-2010 XML Drawing | ✅ | ✅ | ✅ | ✅ | ✅ | | | `.vsdx` | Microsoft Visio Drawing | ✅ | ✅ | ✅ | ✅ | ✅ | | | `.vstx` | Microsoft Visio File Format | ✅ | ✅ | ✅ | ✅ | ✅ | | | `.vss` | Microsoft Visio 2003-2010 Stencil | ✅ | ✅ | ✅ | ✅ | ✅ | | | `.vssx` | Visio Stencil File Format | ✅ | ✅ | ✅ | ✅ | ✅ | | | `.vsdm` | Visio Macro-Enabled Drawing | ✅ | ✅ | ✅ | ✅ | ✅ | | | `.vssm` | Microsoft Visio Macro Enabled File Format | ✅ | ✅ | ✅ | ✅ | ✅ | | | `.vstm` | Visio Macro-Enabled Drawing Template | ✅ | ✅ | ✅ | ✅ | ✅ | | | `.vtx` | VTX Chiptune File | ✅ | ✅ | ✅ | ✅ | ✅ | | | `.vsx` | Microsoft Visio 2003-2010 XML Stencil | ✅ | ✅ | ✅ | ✅ | ✅ | | --- ## ℹ️ Notes - Watermarking capabilities may vary depending on the document content and structure. - For email formats, watermark operations are limited to attached documents and images within the email. - For image formats, search and remove operations are not supported - only adding watermarks is available. - PDF watermark searching and removing is not available for rasterized pages. - For the latest updates, refer to the [Changelog](https://docs.groupdocs.com/watermark/python-net/release-notes/). - If a format you need is not listed, feel free to [contact support](https://forum.groupdocs.com/). --- {{< alert style="tip" >}} **Can’t find your file format?** We’re here to help! Please post a request on our [Free Support Forum](https://forum.groupdocs.com/c/watermark/19), and our team will assist you. {{< /alert >}} --- ## Watermarks in PDF document Path: https://docs.groupdocs.com/watermark/python-net/watermarks-in-pdf-document/ A PDF watermark can be added in three different ways, each with its own trade-offs: - **XObjects** — added to the real page content. They are not removed by simple sanitization, which makes them the hardest to remove. - **Artifacts** — added as page artifacts. Use `PdfArtifactWatermarkOptions`. - **Annotations** — added as page annotations. Use `PdfAnnotationWatermarkOptions`; these can be made **print-only** so they appear when the document is printed but are hidden on screen. ## Add artifact and annotation watermarks The example below adds an artifact text watermark, an annotation text watermark, and a **print-only** annotation image watermark. {{< tabs "code-example-pdf-watermarks">}} {{< tab "add_pdf_watermarks.py" >}} ```python from groupdocs.watermark import Watermarker from groupdocs.watermark.watermarks import TextWatermark, ImageWatermark, Font from groupdocs.watermark.common import HorizontalAlignment, VerticalAlignment from groupdocs.watermark.options.pdf import ( PdfLoadOptions, PdfArtifactWatermarkOptions, PdfAnnotationWatermarkOptions, ) def add_pdf_watermarks(): with Watermarker("./document.pdf", PdfLoadOptions()) as watermarker: # Add as an artifact artifact_text = TextWatermark("Artifact", Font("Arial", 8.0)) artifact_text.horizontal_alignment = HorizontalAlignment.RIGHT watermarker.add(artifact_text, PdfArtifactWatermarkOptions()) # Add as an annotation annotation_text = TextWatermark("Annotation", Font("Arial", 8.0)) annotation_text.horizontal_alignment = HorizontalAlignment.LEFT annotation_text.vertical_alignment = VerticalAlignment.TOP watermarker.add(annotation_text, PdfAnnotationWatermarkOptions()) # Add a print-only annotation (visible when printed, hidden on screen) with ImageWatermark("./logo.png") as image_watermark: image_watermark.horizontal_alignment = HorizontalAlignment.RIGHT image_watermark.vertical_alignment = VerticalAlignment.TOP options = PdfAnnotationWatermarkOptions() options.print_only = True watermarker.add(image_watermark, options) watermarker.save("./output.pdf") if __name__ == "__main__": add_pdf_watermarks() ``` {{< /tab >}} {{< tab "document.pdf" >}} {{< tab-text >}} `document.pdf` and `logo.png` are the sample files used in this example. Download [document.pdf](https://docs.groupdocs.com/watermark/python-net/_sample_files/developer-guide/advanced-usage/adding-watermarks/add-watermarks-to-pdf-documents/document.pdf) and [logo.png](https://docs.groupdocs.com/watermark/python-net/_sample_files/developer-guide/advanced-usage/adding-watermarks/add-watermarks-to-pdf-documents/logo.png). {{< /tab-text >}} {{< /tab >}} {{< tab "output.pdf" >}} ```text Binary file (PDF, 528 KB) ``` [Download full output](https://docs.groupdocs.com/watermark/python-net/_output_files/developer-guide/advanced-usage/adding-watermarks/add-watermarks-to-pdf-documents/watermarks-in-pdf-document/add_pdf_watermarks/output.pdf) {{< /tab >}} {{< /tabs >}} To work with watermarks already present in a PDF — extracting, modifying, or removing existing XObjects, artifacts, and annotations — see [Existing objects in PDF document]({{< ref "watermark/python-net/developer-guide/advanced-usage/adding-watermarks/add-watermarks-to-pdf-documents/existing-objects-in-pdf-document.md" >}}). --- ## Watermarks in word processing document Path: https://docs.groupdocs.com/watermark/python-net/watermarks-in-word-processing-document/ When you add a watermark to a Microsoft Word document, a shape with the appropriate content is placed in the section headers. `WordProcessingWatermarkSectionOptions` (and `WordProcessingWatermarkPagesOptions`) let you set the shape's `name` and `alternative_text`, and apply text or image effects through the `effects` property. ## Add an image watermark with effects The example applies brightness, contrast, and a chroma-key to an image watermark using `WordProcessingImageEffects`. {{< tabs "code-example-word-watermark-effects">}} {{< tab "add_watermark_with_effects.py" >}} ```python from groupdocs.watermark import Watermarker from groupdocs.watermark.watermarks import ImageWatermark, Color from groupdocs.watermark.options.word_processing import ( WordProcessingLoadOptions, WordProcessingWatermarkSectionOptions, WordProcessingImageEffects, ) def add_watermark_with_effects(): with Watermarker("./document.docx", WordProcessingLoadOptions()) as watermarker: with ImageWatermark("./logo.png") as watermark: effects = WordProcessingImageEffects() effects.brightness = 0.7 effects.contrast = 0.6 effects.chroma_key = Color.red options = WordProcessingWatermarkSectionOptions() options.name = "Shape 1" options.alternative_text = "Company logo watermark" options.effects = effects watermarker.add(watermark, options) watermarker.save("./output.docx") if __name__ == "__main__": add_watermark_with_effects() ``` {{< /tab >}} {{< tab "document.docx" >}} {{< tab-text >}} `document.docx` and `logo.png` are the sample files used in this example. Download [document.docx](https://docs.groupdocs.com/watermark/python-net/_sample_files/developer-guide/advanced-usage/adding-watermarks/add-watermarks-to-word-processing-documents/document.docx) and [logo.png](https://docs.groupdocs.com/watermark/python-net/_sample_files/developer-guide/advanced-usage/adding-watermarks/add-watermarks-to-word-processing-documents/logo.png). {{< /tab-text >}} {{< /tab >}} {{< tab "output.docx" >}} ```text Binary file (DOCX, 120 KB) ``` [Download full output](https://docs.groupdocs.com/watermark/python-net/_output_files/developer-guide/advanced-usage/adding-watermarks/add-watermarks-to-word-processing-documents/watermarks-in-word-processing-document/add_watermark_with_effects/output.docx) {{< /tab >}} {{< /tabs >}} For a text watermark, use `WordProcessingTextEffects` instead — set its `line_format` (enabled, color, dash style, line style, and weight) and assign it to `options.effects`. `WordProcessingImageEffects` also exposes `gray_scale` and `border_line_format`. To work with shapes already present in a document, see [Existing objects in word processing document]({{< ref "watermark/python-net/developer-guide/advanced-usage/adding-watermarks/add-watermarks-to-word-processing-documents/existing-objects-in-word-processing-document.md" >}}). --- ## Working with worksheet headers and footers Path: https://docs.groupdocs.com/watermark/python-net/working-with-worksheet-headers-and-footers/ Each worksheet has a collection of header/footer slots, available through `SpreadsheetContent.worksheets[i].headers_footers`. Each slot has a `header_footer_type` and three `sections` (left, center, right), and each section can carry a `script` (text) or an `image`. ## Extract information about headers and footers {{< tabs "code-example-worksheet-headers-footers">}} {{< tab "extract_headers_footers.py" >}} ```python from groupdocs.watermark import Watermarker from groupdocs.watermark.options.spreadsheet import SpreadsheetLoadOptions def extract_headers_footers(): with Watermarker("./spreadsheet.xlsx", SpreadsheetLoadOptions()) as watermarker: content = watermarker.get_content() worksheet = content.worksheets[0] print(f"Worksheet 0 header/footer slots: {len(worksheet.headers_footers)}") for header_footer in worksheet.headers_footers: sections = list(header_footer.sections) with_content = [s for s in sections if s.image is not None or s.script] print(f" type={header_footer.header_footer_type} " f"sections={len(sections)} with_content={len(with_content)}") if __name__ == "__main__": extract_headers_footers() ``` {{< /tab >}} {{< tab "spreadsheet.xlsx" >}} {{< tab-text >}} `spreadsheet.xlsx` is the sample file used in this example. Click [here](https://docs.groupdocs.com/watermark/python-net/_sample_files/developer-guide/advanced-usage/adding-watermarks/working-with-worksheet-headers-and-footers/spreadsheet.xlsx) to download it. {{< /tab-text >}} {{< /tab >}} {{< tab "extract-headers-footers.txt" >}} ```text Worksheet 0 header/footer slots: 6 type=0 sections=3 with_content=0 type=1 sections=3 with_content=0 type=2 sections=3 with_content=0 type=3 sections=3 with_content=0 type=4 sections=3 with_content=0 type=5 sections=3 with_content=0 ``` [Download full output](https://docs.groupdocs.com/watermark/python-net/_output_files/developer-guide/advanced-usage/adding-watermarks/add-watermarks-to-spreadsheet-documents/working-with-worksheet-headers-and-footers/extract_headers_footers/extract-headers-footers.txt) {{< /tab >}} {{< /tabs >}} ## Clear and watermark header/footer content To clear a section, set its `image` and `script` to `None`. To watermark the existing header/footer images, add a watermark to each non-empty `image`: {{< tabs "code-example-worksheet-headers-footers-watermark">}} {{< tab "watermark_headers_footers.py" >}} ```python from groupdocs.watermark import Watermarker from groupdocs.watermark.watermarks import TextWatermark, Font from groupdocs.watermark.options.spreadsheet import SpreadsheetLoadOptions def watermark_headers_footers(): with Watermarker("./spreadsheet.xlsx", SpreadsheetLoadOptions()) as watermarker: watermark = TextWatermark("Protected", Font("Arial", 8.0)) content = watermarker.get_content() for worksheet in content.worksheets: for header_footer in worksheet.headers_footers: for section in header_footer.sections: if section.image is not None: section.image.add(watermark) watermarker.save("./output.xlsx") if __name__ == "__main__": watermark_headers_footers() ``` {{< /tab >}} {{< tab "spreadsheet.xlsx" >}} {{< tab-text >}} `spreadsheet.xlsx` is the sample file used in this example. Click [here](https://docs.groupdocs.com/watermark/python-net/_sample_files/developer-guide/advanced-usage/adding-watermarks/working-with-worksheet-headers-and-footers/spreadsheet.xlsx) to download it. {{< /tab-text >}} {{< /tab >}} {{< tab "output.xlsx" >}} ```text Binary file (XLSX, 9 KB) ``` [Download full output](https://docs.groupdocs.com/watermark/python-net/_output_files/developer-guide/advanced-usage/adding-watermarks/add-watermarks-to-spreadsheet-documents/working-with-worksheet-headers-and-footers/watermark_headers_footers/output.xlsx) {{< /tab >}} {{< /tabs >}} To add a fresh header/footer watermark instead, use `SpreadsheetWatermarkHeaderFooterOptions` (see the [section index]({{< ref "watermark/python-net/developer-guide/advanced-usage/adding-watermarks/add-watermarks-to-spreadsheet-documents" >}})). --- ## Licensing and evaluation Path: https://docs.groupdocs.com/watermark/python-net/licensing-and-evaluation/ To explore the system effectively, you may want immediate access to the API. GroupDocs.Watermark simplifies this by offering various purchase plans, along with a Free Trial and a 30-day Temporary License for evaluation. {{< alert style="info" >}} To learn more about licensing options, purchasing, and evaluation policies, refer to the [Purchase Policies and FAQ](https://purchase.groupdocs.com/policies) section. {{< /alert >}} ## Purchased License After purchasing GroupDocs.Watermark for Python via .NET, you will receive a license file that unlocks the full functionality of the API. A few rules apply: - Apply the license **only once** per process, in your start-up code. - Apply it **before** constructing any `Watermarker` or other GroupDocs.Watermark object. - A license can be applied from a file path, from a binary stream (handy when the license is an embedded resource), or as a [Metered License](https://purchase.groupdocs.com/faqs/licensing/metered/) that bills by usage. Use the [set_license](https://reference.groupdocs.com/watermark/python-net/) method to license the component. Calling it more than once is harmless — it simply wastes a little processor time. ### Set a license from a file The example below applies a license from a file path. It reads the path from the `GROUPDOCS_LIC_PATH` environment variable and falls back to a local `GroupDocs.Watermark.lic` file: {{< tabs "code-example-set-license-from-file" >}} {{< tab "set_license_from_file.py" >}} ```python import os from groupdocs.watermark import License def set_license_from_file(): # Resolve the license path from the environment, with a local fallback license_path = os.environ.get("GROUPDOCS_LIC_PATH", "./GroupDocs.Watermark.lic") # Apply the license before using any watermarking features if os.path.exists(license_path): License().set_license(license_path) print("License set successfully.") else: print("License file not found. Running in evaluation mode.") if __name__ == "__main__": set_license_from_file() ``` {{< /tab >}} {{< /tabs >}} ### Set a license from a stream You can also apply a license from any readable binary stream — useful when the license ships as an embedded resource: {{< tabs "code-example-set-license-from-stream" >}} {{< tab "set_license_from_stream.py" >}} ```python import os from groupdocs.watermark import License def set_license_from_stream(): # Resolve the license path from the environment, with a local fallback license_path = os.environ.get("GROUPDOCS_LIC_PATH", "./GroupDocs.Watermark.lic") # Apply the license from an open binary stream if os.path.exists(license_path): with open(license_path, "rb") as stream: License().set_license(stream) print("License set successfully.") else: print("License file not found. Running in evaluation mode.") if __name__ == "__main__": set_license_from_stream() ``` {{< /tab >}} {{< /tabs >}} ### Set a metered license A Metered License lets you pay for what you use. Set the public and private keys with [set_metered_key](https://reference.groupdocs.com/watermark/python-net/) before using the API: {{< tabs "code-example-set-metered-license" >}} {{< tab "set_metered_license.py" >}} ```python from groupdocs.watermark import Metered def set_metered_license(): # Replace these placeholders with your real metered public/private keys public_key = "*****" private_key = "*****" # Skip the call until real keys are supplied (placeholder keys are rejected) if "*" in public_key or "*" in private_key: print("Provide real metered keys to enable metered licensing.") return # Apply the metered keys before using any watermarking features Metered().set_metered_key(public_key, private_key) print("Metered license set successfully.") if __name__ == "__main__": set_metered_license() ``` {{< /tab >}} {{< /tabs >}} ### Changing the license file name You are not required to keep the license file name as `GroupDocs.Watermark.lic`. You can rename it to any preferred name and use that name when applying the license in your application. ### "Cannot find license filename" exception When you download the license from the GroupDocs website it is saved as `GroupDocs.Watermark.lic`. However, some web browsers may automatically append `.xml`, resulting in `GroupDocs.Watermark.lic.xml`. If your Windows settings are configured to hide file extensions (the default), the file may still appear as `GroupDocs.Watermark.lic` in File Explorer even though the actual name is `GroupDocs.Watermark.lic.xml`. This discrepancy can cause `set_license` to throw an exception. To fix it, manually rename the file to remove the `.xml` extension, or disable "Hide extensions for known file types" in Windows. ## How to evaluate GroupDocs.Watermark You can evaluate GroupDocs.Watermark for Python via .NET without purchasing a license by using one of the following options. ### Free Trial The evaluation version is identical to the purchased one; it becomes fully licensed once you set a license. Without a license the Free Trial gives you access to the API's features, but with some limitations: - A maximum of **10 documents** can be loaded per application run. - Only **one watermark** can be added to a document per editing session. - The output document carries an **evaluation watermark** stamp. ### Temporary License To experience the complete features of GroupDocs.Watermark without the limitations of the Free Trial, you can request a 30-day ["Temporary License"](https://purchase.groupdocs.com/temporary-license). --- ## Update watermarks Path: https://docs.groupdocs.com/watermark/python-net/basic-usage/update/ You can search a document for existing watermarks and modify them in place — for example, replace the text of a text watermark or swap the image of an image watermark. ## Update text watermarks Search for a watermark by its text content, then assign a new value to each match. The example below opens a document that already contains a "CONFIDENTIAL" watermark and replaces it with "APPROVED". {{< tabs "code-example-update">}} {{< tab "update_watermark.py" >}} ```python from groupdocs.watermark import Watermarker from groupdocs.watermark.search.search_criteria import TextSearchCriteria def update_watermark(): with Watermarker("./watermarked-document.pdf") as watermarker: # Find the watermarks whose text matches the criteria possible = watermarker.search(TextSearchCriteria("CONFIDENTIAL")) print("Found", len(possible), "possible watermark(s).") for watermark in possible: try: watermark.text = "APPROVED" except Exception: # Some found entities do not support text editing — skip them pass watermarker.save("./output.pdf") if __name__ == "__main__": update_watermark() ``` {{< /tab >}} {{< tab "watermarked-document.pdf" >}} {{< tab-text >}} `watermarked-document.pdf` is the sample file used in this example. Click [here](https://docs.groupdocs.com/watermark/python-net/_sample_files/developer-guide/basic-usage/update/watermarked-document.pdf) to download it. {{< /tab-text >}} {{< /tab >}} {{< tab "output.pdf" >}} ```text Binary file (PDF, 479 KB) ``` [Download full output](https://docs.groupdocs.com/watermark/python-net/_output_files/developer-guide/basic-usage/update/update_watermark/output.pdf) {{< /tab >}} {{< /tabs >}} ## Update image watermarks Image watermarks can be found with perceptual hashing (`ImageDctHashSearchCriteria`) and updated by assigning new bytes to `image_data`. The example below finds the logo watermark and replaces it with an "APPROVED" stamp: {{< tabs "code-example-update-image">}} {{< tab "update_image_watermark.py" >}} ```python from groupdocs.watermark import Watermarker from groupdocs.watermark.search.search_criteria import ImageDctHashSearchCriteria def update_image_watermark(): with Watermarker("./watermarked-document.docx") as watermarker: criteria = ImageDctHashSearchCriteria("./logo.png") criteria.max_difference = 0.9 possible = watermarker.search(criteria) with open("./stamp.png", "rb") as f: image_data = f.read() for watermark in possible: try: watermark.image_data = image_data except Exception: # Some found entities do not support image editing — skip them pass watermarker.save("./output.docx") if __name__ == "__main__": update_image_watermark() ``` {{< /tab >}} {{< tab "watermarked-document.docx" >}} {{< tab-text >}} `watermarked-document.docx`, `logo.png`, and `stamp.png` are the sample files used in this example. Download [watermarked-document.docx](https://docs.groupdocs.com/watermark/python-net/_sample_files/developer-guide/basic-usage/update/watermarked-document.docx), [logo.png](https://docs.groupdocs.com/watermark/python-net/_sample_files/developer-guide/basic-usage/update/logo.png), and [stamp.png](https://docs.groupdocs.com/watermark/python-net/_sample_files/developer-guide/basic-usage/update/stamp.png). {{< /tab-text >}} {{< /tab >}} {{< tab "output.docx" >}} ```text Binary file (DOCX, 18 KB) ``` [Download full output](https://docs.groupdocs.com/watermark/python-net/_output_files/developer-guide/basic-usage/update/update_image_watermark/output.docx) {{< /tab >}} {{< /tabs >}} --- ## AI agents and LLM integration Path: https://docs.groupdocs.com/watermark/python-net/agents-and-llm-integration/ GroupDocs.Watermark for Python via .NET is designed to work smoothly with AI coding assistants such as Claude Code, Cursor, and GitHub Copilot in agent mode. ## Built into the package The `groupdocs-watermark-net` wheel ships a bundled `AGENTS.md` reference. Once the package is installed, AI tools discover it automatically at `groupdocs/watermark/AGENTS.md`. It covers the canonical imports, the open → add → save workflow, per-operation recipes, licensing, the full API-surface tables, and troubleshooting — everything an agent needs to write correct watermarking code without guessing. ## MCP server For on-demand documentation lookups, point your AI tool at the GroupDocs MCP server: ```json { "mcpServers": { "groupdocs-docs": { "url": "https://docs.groupdocs.com/mcp" } } } ``` This works with Claude Code (`~/.claude/settings.json`), Cursor (`.cursor/mcp.json`), VS Code Copilot (`.vscode/mcp.json`), and any MCP-compatible client. ## Machine-readable documentation LLM-optimized documentation for retrieval-augmented generation and context loading is available at [`https://docs.groupdocs.com/watermark/python-net/llms-full.txt`](https://docs.groupdocs.com/watermark/python-net/llms-full.txt). ## AGENTS.md reference The complete reference bundled inside the wheel is reproduced below. ````markdown # GroupDocs.Watermark for Python via .NET -- AGENTS.md > Instructions for AI agents working with this package. Add, search, and remove text and image watermarks across PDF, Word, Excel, PowerPoint, Visio, email, and image formats through one unified API -- with no MS Office or other external software installed. ## Install ```bash pip install groupdocs-watermark-net ``` **Python**: 3.5 - 3.14 | **Platforms**: Windows, Linux, macOS ## Resources | Resource | URL | |---|---| | Documentation | https://docs.groupdocs.com/watermark/python-net/ | | LLM-optimized docs | https://docs.groupdocs.com/watermark/python-net/llms-full.txt | | API reference | https://reference.groupdocs.com/watermark/python-net/ | | Code examples | https://docs.groupdocs.com/watermark/python-net/developer-guide/ | | Release notes | https://releases.groupdocs.com/watermark/python-net/release-notes/ | | PyPI | https://pypi.org/project/groupdocs-watermark-net/ | | Free support forum | https://forum.groupdocs.com/c/watermark/ | | Temporary license | https://purchase.groupdocs.com/temporary-license | ## MCP Server If your environment has MCP configured, you can connect your AI tool to the GroupDocs documentation server for on-demand API lookups: ```json { "mcpServers": { "groupdocs-docs": { "url": "https://docs.groupdocs.com/mcp" } } } ``` Works with Claude Code (`~/.claude/settings.json`), Cursor (`.cursor/mcp.json`), VS Code Copilot (`.vscode/mcp.json`), and any MCP-compatible client. If MCP is unavailable, fall back to the LLM-optimized docs URL above and this file -- both are shipped inside the wheel. ## Imports ```python from groupdocs.watermark import License, Metered, Watermarker, WatermarkerSettings, UnitOfMeasurement from groupdocs.watermark.common import Attachment, AttachmentWatermarkableImage, Dimension, FileType, FormatFamily, HorizontalAlignment, VerticalAlignment, IDocumentInfo, PageInfo, Point, Rectangle from groupdocs.watermark.options import LoadOptions, OoxmlLoadOptions, SaveOptions, WatermarkOptions, PreviewOptions, PreviewFormats, CreatePageStream, ReleasePageStream from groupdocs.watermark.watermarks import TextWatermark, ImageWatermark, Color, Font, FontStyle, TextAlignment, SizingType, MarginType, Margins, TileOptions, Thickness from groupdocs.watermark.watermarks.results import AddWatermarkResult, ImageWatermarkResult, TextWatermarkResult, WatermarkPosition, WatermarkType from groupdocs.watermark.search import PossibleWatermark, PossibleWatermarkCollection, FormattedTextFragment, FormattedTextFragmentCollection from groupdocs.watermark.search.search_criteria import TextSearchCriteria, ImageSearchCriteria, ColorRange, SizeSearchCriteria, RotateAngleSearchCriteria ``` > Format-specific content/options live under sub-namespaces: `groupdocs.watermark.contents.{pdf,word_processing,spreadsheet,presentation,diagram,email,image}` and `groupdocs.watermark.options.{...}` mirror them. Import these only when you need format-specific shape/content access. ## Add Text Watermark ```python from groupdocs.watermark import Watermarker from groupdocs.watermark.watermarks import TextWatermark, Font, Color with Watermarker("document.pdf") as watermarker: watermark = TextWatermark("CONFIDENTIAL", Font("Arial", 48)) watermark.foreground_color = Color.red watermark.opacity = 0.5 watermarker.add(watermark) watermarker.save("watermarked.pdf") ``` ## Add Image Watermark ```python from groupdocs.watermark import Watermarker from groupdocs.watermark.watermarks import ImageWatermark, SizingType with Watermarker("document.docx") as watermarker: watermark = ImageWatermark("logo.png") watermark.sizing_type = SizingType.SCALE_TO_PARENT_DIMENSIONS watermark.scale_factor = 0.5 watermark.opacity = 0.7 watermarker.add(watermark) watermarker.save("watermarked.docx") ``` ## Search and Remove Watermarks ```python from groupdocs.watermark import Watermarker from groupdocs.watermark.search.search_criteria import TextSearchCriteria with Watermarker("watermarked.pdf") as watermarker: criteria = TextSearchCriteria("CONFIDENTIAL") # also: ImageSearchCriteria(...) possible = watermarker.search(criteria) for wm in possible: print(wm.text, wm.x, wm.y) watermarker.remove(possible) # remove the whole collection watermarker.save("clean.pdf") ``` ## Licensing ```python from groupdocs.watermark import License # From file License().set_license("path/to/license.lic") # From stream with open("license.lic", "rb") as f: License().set_license(f) ``` Or auto-apply: `export GROUPDOCS_LIC_PATH="path/to/license.lic"` **Evaluation vs licensed.** Without a license the library still runs, but PDF output carries an evaluation watermark stamp and non-PDF targets show an equivalent evaluation mark; there is also a page/document count cap. Set `GROUPDOCS_LIC_PATH` (or call `License().set_license(...)`) and re-run to clear both. A 30-day full license is free: https://purchase.groupdocs.com/temporary-license ## Supported Formats | Category | Formats | |---|---| | **Word Processing** | DOC, DOCX, DOCM, DOT, DOTX, RTF, ODT, OTT | | **Spreadsheets** | XLS, XLSX, XLSM, XLSB, ODS | | **Presentations** | PPT, PPTX, PPTM, PPS, PPSX, ODP | | **Fixed-Layout** | PDF | | **Diagrams** | VSD, VSDX, VSS, VST, VDX | | **Email** | MSG, EML, EMLX | | **Images** | BMP, JPG, JPEG, PNG, GIF, TIFF, WEBP | ## API Reference ### Watermarker | Method | Returns | Description | |---|---|---| | `Watermarker(file_path)` | | Open a document (path, or a file-like stream) | | `get_document_info()` | `IDocumentInfo` | Format, page count, per-page dimensions | | `add(watermark)` | `AddWatermarkResult` | Add a text or image watermark | | `search(search_criteria=None)` | `PossibleWatermarkCollection` | Find existing watermarks (optionally filtered) | | `remove(possible_watermark)` | `None` | Remove a watermark or a whole collection | | `get_images(search_criteria=None)` | `WatermarkableImageCollection` | Enumerate raster images in the document | | `generate_preview(preview_options)` | `None` | Render pages to images via a page-stream callback | | `get_content()` | `Content` | Format-specific content tree (advanced) | | `save(file_path)` | `WatermarkResult` | Save to a path, or a file-like stream | | `dispose()` | `None` | Release the document (or use a `with` block) | ### Watermark types - `TextWatermark(text, font)` — `foreground_color`, `background_color`, `opacity`, `rotate_angle`, `sizing_type`, `text_alignment`, `horizontal_alignment`, `vertical_alignment`, `margins`, `tile_options`. - `ImageWatermark(file_path)` or `ImageWatermark(stream=...)` — `opacity`, `scale_factor`, `sizing_type`, `rotate_angle`, alignment + margins as above. ## Key Patterns - **Properties**: use `snake_case` -- auto-mapped to .NET `PascalCase` - **Context managers**: `with Watermarker(...) as x:` ensures resources are released - **Streams**: pass `open("file", "rb")` or `io.BytesIO(data)` where .NET expects Stream - **Stream write-back**: `BytesIO` objects are updated after .NET writes to them - **Colors**: `Color.red`, `Color(255, 0, 0)`, `Color.from_argb(...)`, or `"#RRGGBB"` strings (see `groupdocs.watermark.watermarks.Color`) - **Enums**: case-insensitive, lazy-loaded (e.g., `FileType.DOCX`, `SizingType.SCALE_TO_PARENT_DIMENSIONS`) - **Collections**: `for item in result` and `len(result)` work on .NET collections (e.g. `search()` results) ## Platform Requirements | Platform | Requirements | |---|---| | Windows | None | | Linux | `apt install libgdiplus libfontconfig1 ttf-mscorefonts-installer` | | macOS | `brew install mono-libgdiplus` | ## Troubleshooting **`System.Drawing.Common is not supported`** -- install libgdiplus: `sudo apt install libgdiplus` (Linux) / `brew install mono-libgdiplus` (macOS) **`Gdip` type initializer exception** -- outdated libgdiplus: `brew reinstall mono-libgdiplus` (macOS) **Garbled text / missing fonts** -- install fonts: `sudo apt install ttf-mscorefonts-installer fontconfig && sudo fc-cache -f` **`DllNotFoundException: libSkiaSharp`** -- stale system copy conflicts with bundled version. Rename it: `sudo mv /usr/local/lib/libSkiaSharp.dylib /usr/local/lib/libSkiaSharp.dylib.bak` **`DOTNET_SYSTEM_GLOBALIZATION_INVARIANT` errors** -- do NOT set this. Install ICU: `sudo apt install libicu-dev` **`TypeLoadException`** -- reinstall: `pip install --force-reinstall groupdocs-watermark-net` **Still stuck?** Post your question at https://forum.groupdocs.com/c/watermark/ -- the development team responds directly. ```` --- ## Clear watermarks Path: https://docs.groupdocs.com/watermark/python-net/basic-usage/clear/ You can search a document for existing watermarks and remove them. The example below finds a "CONFIDENTIAL" text watermark and removes it, producing a clean document. ## Remove text watermarks Iterate the search results in reverse so removing an item does not shift the indexes still to visit, and call `remove()` for each match. {{< tabs "code-example-clear">}} {{< tab "clear_watermark.py" >}} ```python from groupdocs.watermark import Watermarker from groupdocs.watermark.search.search_criteria import TextSearchCriteria def clear_watermark(): with Watermarker("./watermarked-document.pdf") as watermarker: possible = watermarker.search(TextSearchCriteria("CONFIDENTIAL")) # Remove in reverse so indexes stay valid as items are deleted for i in range(len(possible) - 1, -1, -1): watermarker.remove(possible[i]) watermarker.save("./output.pdf") if __name__ == "__main__": clear_watermark() ``` {{< /tab >}} {{< tab "watermarked-document.pdf" >}} {{< tab-text >}} `watermarked-document.pdf` is the sample file used in this example. Click [here](https://docs.groupdocs.com/watermark/python-net/_sample_files/developer-guide/basic-usage/clear/watermarked-document.pdf) to download it. {{< /tab-text >}} {{< /tab >}} {{< tab "output.pdf" >}} ```text Binary file (PDF, 394 KB) ``` [Download full output](https://docs.groupdocs.com/watermark/python-net/_output_files/developer-guide/basic-usage/clear/clear_watermark/output.pdf) {{< /tab >}} {{< /tabs >}} {{< alert style="info" >}} **Use case:** Remove outdated labels such as "Draft" or "Internal Use Only" before sharing a document externally. {{< /alert >}} ## Remove image watermarks Image watermarks can be found with perceptual hashing and removed the same way: {{< tabs "code-example-clear-image">}} {{< tab "clear_image_watermark.py" >}} ```python from groupdocs.watermark import Watermarker from groupdocs.watermark.search.search_criteria import ImageDctHashSearchCriteria def clear_image_watermark(): with Watermarker("./watermarked-document.docx") as watermarker: criteria = ImageDctHashSearchCriteria("./logo.png") criteria.max_difference = 0.9 possible = watermarker.search(criteria) # Remove in reverse so indexes stay valid as items are deleted for i in range(len(possible) - 1, -1, -1): watermarker.remove(possible[i]) watermarker.save("./output.docx") if __name__ == "__main__": clear_image_watermark() ``` {{< /tab >}} {{< tab "watermarked-document.docx" >}} {{< tab-text >}} `watermarked-document.docx` and `logo.png` are the sample files used in this example. Download [watermarked-document.docx](https://docs.groupdocs.com/watermark/python-net/_sample_files/developer-guide/basic-usage/clear/watermarked-document.docx) and [logo.png](https://docs.groupdocs.com/watermark/python-net/_sample_files/developer-guide/basic-usage/clear/logo.png). {{< /tab-text >}} {{< /tab >}} {{< tab "output.docx" >}} ```text Binary file (DOCX, 12 KB) ``` [Download full output](https://docs.groupdocs.com/watermark/python-net/_output_files/developer-guide/basic-usage/clear/clear_image_watermark/output.docx) {{< /tab >}} {{< /tabs >}} --- ## Document preview Path: https://docs.groupdocs.com/watermark/python-net/basic-usage/preview/ GroupDocs.Watermark can render document pages as images so you can show page thumbnails without fully opening a document in a viewer. You drive the render with a `create_page_stream` callback that supplies a writable file stream for each page — the library writes the page image to it and closes it for you. ## Generate a document preview Set `PreviewOptions` with a `create_page_stream` callback, choose the `preview_format`, and list the `page_numbers` to render. {{< tabs "code-example-preview">}} {{< tab "generate_preview.py" >}} ```python from groupdocs.watermark import Watermarker from groupdocs.watermark.options import PreviewOptions, PreviewFormats def generate_preview(): # Supply a writable file stream for each page to render def create_page_stream(page_number): return open(f"./output-page-{page_number}.png", "wb") with Watermarker("./sample.pdf") as watermarker: options = PreviewOptions(create_page_stream) options.preview_format = PreviewFormats.PNG options.page_numbers = [1, 2] watermarker.generate_preview(options) if __name__ == "__main__": generate_preview() ``` {{< /tab >}} {{< tab "sample.pdf" >}} {{< tab-text >}} `sample.pdf` is the two-page sample file used in this example. Click [here](https://docs.groupdocs.com/watermark/python-net/_sample_files/developer-guide/basic-usage/preview/sample.pdf) to download it. {{< /tab-text >}} {{< /tab >}} {{< tab "generate-preview-outputs.zip" >}} ```text output-page-1.png (597 KB) output-page-2.png (129 KB) ``` [Download full output](https://docs.groupdocs.com/watermark/python-net/_output_files/developer-guide/basic-usage/preview/generate_preview/generate-preview-outputs.zip) {{< /tab >}} {{< /tabs >}} The page images are written to the current directory — one PNG per requested page. Use `PreviewFormats.JPEG` or `PreviewFormats.BMP` for other formats, and set `options.width` / `options.height` to control the rendered size. {{< alert style="info" >}} The library owns the lifecycle of the stream returned by `create_page_stream` and closes it after writing the page. A two-argument form, `PreviewOptions(create_page_stream, release_page_stream)`, is also available, but the release callback receives `stream=None` because the bridge has already closed the stream — capture the stream in the `create_page_stream` closure if you need to act on it. {{< /alert >}} {{< alert style="info" >}} **Use case:** Generate page previews to display in a web app, dashboard, or document-management system without requiring users to download the full file. {{< /alert >}} --- ## How to run examples Path: https://docs.groupdocs.com/watermark/python-net/how-to-run-examples/ The complete project [GroupDocs.Watermark for Python via .NET](https://github.com/groupdocs-watermark/GroupDocs.Watermark-for-Python-via-.NET) with code examples and sample files is hosted on GitHub. ## Prerequisites - [Python 3.5–3.14](https://www.python.org/downloads/). - On Linux, the .NET runtime dependencies: `libgdiplus`, `libfontconfig1`, `libicu-dev`. On macOS: `mono-libgdiplus` (via Homebrew). ## Get the code ```bash git clone https://github.com/groupdocs-watermark/GroupDocs.Watermark-for-Python-via-.NET.git cd ./GroupDocs.Watermark-for-Python-via-.NET/Examples ``` ## Project structure ``` Examples/ ├── run_all_examples.py # Runs every example and prints a pass/fail summary ├── _run_example.py # Per-example wrapper (applies license, isolates evaluation limits) ├── requirements.txt ├── licensing/ # Set a license from a file, a stream, or a metered key ├── getting-started/ │ └── hello-world/ # Minimal add-a-watermark example └── developer-guide/ ├── basic-usage/ # Add text/image/custom-font/tile watermarks, document info, formats └── advanced-usage/ # Loading options, format-specific placement, search & modify ``` ## Set up ```bash pip install -r requirements.txt ``` > Version 26.6.0 is not yet on PyPI (the latest PyPI release is 25.12). Until it is published, `requirements.txt` points at the platform wheel on the [GroupDocs Releases](https://releases.groupdocs.com/watermark/python-net/) site. See [Installation](https://docs.groupdocs.com/watermark/python-net/installation.md) for the per-platform wheel names. To run the examples with the full feature set, apply a license. The simplest way is the `GROUPDOCS_LIC_PATH` environment variable, which the package applies automatically at import: {{< tabs "set-license" >}} {{< tab "Windows" >}} ```batch set GROUPDOCS_LIC_PATH=C:\path\to\GroupDocs.Watermark.lic ``` {{< /tab >}} {{< tab "Linux / macOS" >}} ```bash export GROUPDOCS_LIC_PATH=/path/to/GroupDocs.Watermark.lic ``` {{< /tab >}} {{< /tabs >}} Without a license the suite still runs in evaluation mode — each example runs in its own subprocess, so the evaluation document-load cap is reset per example and the suite stays green. ## Run the examples Run the full suite, which prints a pass/fail summary at the end: ```bash python run_all_examples.py ``` You can also run any single example by navigating to its folder and running the script directly — each example uses paths relative to its own folder, and writes its result next to the script as `output.*`: ```bash cd getting-started/hello-world python hello_world.py ``` ## Run with Docker The repository ships a `Dockerfile` that builds a Linux image with Python 3.13, the .NET runtime dependencies, and the package preinstalled. ```bash # Build the image docker build -t watermark-examples . # Run unlicensed (evaluation mode) docker run --rm watermark-examples # Run with a license mounted from the host docker run --rm \ -v /path/to/license:/lic:ro \ -e GROUPDOCS_LIC_PATH=/lic/your-license.lic \ watermark-examples ``` ## Continuous integration The `.github/workflows/` directory contains a workflow that runs the full example suite on every push, on `ubuntu-latest` with Python 3.13. The same matrix is reproducible locally via the `Dockerfile` above. ## Troubleshooting - **`System.Drawing.Common is not supported` / `libgdiplus` errors (Linux/macOS)** — install the GDI+ library: `sudo apt install libgdiplus libfontconfig1` (Linux) or `brew install mono-libgdiplus` (macOS). - **Garbled or missing text** — install fonts: `sudo apt install ttf-mscorefonts-installer fontconfig && sudo fc-cache -f`. - **Evaluation limits** — output carries an evaluation watermark and only the first watermark per document is kept. Apply a license (see above) to remove the limits; a free 30-day [temporary license](https://purchase.groupdocs.com/temporary-license) is available. ## Contribute If you would like to add or improve an example, we encourage you to contribute to the project. All examples in this repository are open source and can be freely used in your own applications. Fork the repository, edit the source code, and open a pull request. --- ## Technical Support Path: https://docs.groupdocs.com/watermark/python-net/technical-support/ GroupDocs provides unlimited free technical support for all of its products. Support is available to all users, including evaluation. The support is provided at [Free Support Forum](https://forum.groupdocs.com/) and [Paid Support Helpdesk](https://helpdesk.groupdocs.com/). {{< alert style="info" >}} Please note that GroupDocs does not provide technical support over the phone. Phone support is only available for sales and purchase questions. {{< /alert >}} ## GroupDocs Free Support Forum If you need help with GroupDocs.Watermark, consider the following: * Make sure you are using the latest GroupDocs.Watermark version before reporting an issue. See [PyPI](https://pypi.org/project/groupdocs-watermark-net) to find out about the latest version. * Have a look through the forums, this documentation, and the API Reference before reporting an issue – perhaps your question has already been answered. * Post your question at [GroupDocs.Watermark Free Support Forum](https://forum.groupdocs.com/c/watermark/9), and we'll assist you. Questions are answered directly by the GroupDocs.Watermark development team. * When expecting a reply on the forums, please allow for time zone differences. ## Paid Support Helpdesk The paid support issues has higher priority comparing to the free support requests. * Post your question at the [Paid Support Helpdesk](https://helpdesk.groupdocs.com/) to set higher priority for the issue. ## Report an Issue or Feature Request When posting your issue, question, or feature request with GroupDocs.Watermark, follow these simple steps to make sure it is resolved in the most efficient way: * Include the original document and possibly the code snippet that is causing the problem. If you need to attach a few files, zip them into one. It is safe to attach your documents to GroupDocs.Forums because only you and the GroupDocs developers will have access to the attached files. * Add information about the environment you are facing the issue. * Try to report one issue per thread. If you have another issue, question, or feature request, please report it in a separate thread. --- ## Get document info Path: https://docs.groupdocs.com/watermark/python-net/get-document-info/ GroupDocs.Watermark can obtain a document's basic information — file type, page count, and size — before you process it. The `get_document_info()` method works on a `Watermarker` opened from either a file path or a stream. ## Get document information from a file {{< tabs "code-example-get-document-info">}} {{< tab "get_document_info.py" >}} ```python from groupdocs.watermark import Watermarker def get_document_info(): with Watermarker("./sample.docx") as watermarker: info = watermarker.get_document_info() print("File type:", info.file_type) print("Pages:", info.page_count) print("Size, bytes:", info.size) if __name__ == "__main__": get_document_info() ``` {{< /tab >}} {{< tab "sample.docx" >}} {{< tab-text >}} `sample.docx` is the sample file used in this example. Click [here](https://docs.groupdocs.com/watermark/python-net/_sample_files/developer-guide/basic-usage/get-document-info/sample.docx) to download it. {{< /tab-text >}} {{< /tab >}} {{< tab "get-document-info.txt" >}} ```text File type: Docx (.docx) - WordProcessing Pages: 3 Size, bytes: 121298 ``` [Download full output](https://docs.groupdocs.com/watermark/python-net/_output_files/developer-guide/basic-usage/get-document-info/get_document_info/get-document-info.txt) {{< /tab >}} {{< /tabs >}} ## Get document information from a stream A document can also be opened from any readable stream: {{< tabs "code-example-get-document-info-stream">}} {{< tab "get_document_info_from_stream.py" >}} ```python import io from groupdocs.watermark import Watermarker def get_document_info_from_stream(): with open("./sample.docx", "rb") as f: stream = io.BytesIO(f.read()) with Watermarker(stream) as watermarker: info = watermarker.get_document_info() print("File type:", info.file_type) print("Pages:", info.page_count) print("Size, bytes:", info.size) if __name__ == "__main__": get_document_info_from_stream() ``` {{< /tab >}} {{< tab "sample.docx" >}} {{< tab-text >}} `sample.docx` is the sample file used in this example. Click [here](https://docs.groupdocs.com/watermark/python-net/_sample_files/developer-guide/basic-usage/get-document-info/sample.docx) to download it. {{< /tab-text >}} {{< /tab >}} {{< tab "get-document-info-from-stream.txt" >}} ```text File type: Docx (.docx) - WordProcessing Pages: 3 Size, bytes: 121298 ``` [Download full output](https://docs.groupdocs.com/watermark/python-net/_output_files/developer-guide/basic-usage/get-document-info/get_document_info_from_stream/get-document-info-from-stream.txt) {{< /tab >}} {{< /tabs >}} {{< alert style="info" >}} **Use case:** Validate documents before processing — for example, reject unsupported file types or confirm page limits. {{< /alert >}} --- ## Get supported file formats Path: https://docs.groupdocs.com/watermark/python-net/get-supported-file-formats/ Quickly retrieve the complete list of file formats supported by GroupDocs.Watermark. This lets your application check compatibility dynamically before processing a document — for example, to validate user-uploaded files. ## List supported file formats `FileType.get_supported_file_types()` returns every supported file type. Each item exposes its `extension` and a friendly description. {{< tabs "code-example-get-supported-file-formats">}} {{< tab "list_supported_formats.py" >}} ```python from groupdocs.watermark.common import FileType def list_supported_formats(): # Enumerate every file type the library can open supported_file_types = FileType.get_supported_file_types() for file_type in sorted(supported_file_types, key=lambda x: x.extension): print(file_type) if __name__ == "__main__": list_supported_formats() ``` {{< /tab >}} {{< tab "list-supported-formats.txt" >}} ```text Bmp (.bmp) - Image Doc (.doc) - WordProcessing Docm (.docm) - WordProcessing Docx (.docx) - WordProcessing Dot (.dot) - WordProcessing Dotm (.dotm) - WordProcessing Dotx (.dotx) - WordProcessing Eml (.eml) - Email Emlx (.emlx) - Email Gif (.gif) - Image [TRUNCATED] ``` [Download full output](https://docs.groupdocs.com/watermark/python-net/_output_files/developer-guide/basic-usage/get-supported-file-formats/list_supported_formats/list-supported-formats.txt) {{< /tab >}} {{< /tabs >}} {{< alert style="info" >}} **Use case:** Build flexible applications that validate user-uploaded files and tell the user whether watermarking is supported. {{< /alert >}}