# GroupDocs.Comparison for Python via .NET — Complete Documentation > GroupDocs.Comparison for Python via .NET developer documentation. Learn how to diff DOCX, PPTX, XLSX, and PDF files using the Python API. --- ## Compare Documents Path: /comparison/python-net/developer-guide/comparing-documents/compare-documents/ The change-detection algorithm of [GroupDocs.Comparison](https://products.groupdocs.com/comparison/python-net) detects changes across many document parts and blocks: - Text blocks — paragraphs, words, and characters. - Tables. - Images. - Shapes. The result document highlights detected changes with colour: - Added — **blue**. - Modified — **green**. - Style — **green**. - Deleted — **red**. The styling scheme is fully customizable — see [Customize changes styles]({{< ref "comparison/python-net/developer-guide/comparing-documents/customize-changes-styles" >}}). To compare two documents, follow these steps: 1. Instantiate a [`Comparer`](https://reference.groupdocs.com/comparison/python-net/groupdocs.comparison/comparer) with the source document path or stream. 2. Call [`add()`](https://reference.groupdocs.com/comparison/python-net/groupdocs.comparison/comparer/#add) and specify the target document path or stream. 3. Call [`compare()`](https://reference.groupdocs.com/comparison/python-net/groupdocs.comparison/comparer/#compare) and specify the result file path or output stream. ## Example 1: Compare documents from file paths The simplest way to compare two documents is by passing file paths to `Comparer`. {{< tabs "compare-documents-path">}} {{< tab "compare_documents.py" >}} ```python from groupdocs.comparison import Comparer def compare_documents(): # Initialize Comparer with the source file path with Comparer("./source.docx") as comparer: # Add the target file and run the comparison comparer.add("./target.docx") comparer.compare("./result.docx") if __name__ == "__main__": compare_documents() ``` {{< /tab >}} {{< tab "source.docx" >}} {{< tab-text >}} `source.docx` is the source file used in this example. Click [here](/comparison/python-net/_sample_files/developer-guide/comparing-documents/compare-documents/source.docx) to download it. {{< /tab-text >}} {{< /tab >}} {{< tab "target.docx" >}} {{< tab-text >}} `target.docx` is the target file used in this example. Click [here](/comparison/python-net/_sample_files/developer-guide/comparing-documents/compare-documents/target.docx) to download it. {{< /tab-text >}} {{< /tab >}} {{< tab "result.docx" >}} ```text Binary file (DOCX, 25 KB) ``` [Download full output](/comparison/python-net/_output_files/developer-guide/comparing-documents/compare-documents/compare_documents/result.docx) {{< /tab >}} {{< /tabs >}} The output file looks like this: ![](/comparison/python-net/images/compare-documents.png) ## Example 2: Compare documents from streams You can also feed `Comparer` open file streams — useful when the source and target arrive over the network, from a database, or from another in-memory source. {{< tabs "compare-documents-stream">}} {{< tab "compare_documents_from_stream.py" >}} ```python from groupdocs.comparison import Comparer def compare_documents_from_stream(): # Open the source and target as binary streams with open("./source.docx", "rb") as source_stream, \ open("./target.docx", "rb") as target_stream: with Comparer(source_stream) as comparer: comparer.add(target_stream) comparer.compare("./result.docx") if __name__ == "__main__": compare_documents_from_stream() ``` {{< /tab >}} {{< tab "source.docx" >}} {{< tab-text >}} `source.docx` is the source file used in this example. Click [here](/comparison/python-net/_sample_files/developer-guide/comparing-documents/compare-documents/source.docx) to download it. {{< /tab-text >}} {{< /tab >}} {{< tab "target.docx" >}} {{< tab-text >}} `target.docx` is the target file used in this example. Click [here](/comparison/python-net/_sample_files/developer-guide/comparing-documents/compare-documents/target.docx) to download it. {{< /tab-text >}} {{< /tab >}} {{< tab "result.docx" >}} ```text Binary file (DOCX, 25 KB) ``` [Download full output](/comparison/python-net/_output_files/developer-guide/comparing-documents/compare-documents/compare_documents_from_stream/result.docx) {{< /tab >}} {{< /tabs >}} ## Example 3: Compare documents and write the result to a stream Combine input streams with an output stream to keep everything in memory: {{< tabs "compare-documents-output-stream">}} {{< tab "compare_documents_to_stream.py" >}} ```python from groupdocs.comparison import Comparer def compare_documents_to_stream(): with Comparer("./source.docx") as comparer: comparer.add("./target.docx") with open("./result.docx", "wb") as out_stream: comparer.compare(out_stream) if __name__ == "__main__": compare_documents_to_stream() ``` {{< /tab >}} {{< tab "source.docx" >}} {{< tab-text >}} `source.docx` is the source file used in this example. Click [here](/comparison/python-net/_sample_files/developer-guide/comparing-documents/compare-documents/source.docx) to download it. {{< /tab-text >}} {{< /tab >}} {{< tab "target.docx" >}} {{< tab-text >}} `target.docx` is the target file used in this example. Click [here](/comparison/python-net/_sample_files/developer-guide/comparing-documents/compare-documents/target.docx) to download it. {{< /tab-text >}} {{< /tab >}} {{< tab "result.docx" >}} ```text Binary file (DOCX, 25 KB) ``` [Download full output](/comparison/python-net/_output_files/developer-guide/comparing-documents/compare-documents/compare_documents_to_stream/result.docx) {{< /tab >}} {{< /tabs >}} ## Next steps - [Compare multiple documents]({{< ref "comparison/python-net/developer-guide/comparing-documents/compare-multiple-documents" >}}) — compare a source against multiple targets. - [Accept or reject detected changes]({{< ref "comparison/python-net/developer-guide/comparing-documents/accept-or-reject-detected-changes" >}}) — review changes individually before producing the result. - [Adjusting comparison sensitivity]({{< ref "comparison/python-net/developer-guide/comparing-documents/adjusting-comparison-sensitivity" >}}) — fine-tune the change-detection threshold. - [Customize changes styles]({{< ref "comparison/python-net/developer-guide/comparing-documents/customize-changes-styles" >}}) — change the highlight colours and styles. --- ## Features Overview Path: /comparison/python-net/getting-started/features-overview/ GroupDocs.Comparison for Python via .NET is a feature-rich document comparison library. The sections below summarize what the API can do; each one links to the developer-guide topic that covers it in depth. ## File comparison [GroupDocs.Comparison](https://products.groupdocs.com/comparison/python-net) identifies differences between two or more files at paragraph, word, and character levels. It detects content changes — additions, deletions, modifications — and style and formatting changes such as bold, italic, underline, strikethrough, and font changes. See: [Compare documents]({{< ref "comparison/python-net/developer-guide/comparing-documents/compare-documents" >}}). ## Multi-document comparison Compare a source document against multiple targets in a single operation. The merged result aggregates changes from every target, which is useful for collating proposal revisions or multiple reviewer iterations. See: [Compare multiple documents]({{< ref "comparison/python-net/developer-guide/comparing-documents/compare-multiple-documents" >}}). ## Accept or reject changes Every detected difference can be accepted or rejected programmatically. The accepted-only result can be saved to a new document, enabling reviewer-style workflows. See: [Accept or reject detected changes]({{< ref "comparison/python-net/developer-guide/comparing-documents/accept-or-reject-detected-changes" >}}). ## Customize the comparison process Tune how the comparison runs: - Sensitivity (per-line, per-word, per-character) — see [Adjusting comparison sensitivity]({{< ref "comparison/python-net/developer-guide/comparing-documents/adjusting-comparison-sensitivity" >}}). - Highlight colours and styles — see [Customize changes styles]({{< ref "comparison/python-net/developer-guide/comparing-documents/customize-changes-styles" >}}). - Show or hide gap lines — see [Show gap lines]({{< ref "comparison/python-net/developer-guide/comparing-documents/show-gap-lines" >}}). - Word track-changes handling — see [Word track changes]({{< ref "comparison/python-net/developer-guide/comparing-documents/word-track-changes" >}}). ## Document information extraction Without performing a full comparison, query basic metadata: file type, size, and page count. Useful for routing decisions and previews. See: [Get document information]({{< ref "comparison/python-net/developer-guide/getting-document-info" >}}). ## Page previews Generate per-page image previews of the source, target, or result document. See: [Generate document pages preview]({{< ref "comparison/python-net/developer-guide/generate-document-pages-preview" >}}). ## Folder comparison Compare entire folders of documents in one pass. See: [Compare folders]({{< ref "comparison/python-net/developer-guide/compare-folders" >}}). ## Summary reports When comparison completes, you can save a summary page listing every detected change. Combine with [Get extended information on the summary page]({{< ref "comparison/python-net/developer-guide/comparing-documents/get-extended-information-on-the-summary-page" >}}) for richer reports. ## Load and save flexibility - Load from local files or streams, including password-protected documents and custom fonts — see [Loading documents]({{< ref "comparison/python-net/developer-guide/loading-documents" >}}). - Save results to file paths or streams; control output format, metadata, and password — see [Saving results]({{< ref "comparison/python-net/developer-guide/saving-results" >}}). --- ## Get Document Information Path: /comparison/python-net/developer-guide/getting-document-info/ [GroupDocs.Comparison for Python via .NET](https://products.groupdocs.com/comparison/python-net) can return the following information about a document without performing a comparison: - `file_type` — the document file type (PDF, Word, Excel, PowerPoint, image, etc.). - `page_count` — number of pages. - `size` — file size in bytes. - `pages_info` — per-page information. ## Example 1: Get document info for a file on local disk {{< tabs "get-document-info-path">}} {{< tab "get_document_info.py" >}} ```python from groupdocs.comparison import Comparer def get_document_info(): with Comparer("./source.docx") as comparer: info = comparer.source.get_document_info() print(f"File type: {info.file_type.file_format}") print(f"Number of pages: {info.page_count}") print(f"Document size: {info.size} bytes") print("\nDocument info extracted successfully.") if __name__ == "__main__": get_document_info() ``` {{< /tab >}} {{< tab "source.docx" >}} {{< tab-text >}} `source.docx` is the document used in this example. Click [here](/comparison/python-net/_sample_files/developer-guide/getting-document-info/source.docx) to download it. {{< /tab-text >}} {{< /tab >}} {{< tab "get-document-info.txt" >}} ```text File type: Microsoft Word Document Number of pages: 1 Document size: 26611 bytes Document info extracted successfully. ``` [Download full output](/comparison/python-net/_output_files/developer-guide/getting-document-info/get_document_info/get-document-info.txt) {{< /tab >}} {{< /tabs >}} ## Example 2: Get document info for a file from a stream {{< tabs "get-document-info-stream">}} {{< tab "get_document_info_from_stream.py" >}} ```python from groupdocs.comparison import Comparer def get_document_info_from_stream(): with open("./source.docx", "rb") as source_stream: with Comparer(source_stream) as comparer: info = comparer.source.get_document_info() print(f"File type: {info.file_type.file_format}") print(f"Number of pages: {info.page_count}") print(f"Document size: {info.size} bytes") if __name__ == "__main__": get_document_info_from_stream() ``` {{< /tab >}} {{< tab "source.docx" >}} {{< tab-text >}} `source.docx` is the document used in this example. Click [here](/comparison/python-net/_sample_files/developer-guide/getting-document-info/source.docx) to download it. {{< /tab-text >}} {{< /tab >}} {{< tab "get-document-info-from-stream.txt" >}} ```text File type: Microsoft Word Document Number of pages: 1 Document size: 26611 bytes ``` [Download full output](/comparison/python-net/_output_files/developer-guide/getting-document-info/get_document_info_from_stream/get-document-info-from-stream.txt) {{< /tab >}} {{< /tabs >}} ## Inspect without comparing — the trio `Comparer.source.get_document_info()` is one of three ways to read information about a document without running a full comparison: | What you need | Use | |---|---| | File type, size, page count of a *specific* document | This page | | The list of *every* supported format at runtime | [Get supported file formats]({{< ref "comparison/python-net/developer-guide/get-supported-file-formats" >}}) | | Visual thumbnails of selected pages | [Generate document pages preview]({{< ref "comparison/python-net/developer-guide/generate-document-pages-preview" >}}) | Pair `get_document_info()` with the format-list to validate inputs early in a pipeline (e.g., reject anything outside an allowlist), and use page previews to give end users a quick visual preview before committing to a full diff. ## Related topics - [Get supported file formats]({{< ref "comparison/python-net/developer-guide/get-supported-file-formats" >}}) — enumerate supported types at runtime. - [Generate document pages preview]({{< ref "comparison/python-net/developer-guide/generate-document-pages-preview" >}}) — render page thumbnails. - [Specify file type for comparison manually]({{< ref "comparison/python-net/developer-guide/comparing-documents/specify-file-type-manually" >}}) — when the inferred type is wrong. --- ## Load File from Local Disk Path: /comparison/python-net/developer-guide/loading-documents/load-file-from-local-disk/ When source and target files are on the local disk, pass their paths directly to `Comparer` and `add()`. Both absolute and relative paths work. ## Example: Load files from local disk {{< tabs "load-from-disk">}} {{< tab "load_file_from_local_disk.py" >}} ```python from groupdocs.comparison import Comparer def load_file_from_local_disk(): with Comparer("./source.docx") as comparer: comparer.add("./target.docx") comparer.compare("./result.docx") print("Documents compared successfully. Check output in result.docx.") if __name__ == "__main__": load_file_from_local_disk() ``` {{< /tab >}} {{< tab "source.docx" >}} {{< tab-text >}} `source.docx` is the source file used in this example. Click [here](/comparison/python-net/_sample_files/developer-guide/loading-documents/load-file-from-local-disk/source.docx) to download it. {{< /tab-text >}} {{< /tab >}} {{< tab "target.docx" >}} {{< tab-text >}} `target.docx` is the target file used in this example. Click [here](/comparison/python-net/_sample_files/developer-guide/loading-documents/load-file-from-local-disk/target.docx) to download it. {{< /tab-text >}} {{< /tab >}} {{< tab "result.docx" >}} ```text Binary file (DOCX, 25 KB) ``` [Download full output](/comparison/python-net/_output_files/developer-guide/loading-documents/load-file-from-local-disk/load_file_from_local_disk/result.docx) {{< /tab >}} {{< /tabs >}} --- ## GroupDocs.Comparison for Python via .NET Overview Path: /comparison/python-net/product-overview/ ## What is GroupDocs.Comparison? GroupDocs.Comparison for Python via .NET is a native Python library that compares **50+ document formats** — DOCX, PDF, XLSX, PPTX, OpenDocument, AutoCAD, Visio, images, HTML, and source code — and reports the differences at paragraph, word, and character level, including style and formatting changes. It runs entirely on-premise, requires no Microsoft Office installation, and ships as a pre-built wheel on Windows, Linux, and macOS. Typical uses include: - **Contract and policy review** — surface inserted, deleted, and modified clauses between two DOCX or PDF revisions and route only the changed regions to reviewers (or to an LLM) instead of re-reading both documents. - **Editorial accept/reject workflows** — classify each detected change, then re-emit the document honouring the decisions via `apply_changes`. - **AI-edit audit** — compare the document an agent produced against the original to verify and explain every change it made. See [Agents and LLM Integration]({{< ref "comparison/python-net/agents-and-llm-integration" >}}) for the full pipeline. - **Version-control review** — diff two exports of a non-text-friendly format (PPTX, XLSX, Visio, DWG) without flattening the binary. - **Multi-source consolidation** — diff one source against many targets in a single pass to spot which downstream copy drifted from the canonical version. ## Key Capabilities | Capability | Description | |---|---| | **50+ comparison formats** | DOCX, PDF, XLSX, PPTX, ODT, HTML, images, AutoCAD, Visio, source code, and more. See [supported formats]({{< ref "comparison/python-net/getting-started/supported-document-formats" >}}). | | **Granular change detection** | [Paragraph, word, and character-level diffs]({{< ref "comparison/python-net/developer-guide/comparing-documents/compare-documents" >}}) — including style, formatting, and structural changes. | | **Inspect detected changes** | [Iterate `ChangeInfo` objects]({{< ref "comparison/python-net/developer-guide/comparing-documents/get-list-of-changes" >}}) — type (INSERTED / DELETED / STYLE_CHANGED), text, author, and style deltas — without writing an output file. | | **Accept / reject workflows** | [Per-change ACCEPT / REJECT decisions]({{< ref "comparison/python-net/developer-guide/comparing-documents/accept-or-reject-detected-changes" >}}) re-emitted via `apply_changes`. | | **Multi-source comparison** | [Diff one source against multiple targets]({{< ref "comparison/python-net/developer-guide/comparing-documents/compare-multiple-documents" >}}) in a single `Comparer`. | | **Folder comparison** | [Compare entire directories]({{< ref "comparison/python-net/developer-guide/compare-folders" >}}) with the folder-compare mode. | | **Change coordinates** | [Get the `Rectangle` (x / y / width / height) of every detected change]({{< ref "comparison/python-net/developer-guide/comparing-documents/get-changes-coordinates" >}}) for overlay rendering. | | **Custom change styling** | [Style inserted / deleted / changed regions]({{< ref "comparison/python-net/developer-guide/comparing-documents/customize-changes-styles" >}}) with `Color`, RGB tuples, hex strings, or named colours. | | **Summary pages** | [Append a summary]({{< ref "comparison/python-net/developer-guide/comparing-documents/get-only-summary-page" >}}) with change statistics, or emit a summary-only result. | | **Password-protected documents** | [Open and re-save protected DOCX / PDF / XLSX]({{< ref "comparison/python-net/developer-guide/loading-documents/load-password-protected-documents" >}}) via `LoadOptions.password` and `SaveOptions.password`. | | **Streams** | Load input from file-like objects (`open(..., "rb")` or `io.BytesIO`) — handy for cloud blobs and HTTP bodies. | | **Document inspection** | [Read format, page count, and size]({{< ref "comparison/python-net/developer-guide/getting-document-info" >}}) without running a comparison. | | **Logging and diagnostics** | [Wire `ConsoleLogger`]({{< ref "comparison/python-net/developer-guide/logging-and-diagnostics" >}}) through `ComparerSettings` for production traces. | | **On-premise** | No cloud calls, no Microsoft Office install, no network traffic. | ## Quick Example {{< tabs "quick-example">}} {{< tab "compare_documents.py" >}} ```python from groupdocs.comparison import Comparer def compare_documents(): """Compare two DOCX revisions and write a tracked-changes result.""" with Comparer("./source.docx") as comparer: comparer.add("./target.docx") comparer.compare("./result.docx") if __name__ == "__main__": compare_documents() ``` {{< /tab >}} {{< tab "With options" >}} ```python from groupdocs.comparison import Comparer from groupdocs.comparison.options import CompareOptions, LoadOptions def compare_with_options(): """Compare two password-protected DOCX files with style detection and a summary page appended to the result.""" load = LoadOptions() load.password = "1234" with Comparer("./protected_source.docx", load_options=load) as comparer: comparer.add("./protected_target.docx", load_options=load) options = CompareOptions() options.detect_style_changes = True options.generate_summary_page = True options.sensitivity_of_comparison = 75 comparer.compare("./result.docx", options) if __name__ == "__main__": compare_with_options() ``` {{< /tab >}} {{< tab "result.docx" >}} {{< tab-text >}} `result.docx` is the comparison output produced by the `compare_documents.py` snippet. [Download the sample result](/comparison/python-net/_output_files/developer-guide/comparing-documents/compare-documents/compare_documents/result.docx). {{< /tab-text >}} {{< /tab >}} {{< /tabs >}} ## Where to next 1. **Install the package** — [Installation]({{< ref "comparison/python-net/getting-started/installation" >}}) walks through PyPI installation for Windows, Linux, and macOS. 2. **Run your first comparison** — [Quick Start Guide]({{< ref "comparison/python-net/getting-started/quick-start-guide" >}}) compares two DOCX files in five minutes. 3. **Explore the examples** — [Running Examples]({{< ref "comparison/python-net/getting-started/how-to-run-examples" >}}) clones the runnable repository and runs every documented scenario locally. 4. **Use it in depth** — the [Developer Guide]({{< ref "comparison/python-net/developer-guide" >}}) covers loading, comparing, accepting/rejecting changes, multi-source, folder compare, summary pages, and logging. 5. **Plug it into AI pipelines** — [Agents and LLM Integration]({{< ref "comparison/python-net/agents-and-llm-integration" >}}) explains the MCP server, `AGENTS.md`, and how to use Comparison as the change-detection step in agent workflows. --- ## Quick Start Guide Path: /comparison/python-net/getting-started/quick-start-guide/ This guide walks you through installing GroupDocs.Comparison for Python via .NET and comparing two documents end to end. By the end you will have a working environment, an output file showing the differences between two sample documents, and the code skeleton to extend for your own use cases. ## Prerequisites - **Python 3.5 or newer** — verify with `python --version`. - A package manager — pip is bundled with Python. - Two sample documents to compare. You can [download `source.docx`](/comparison/python-net/_sample_files/getting-started/quick-start-guide/source.docx) and [`target.docx`](/comparison/python-net/_sample_files/getting-started/quick-start-guide/target.docx) used in this guide, or use your own. On Linux and macOS, GroupDocs.Comparison also requires `libgdiplus` and font support — see the [installation guide]({{< ref "comparison/python-net/getting-started/installation" >}}) for the exact commands. ## Step 1 — Install the package Install GroupDocs.Comparison from PyPI: ```bash pip install groupdocs-comparison-net ``` The wheel is roughly 150 MB and bundles the .NET runtime; no further setup is required on Windows. ## Step 2 — Compare two documents Save the following snippet as `quick_start.py` in the same folder as `source.docx` and `target.docx`, then run it with `python quick_start.py`. {{< tabs "quick-start">}} {{< tab "quick_start.py" >}} ```python from groupdocs.comparison import Comparer def quick_start(): # Initialize Comparer with the source document and add the target. with Comparer("./source.docx") as comparer: comparer.add("./target.docx") # The result file contains the merged comparison highlighting added, # deleted, modified, and style changes. comparer.compare("./result.docx") if __name__ == "__main__": quick_start() ``` {{< /tab >}} {{< tab "source.docx" >}} {{< tab-text >}} `source.docx` is the source file used in this example. Click [here](/comparison/python-net/_sample_files/getting-started/quick-start-guide/source.docx) to download it. {{< /tab-text >}} {{< /tab >}} {{< tab "target.docx" >}} {{< tab-text >}} `target.docx` is the target file used in this example. Click [here](/comparison/python-net/_sample_files/getting-started/quick-start-guide/target.docx) to download it. {{< /tab-text >}} {{< /tab >}} {{< tab "result.docx" >}} ```text Binary file (DOCX, 25 KB) ``` [Download full output](/comparison/python-net/_output_files/getting-started/quick-start-guide/quick_start/result.docx) {{< /tab >}} {{< /tabs >}} Open `result.docx` to see the differences highlighted in colour: insertions in blue, deletions in red, style changes in green. ## Step 3 — Inspect detected changes programmatically Beyond writing a merged result file, you can iterate over the individual changes: {{< tabs "quick-start-changes">}} {{< tab "list_changes.py" >}} ```python from groupdocs.comparison import Comparer def list_changes(): with Comparer("./source.docx") as comparer: comparer.add("./target.docx") comparer.compare() for change in comparer.get_changes(): print(f"Type: {change.type}, Text: {change.text}") if __name__ == "__main__": list_changes() ``` {{< /tab >}} {{< tab "source.docx" >}} {{< tab-text >}} `source.docx` is the source file used in this example. Click [here](/comparison/python-net/_sample_files/getting-started/quick-start-guide/source.docx) to download it. {{< /tab-text >}} {{< /tab >}} {{< tab "target.docx" >}} {{< tab-text >}} `target.docx` is the target file used in this example. Click [here](/comparison/python-net/_sample_files/getting-started/quick-start-guide/target.docx) to download it. {{< /tab-text >}} {{< /tab >}} {{< tab "list-changes.txt" >}} ```text Type: 2, Text: Cool Type: 2, Text: Type: 3, Text: test Type: 2, Text: signatures Type: 2, Text: Our Type: 2, Text: char[ Type: 2, Text: 255] Type: 2, Text: Type: 3, Text: ``` [Download full output](/comparison/python-net/_output_files/getting-started/quick-start-guide/list_changes/list-changes.txt) {{< /tab >}} {{< /tabs >}} ## Evaluation vs licensed mode Without a license, GroupDocs.Comparison processes only the first two pages of any document and stamps trial badges on the output. To unlock the full feature set, apply a license — either via the `GROUPDOCS_LIC_PATH` environment variable (zero-code) or by calling `License().set_license(path)`. Request a free 30-day temporary license at [purchase.groupdocs.com/temporary-license](https://purchase.groupdocs.com/temporary-license). See [Licensing and subscription]({{< ref "comparison/python-net/getting-started/licensing-and-subscription" >}}) for the full set of options, including metered licensing and stream-based license loading. ## Next steps - [Compare documents]({{< ref "comparison/python-net/developer-guide/comparing-documents/compare-documents" >}}) — the full API surface for two-document comparison. - [Accept or reject detected changes]({{< ref "comparison/python-net/developer-guide/comparing-documents/accept-or-reject-detected-changes" >}}) — reviewer-style workflows that pick and choose which changes to apply. - [Customize changes styles]({{< ref "comparison/python-net/developer-guide/comparing-documents/customize-changes-styles" >}}) — change highlight colours, fonts, and decorations. - [Load documents]({{< ref "comparison/python-net/developer-guide/loading-documents" >}}) — paths, streams, password-protected files, custom fonts. - [Save comparison results]({{< ref "comparison/python-net/developer-guide/saving-results" >}}) — output format, metadata, output password. - [AI agents and LLM integration]({{< ref "comparison/python-net/agents-and-llm-integration" >}}) — work with the API from Claude Code, Cursor, and other AI assistants. --- ## Set Document Metadata on Save Path: /comparison/python-net/developer-guide/saving-results/set-document-metadata-on-save/ The comparison result document can carry metadata (author, organization, creation date, etc.). Use [`SaveOptions.clone_metadata_type`](https://reference.groupdocs.com/comparison/python-net/groupdocs.comparison.options.save/saveoptions/) to choose where it comes from: - `MetadataType.SOURCE` — clone metadata from the source document. - `MetadataType.TARGET` — clone metadata from the target document. - `MetadataType.FILE_AUTHOR` — set user-defined metadata via `SaveOptions.file_author_metadata`. ## Example 1: Use metadata from the source file {{< tabs "metadata-source">}} {{< tab "set_metadata_from_source.py" >}} ```python from groupdocs.comparison import Comparer from groupdocs.comparison.options import SaveOptions, MetadataType def set_metadata_from_source(): with Comparer("./source.docx") as comparer: comparer.add("./target.docx") save_options = SaveOptions() save_options.clone_metadata_type = MetadataType.SOURCE comparer.compare("./result.docx", save_options) if __name__ == "__main__": set_metadata_from_source() ``` {{< /tab >}} {{< tab "source.docx" >}} {{< tab-text >}} `source.docx` is the source file used in this example. Click [here](/comparison/python-net/_sample_files/developer-guide/saving-results/set-document-metadata-on-save/source.docx) to download it. {{< /tab-text >}} {{< /tab >}} {{< tab "target.docx" >}} {{< tab-text >}} `target.docx` is the target file used in this example. Click [here](/comparison/python-net/_sample_files/developer-guide/saving-results/set-document-metadata-on-save/target.docx) to download it. {{< /tab-text >}} {{< /tab >}} {{< tab "result.docx" >}} ```text Binary file (DOCX, 25 KB) ``` [Download full output](/comparison/python-net/_output_files/developer-guide/saving-results/set-document-metadata-on-save/set_metadata_from_source/result.docx) {{< /tab >}} {{< /tabs >}} ## Example 2: Use metadata from the target file {{< tabs "metadata-target">}} {{< tab "set_metadata_from_target.py" >}} ```python from groupdocs.comparison import Comparer from groupdocs.comparison.options import SaveOptions, MetadataType def set_metadata_from_target(): with Comparer("./source.docx") as comparer: comparer.add("./target.docx") save_options = SaveOptions() save_options.clone_metadata_type = MetadataType.TARGET comparer.compare("./result.docx", save_options) if __name__ == "__main__": set_metadata_from_target() ``` {{< /tab >}} {{< tab "source.docx" >}} {{< tab-text >}} `source.docx` is the source file used in this example. Click [here](/comparison/python-net/_sample_files/developer-guide/saving-results/set-document-metadata-on-save/source.docx) to download it. {{< /tab-text >}} {{< /tab >}} {{< tab "result.docx" >}} ```text Binary file (DOCX, 25 KB) ``` [Download full output](/comparison/python-net/_output_files/developer-guide/saving-results/set-document-metadata-on-save/set_metadata_from_target/result.docx) {{< /tab >}} {{< /tabs >}} ## Example 3: Set user-defined metadata {{< tabs "metadata-user-defined">}} {{< tab "set_user_defined_metadata.py" >}} ```python from groupdocs.comparison import Comparer from groupdocs.comparison.options import SaveOptions, MetadataType, FileAuthorMetadata def set_user_defined_metadata(): with Comparer("./source.docx") as comparer: comparer.add("./target.docx") author_metadata = FileAuthorMetadata() author_metadata.author = "Tom" author_metadata.company = "GroupDocs" author_metadata.last_save_by = "Jack" save_options = SaveOptions() save_options.clone_metadata_type = MetadataType.FILE_AUTHOR save_options.file_author_metadata = author_metadata comparer.compare("./result.docx", save_options) if __name__ == "__main__": set_user_defined_metadata() ``` {{< /tab >}} {{< tab "source.docx" >}} {{< tab-text >}} `source.docx` is the source file used in this example. Click [here](/comparison/python-net/_sample_files/developer-guide/saving-results/set-document-metadata-on-save/source.docx) to download it. {{< /tab-text >}} {{< /tab >}} {{< tab "result.docx" >}} ```text Binary file (DOCX, 25 KB) ``` [Download full output](/comparison/python-net/_output_files/developer-guide/saving-results/set-document-metadata-on-save/set_user_defined_metadata/result.docx) {{< /tab >}} {{< /tabs >}} --- ## Compare Word Documents Path: /comparison/python-net/developer-guide/comparing-documents/compare-word-documents/ [GroupDocs.Comparison for Python via .NET](https://products.groupdocs.com/comparison/python-net) compares Word documents and highlights differences in text, formatting, styles, and structure. Typical use cases include legal contracts, business reports, and any collaborative editing workflow where accurate change tracking matters. The API: - Compares **DOC and DOCX** files (and Word-compatible formats such as RTF, ODT, DOT, DOTX). - Highlights insertions, deletions, and formatting changes. - Exports the result as a Word document or any other supported format. ## Steps to compare Word documents 1. Create a `Comparer` instance and load the source Word document. 2. Add one or more target Word documents via `add()`. 3. Call `compare()` to generate the result file. ## Example: Compare Word documents {{< tabs "compare-word">}} {{< tab "compare_word_documents.py" >}} ```python from groupdocs.comparison import Comparer def compare_word_documents(): with Comparer("./source.docx") as comparer: comparer.add("./target.docx") comparer.compare("./result.docx") if __name__ == "__main__": compare_word_documents() ``` {{< /tab >}} {{< tab "source.docx" >}} {{< tab-text >}} `source.docx` is the source file used in this example. Click [here](/comparison/python-net/_sample_files/developer-guide/comparing-documents/compare-word-documents/source.docx) to download it. {{< /tab-text >}} {{< /tab >}} {{< tab "target.docx" >}} {{< tab-text >}} `target.docx` is the target file used in this example. Click [here](/comparison/python-net/_sample_files/developer-guide/comparing-documents/compare-word-documents/target.docx) to download it. {{< /tab-text >}} {{< /tab >}} {{< tab "result.docx" >}} ```text Binary file (DOCX, 25 KB) ``` [Download full output](/comparison/python-net/_output_files/developer-guide/comparing-documents/compare-word-documents/compare_word_documents/result.docx) {{< /tab >}} {{< /tabs >}} ## Word-specific options The base flow above works for any Word format, but several options on `CompareOptions` are specifically useful when comparing Word documents: | Option | Purpose | Topic | |---|---|---| | `word_track_changes` | Include or ignore previously-tracked revisions | [Word track changes]({{< ref "comparison/python-net/developer-guide/comparing-documents/word-track-changes" >}}) | | `compare_bookmarks` | Detect changes inside bookmarked ranges | [Compare bookmarks in Word documents]({{< ref "comparison/python-net/developer-guide/comparing-documents/compare-bookmarks-in-word" >}}) | | `revision_author_name` | Attribute changes in the result to a specific author | [Setting author of changes]({{< ref "comparison/python-net/developer-guide/comparing-documents/setting-author-of-changes" >}}) | | `show_revisions` | Show or hide inline revision markers in the result | [Show revisions]({{< ref "comparison/python-net/developer-guide/comparing-documents/show-revisions" >}}) | | `compare_variable_property` / `compare_document_property` | Compare document metadata | [Compare variables and document properties]({{< ref "comparison/python-net/developer-guide/comparing-documents/compare-of-variables-and-document-properties" >}}) | ## Related topics - [Accept or reject detected changes]({{< ref "comparison/python-net/developer-guide/comparing-documents/accept-or-reject-detected-changes" >}}) — apply only the changes you want. - [Accept or reject revisions]({{< ref "comparison/python-net/developer-guide/comparing-documents/accept-or-reject-revisions" >}}) — process Word Track Changes revisions independently of comparison. - [Customize changes styles]({{< ref "comparison/python-net/developer-guide/comparing-documents/customize-changes-styles" >}}) — change colours and decorations for inserted/deleted/changed items. --- ## Load File from Stream Path: /comparison/python-net/developer-guide/loading-documents/load-file-from-stream/ To avoid persisting intermediate files, work with file streams directly. Pass an open binary stream to `Comparer` and `add()`. 1. Open the source and target files as binary streams. 2. Pass the source stream to the `Comparer` constructor. 3. Pass the target stream to `add()`. 4. Call `compare()` with the result path or output stream. ## Example: Load files from streams {{< tabs "load-from-stream">}} {{< tab "load_file_from_stream.py" >}} ```python from groupdocs.comparison import Comparer def load_file_from_stream(): with open("./source.docx", "rb") as source_stream, \ open("./target.docx", "rb") as target_stream: with Comparer(source_stream) as comparer: comparer.add(target_stream) comparer.compare("./result.docx") print("Documents compared successfully. Check output in result.docx.") if __name__ == "__main__": load_file_from_stream() ``` {{< /tab >}} {{< tab "source.docx" >}} {{< tab-text >}} `source.docx` is the source file used in this example. Click [here](/comparison/python-net/_sample_files/developer-guide/loading-documents/load-file-from-stream/source.docx) to download it. {{< /tab-text >}} {{< /tab >}} {{< tab "target.docx" >}} {{< tab-text >}} `target.docx` is the target file used in this example. Click [here](/comparison/python-net/_sample_files/developer-guide/loading-documents/load-file-from-stream/target.docx) to download it. {{< /tab-text >}} {{< /tab >}} {{< tab "result.docx" >}} ```text Binary file (DOCX, 25 KB) ``` [Download full output](/comparison/python-net/_output_files/developer-guide/loading-documents/load-file-from-stream/load_file_from_stream/result.docx) {{< /tab >}} {{< /tabs >}} --- ## Set a Password for the Resultant Document Path: /comparison/python-net/developer-guide/saving-results/set-password-for-resultant-document/ [GroupDocs.Comparison for Python via .NET](https://products.groupdocs.com/comparison/python-net) can apply a password to the comparison result. Combine `CompareOptions.password_save_option = PasswordSaveOption.USER` with `SaveOptions.password = ""`. ## Example: Password-protect the result document {{< tabs "set-output-password">}} {{< tab "set_password_for_resultant_document.py" >}} ```python from groupdocs.comparison import Comparer from groupdocs.comparison.options import CompareOptions, SaveOptions, PasswordSaveOption def set_password_for_resultant_document(): with Comparer("./source.docx") as comparer: comparer.add("./target.docx") compare_options = CompareOptions() compare_options.password_save_option = PasswordSaveOption.USER save_options = SaveOptions() save_options.password = "3333" comparer.compare("./result.docx", save_options, compare_options) if __name__ == "__main__": set_password_for_resultant_document() ``` {{< /tab >}} {{< tab "source.docx" >}} {{< tab-text >}} `source.docx` is the source file used in this example. Click [here](/comparison/python-net/_sample_files/developer-guide/saving-results/set-password-for-resultant-document/source.docx) to download it. {{< /tab-text >}} {{< /tab >}} {{< tab "target.docx" >}} {{< tab-text >}} `target.docx` is the target file used in this example. Click [here](/comparison/python-net/_sample_files/developer-guide/saving-results/set-password-for-resultant-document/target.docx) to download it. {{< /tab-text >}} {{< /tab >}} {{< tab "result.docx" >}} ```text Binary file (DOCX, 25 KB) ``` [Download full output](/comparison/python-net/_output_files/developer-guide/saving-results/set-password-for-resultant-document/set_password_for_resultant_document/result.docx) {{< /tab >}} {{< /tabs >}} Opening `result.docx` will require the password `3333`. --- ## Supported Document Formats Path: /comparison/python-net/getting-started/supported-document-formats/ This topic lists file formats supported by [GroupDocs.Comparison](https://products.groupdocs.com/comparison/python-net). You can use the input below to filter supported formats by extension. {{< table-filter placeholder="Start typing to find file format" forumUrl="https://forum.groupdocs.com/c/comparison/12">}} ## CAD and 3D file formats | Format | Description | Automatic format detection | | --- | --- | :---: | | [DWG](https://docs.fileformat.com/cad/dwg/) | AutoCAD Drawing | ✅ | | [DXF](https://docs.fileformat.com/cad/dxf/) | Drawing Exchange Format | ✅ | ## EBook file formats | Format | Description | Automatic format detection | | --- | --- | :---: | | [MOBI](https://docs.fileformat.com/ebook/mobi/) | Mobipocket EBook | ✅ | ## Email file formats | Format | Description | Automatic format detection | | --- | --- | :---: | | [EML](https://docs.fileformat.com/email/eml/) | Email Message | ✅ | | [EMLX](https://docs.fileformat.com/email/emlx/) | Apple Mail Message | ✅ | | [MSG](https://docs.fileformat.com/email/msg/) | Outlook Message Item File | ✅ | ## Image file formats | Format | Description | Automatic format detection | | --- | --- | :---: | | [BMP](https://docs.fileformat.com/image/bmp/) | Bitmap Image | ✅ | | [DCM](https://docs.fileformat.com/image/dcm/) | DICOM (Digital Imaging and Communications in Medicine) Image | ✅ | | [DJVU](https://docs.fileformat.com/image/djvu/) | DjVu Image | ✅ | | [GIF](https://docs.fileformat.com/image/gif/) | Graphical Interchange Format | ✅ | | [JPEG / JPG](https://docs.fileformat.com/image/jpeg) | JPEG Image | ✅ | | [PNG](https://docs.fileformat.com/image/png/) | Portable Network Graphics | ✅ | | [SVG](https://docs.fileformat.com/page-description-language/svg/) | Scalable Vector Graphics File | ✅ | ## Note-taking file formats | Format | Description | Automatic format detection | | --- | --- | :---: | | [ONE](https://docs.fileformat.com/note-taking/one/) | Microsoft OneNote Document | ✅ | ## Page Layout file formats | Format | Description | Automatic format detection | | --- | --- | :---: | | [PDF](https://docs.fileformat.com/pdf/) | Adobe Portable Document Format | ✅ | ## Presentation file formats | Format | Description | Automatic format detection | | --- | --- | :---: | | [ODP](https://docs.fileformat.com/presentation/odp/) | OpenDocument Presentation | ✅ | | [OTP](https://docs.fileformat.com/presentation/otp/) | OpenDocument Presentation Template | ✅ | | [POT](https://docs.fileformat.com/presentation/pot/) | Microsoft PowerPoint 97-2003 Template | ✅ | | [POTX](https://docs.fileformat.com/presentation/potx/) | Microsoft PowerPoint Template | ✅ | | [PPS](https://docs.fileformat.com/presentation/pps/) | Microsoft PowerPoint 97-2003 Slide Show | ✅ | | [PPSX](https://docs.fileformat.com/presentation/ppsx/) | Microsoft PowerPoint Slide Show | ✅ | | [PPT](https://docs.fileformat.com/presentation/ppt/) | Microsoft PowerPoint 97-2003 Presentation | ✅ | | [PPTX](https://docs.fileformat.com/presentation/pptx/) | Microsoft PowerPoint Presentation | ✅ | ## Spreadsheet file formats | Format | Description | Automatic format detection | | --- | --- | :---: | | [CSV](https://docs.fileformat.com/spreadsheet/csv/) | Comma Separated Values File | ✅ | | [ODS](https://docs.fileformat.com/spreadsheet/ods/) | OpenDocument Spreadsheet | ✅ | | [XLS](https://docs.fileformat.com/spreadsheet/xls/) | Microsoft Excel 97-2003 Workbook | ✅ | | [XLSB](https://docs.fileformat.com/spreadsheet/xlsb/) | Microsoft Excel Binary Workbook | ✅ | | [XLSM](https://docs.fileformat.com/spreadsheet/xlsm/) | Microsoft Excel Macro-Enabled Workbook | ✅ | | [XLSX](https://docs.fileformat.com/spreadsheet/xlsx/) | Microsoft Excel Workbook | ✅ | | [XLT](https://docs.fileformat.com/spreadsheet/xlt/) | Microsoft Excel 97-2003 Template | ✅ | | [XLTX](https://docs.fileformat.com/spreadsheet/xltx/) | Microsoft Excel Template | ✅ | | [XLTM](https://docs.fileformat.com/spreadsheet/xltm/) | Microsoft Excel Macro-Enabled Template | ✅ | | [XML](https://docs.fileformat.com/spreadsheet/) | XML Spreadsheet 2003 | ✅ | ## Text and programming file formats | Format | Description | Automatic format detection | | --- | --- | :---: | | [AS / AS3](https://docs.fileformat.com/programming/as/) | ActionScript File | ✅ | | [ASM](https://docs.fileformat.com/programming/asm/) | Assembly Language Source Code File | ✅ | | [BAT](https://docs.fileformat.com/executable/bat/) | DOS Batch File | ✅ | | [C](https://docs.fileformat.com/programming/c/) | C/C++ Source Code File | ✅ | | [CC](https://docs.fileformat.com/programming/c/) | C++ Source Code File | ✅ | | [CMAKE](https://docs.fileformat.com/programming/cmake/) | CMake File | ✅ | | [CPP](https://docs.fileformat.com/programming/cpp/) | C++ Source Code File | ✅ | | [CS](https://docs.fileformat.com/specification/programming/cs/) | C# Source Code File | ✅ | | [CSS](https://docs.fileformat.com/web/css/) | Cascading Style Sheet | ✅ | | [CXX](https://docs.fileformat.com/programming/cxx/) | C++ Source Code File | ✅ | | [DIFF](https://docs.fileformat.com/programming/diff/) | Patch File | ✅ | | [ERB](https://docs.fileformat.com/programming/erb/) | Ruby ERB Script | ✅ | | [GROOVY](https://docs.fileformat.com/programming/groovy/) | Groovy Source Code File | ✅ | | [H](https://docs.fileformat.com/programming/h/) | C/C++/Objective-C Header File | ✅ | | [HAML](https://docs.fileformat.com/programming/haml/) | Haml Source Code File | ✅ | | [HH](https://docs.fileformat.com/programming/hh/) | C++ Header File | ✅ | | [JAVA](https://docs.fileformat.com/programming/java/) | Java Source Code File | ✅ | | [JS](https://docs.fileformat.com/web/js/) | JavaScript File | ✅ | | [JSON](https://docs.fileformat.com/web/json/) | JavaScript Object Notation File | ✅ | | [LESS](https://docs.fileformat.com/web/less/) | LESS Style Sheet | ✅ | | [LOG](https://docs.fileformat.com/database/log/) | Log File | ✅ | | [M](https://docs.fileformat.com/programming/m/) | Objective-C Implementation File | ✅ | | [MAKE](https://docs.fileformat.com/programming/make/) | Xcode Makefile Script | ✅ | | [MD](https://docs.fileformat.com/word-processing/md/) | Markdown Documentation File | ✅ | | [ML](https://docs.fileformat.com/programming/ml/) | ML Source Code File | ✅ | | [MM](https://docs.fileformat.com/programming/mm/) | Objective-C++ Source File | ✅ | | [PHP](https://docs.fileformat.com/programming/php/) | PHP Source Code File | ✅ | | [PL](https://docs.fileformat.com/programming/pl/) | Perl Script | ✅ | | [PROPERTIES](https://en.wikipedia.org/wiki/.properties) | Java Properties File | ✅ | | [PY](https://docs.fileformat.com/programming/py/) | Python Script | ✅ | | [RB](https://docs.fileformat.com/ebook/rb/) | Ruby Source Code | ✅ | | [RST](https://docs.fileformat.com/programming/rst/) | reStructuredText File | ✅ | | [SASS](https://docs.fileformat.com/web/sass/) | Syntactically Awesome StyleSheets File | ✅ | | [SCALA](https://docs.fileformat.com/programming/scala/) | Scala Source Code File | ✅ | | [SH](https://docs.fileformat.com/programming/sh/) | Bash Shell Script | ✅ | | [SQL](https://docs.fileformat.com/database/sql/) | Structured Query Language Data File | ✅ | | [TXT](https://docs.fileformat.com/word-processing/txt) | Plain Text File | ✅ | | [VIM](https://docs.fileformat.com/misc/vim/) | Vim Settings File | ✅ | | [XML](https://docs.fileformat.com/web/xml/) | XML File | ✅ | | [YAML](https://docs.fileformat.com/programming/yaml/) | YAML Document | ✅ | ## Visio file formats | Format | Description | Automatic format detection | | --- | --- | :---: | | [VDX](https://docs.fileformat.com/image/vdx/) | Visio Drawing XML File | ✅ | | [VSD](https://docs.fileformat.com/image/vsd/) | Visio 2003-2010 Drawing | ✅ | | [VSDX](https://docs.fileformat.com/image/vsdx/) | Visio Drawing | ✅ | | [VSS](https://docs.fileformat.com/image/vss/) | Visio 2003-2010 Stencil | ✅ | | [VST](https://docs.fileformat.com/image/vst/) | Visio 2003-2010 Template | ✅ | ## Web file formats | Format | Description | Automatic format detection | | --- | --- | :---: | | [HTML](https://docs.fileformat.com/web/html/) | Hypertext Markup Language Format | ✅ | | [MHT](https://docs.fileformat.com/web/mht/) | MHTML Web Archive | ✅ | | [MHTML](https://docs.fileformat.com/web/mhtml/) | MIME HTML Format | ✅ | ## Word processing file formats | Format | Description | Automatic format detection | | --- | --- | :---: | | [DOC](https://docs.fileformat.com/word-processing/doc/) | Microsoft Word 97-2003 Document | ✅ | | [DOCM](https://docs.fileformat.com/word-processing/docm/) | Microsoft Word Macro-Enabled Document | ✅ | | [DOCX](https://docs.fileformat.com/word-processing/docx/) | Microsoft Word Document | ✅ | | [DOT](https://docs.fileformat.com/word-processing/dot/) | Microsoft Word 97-2003 Template | ✅ | | [DOTM](https://docs.fileformat.com/word-processing/dotm/) | Microsoft Word Macro-Enabled Template | ✅ | | [DOTX](https://docs.fileformat.com/word-processing/dotx/) | Microsoft Word Template | ✅ | | [ODT](https://docs.fileformat.com/word-processing/odt/) | OpenDocument Text | ✅ | | [OTT](https://docs.fileformat.com/word-processing/ott/) | OpenDocument Text Template | ✅ | | [RTF](https://docs.fileformat.com/word-processing/rtf/) | Rich Text Document | ✅ | --- ## Compare PDF Documents Path: /comparison/python-net/developer-guide/comparing-documents/compare-pdf-documents/ [GroupDocs.Comparison for Python via .NET](https://products.groupdocs.com/comparison/python-net) compares PDF documents and identifies changes in text, formatting, annotations, and structure. Typical use cases include contract review, legal-document comparison, and any workflow where precise difference detection is critical. The API: - Compares two or more **PDF files**. - Highlights insertions, deletions, and formatting changes. - Saves the comparison result to a new PDF or any other supported format. ## Steps to compare PDF documents 1. Create a `Comparer` instance and load the source PDF file. 2. Add one or more target PDF files via `add()`. 3. Call `compare()` with the result file path. ## Example: Compare PDF documents {{< tabs "compare-pdf">}} {{< tab "compare_pdf_documents.py" >}} ```python from groupdocs.comparison import Comparer def compare_pdf_documents(): with Comparer("./source.pdf") as comparer: comparer.add("./target.pdf") comparer.compare("./result.pdf") if __name__ == "__main__": compare_pdf_documents() ``` {{< /tab >}} {{< tab "source.pdf" >}} {{< tab-text >}} `source.pdf` is the source file used in this example. Click [here](/comparison/python-net/_sample_files/developer-guide/comparing-documents/compare-pdf-documents/source.pdf) to download it. {{< /tab-text >}} {{< /tab >}} {{< tab "target.pdf" >}} {{< tab-text >}} `target.pdf` is the target file used in this example. Click [here](/comparison/python-net/_sample_files/developer-guide/comparing-documents/compare-pdf-documents/target.pdf) to download it. {{< /tab-text >}} {{< /tab >}} {{< tab "result.pdf" >}} ```text Binary file (PDF, 279 KB) ``` [Download full output](/comparison/python-net/_output_files/developer-guide/comparing-documents/compare-pdf-documents/compare_pdf_documents/result.pdf) {{< /tab >}} {{< /tabs >}} ## PDF-specific notes - **Text vs. images.** By default, PDF comparison detects both text and embedded image changes. For text-only review, disable image comparison — see [Disable image comparison in PDF documents]({{< ref "comparison/python-net/developer-guide/comparing-documents/disable-image-comparison-in-pdf-documents" >}}). Text-only mode is faster and produces less visual noise when the PDFs differ only in scanned figures or watermarks. - **Annotations and form fields.** GroupDocs.Comparison detects changes in PDF annotation text and form-field values alongside body text. - **Page-level coordinates.** Set `calculate_coordinates = True` on `CompareOptions` to receive pixel-accurate change locations on each page — useful for overlay UIs. See [Get changes coordinates]({{< ref "comparison/python-net/developer-guide/comparing-documents/get-changes-coordinates" >}}). - **Password-protected PDFs.** Pass a `LoadOptions` with `password` set — see [Load password-protected documents]({{< ref "comparison/python-net/developer-guide/loading-documents/load-password-protected-documents" >}}). ## Related topics - [Disable image comparison in PDF documents]({{< ref "comparison/python-net/developer-guide/comparing-documents/disable-image-comparison-in-pdf-documents" >}}) — skip image comparison for faster PDF diffs. - [Get changes coordinates]({{< ref "comparison/python-net/developer-guide/comparing-documents/get-changes-coordinates" >}}) — pixel coordinates for each detected change. - [Customize changes styles]({{< ref "comparison/python-net/developer-guide/comparing-documents/customize-changes-styles" >}}) — change highlight colours. - [Save comparison result in a different format]({{< ref "comparison/python-net/developer-guide/saving-results/save-comparison-result-in-different-format" >}}) — export a PDF diff to DOCX or HTML for review tools that don't render PDF inline. --- ## Load Password-Protected Documents Path: /comparison/python-net/developer-guide/loading-documents/load-password-protected-documents/ [GroupDocs.Comparison for Python via .NET](https://products.groupdocs.com/comparison/python-net) can compare password-protected documents. Supply the source password through a [`LoadOptions`](https://reference.groupdocs.com/comparison/python-net/groupdocs.comparison.options/loadoptions) instance when constructing the `Comparer`, and the target password through a separate `LoadOptions` when calling `add()`. ## Example: Compare a password-protected source and target {{< tabs "load-password-protected">}} {{< tab "load_password_protected_documents.py" >}} ```python from groupdocs.comparison import Comparer from groupdocs.comparison.options import LoadOptions def load_password_protected_documents(): source_load = LoadOptions() source_load.password = "1234" target_load = LoadOptions() target_load.password = "5678" with Comparer("./source_protected.docx", source_load) as comparer: comparer.add("./target_protected.docx", target_load) comparer.compare("./result.docx") if __name__ == "__main__": load_password_protected_documents() ``` {{< /tab >}} {{< tab "source_protected.docx" >}} {{< tab-text >}} `source_protected.docx` is a password-protected source file. Click [here](/comparison/python-net/_sample_files/developer-guide/loading-documents/load-password-protected-documents/source_protected.docx) to download it. {{< /tab-text >}} {{< /tab >}} {{< tab "target_protected.docx" >}} {{< tab-text >}} `target_protected.docx` is a password-protected target file. Click [here](/comparison/python-net/_sample_files/developer-guide/loading-documents/load-password-protected-documents/target_protected.docx) to download it. {{< /tab-text >}} {{< /tab >}} {{< tab "result.docx" >}} ```text Binary file (DOCX, 24 KB) ``` [Download full output](/comparison/python-net/_output_files/developer-guide/loading-documents/load-password-protected-documents/load_password_protected_documents/result.docx) {{< /tab >}} {{< /tabs >}} ## Related topics - [Compare multiple password-protected documents]({{< ref "comparison/python-net/developer-guide/comparing-documents/compare-multiple-documents" >}}) — extend the same pattern to several targets. --- ## System Requirements Path: /comparison/python-net/getting-started/system-requirements/ GroupDocs.Comparison for Python via .NET is a self-contained Python wheel; it does not require a separate .NET installation. The .NET runtime is bundled. ## Supported operating systems GroupDocs.Comparison runs on 64-bit Windows, Linux, and macOS. Per-platform wheels are published. ### Windows - Windows 10 (x64) - Windows 11 (x64) - Windows Server 2016, 2019, 2022, 2025 ### Linux - Ubuntu 20.04+, Debian 11+, Fedora 36+, CentOS Stream 9+ — any glibc-based distribution that meets the manylinux baseline. - Native dependencies: `libgdiplus`, `libfontconfig1`, `libicu-dev`, `ttf-mscorefonts-installer` — see [Installation]({{< ref "comparison/python-net/getting-started/installation" >}}). ### macOS - macOS 12 Monterey or later, on Intel x64 or Apple Silicon (arm64). - Native dependencies: `mono-libgdiplus` via Homebrew. ## Supported Python versions GroupDocs.Comparison for Python via .NET supports CPython 3.5 through 3.14. The package is published as platform-specific wheels for each supported Python version. ```bash python --version # Should print 3.5.x or higher ``` ## Hardware requirements - **CPU:** any 64-bit x86 (x64) or ARM (arm64) processor. - **RAM:** at least 1 GB free. Large documents and high-DPI conversions benefit from more. - **Disk:** the wheel itself is ~150 MB. Allow ample temporary space for the documents being compared. ## Development environments Any Python IDE or text editor works — VS Code, PyCharm, Cursor, Sublime Text, vim, etc. AI assistants such as Claude Code, Cursor, and GitHub Copilot have first-class support via the bundled `AGENTS.md` and the [MCP server]({{< ref "comparison/python-net/agents-and-llm-integration" >}}). --- ## Compare Multiple Documents Path: /comparison/python-net/developer-guide/comparing-documents/compare-multiple-documents/ {{< alert style="info" >}} Multi-target comparison is supported for Microsoft Word documents, Microsoft PowerPoint presentations, and OpenDocument presentations. {{< /alert >}} [GroupDocs.Comparison](https://products.groupdocs.com/comparison/python-net) can compare a source document against more than two targets in a single operation. Call `add()` for every target before calling `compare()`. ## Steps to compare multiple documents 1. Instantiate a [`Comparer`](https://reference.groupdocs.com/comparison/python-net/groupdocs.comparison/comparer) with the source document path or stream. 2. Call [`add()`](https://reference.groupdocs.com/comparison/python-net/groupdocs.comparison/comparer/#add) for each target document. Repeat for every target. 3. Call [`compare()`](https://reference.groupdocs.com/comparison/python-net/groupdocs.comparison/comparer/#compare) and specify the result file path or output stream. ## Example 1: Compare several documents from file paths {{< tabs "compare-multiple-path">}} {{< tab "compare_multiple_documents.py" >}} ```python from groupdocs.comparison import Comparer def compare_multiple_documents(): with Comparer("./source.docx") as comparer: comparer.add("./target1.docx") comparer.add("./target2.docx") comparer.add("./target3.docx") comparer.compare("./result.docx") print("Documents compared successfully. Result saved to result.docx.") if __name__ == "__main__": compare_multiple_documents() ``` {{< /tab >}} {{< tab "source.docx" >}} {{< tab-text >}} `source.docx` is the source file used in this example. Click [here](/comparison/python-net/_sample_files/developer-guide/comparing-documents/compare-multiple-documents/source.docx) to download it. {{< /tab-text >}} {{< /tab >}} {{< tab "target1.docx" >}} {{< tab-text >}} `target1.docx` is a target file used in this example. Click [here](/comparison/python-net/_sample_files/developer-guide/comparing-documents/compare-multiple-documents/target1.docx) to download it. {{< /tab-text >}} {{< /tab >}} {{< tab "target2.docx" >}} {{< tab-text >}} `target2.docx` is a target file used in this example. Click [here](/comparison/python-net/_sample_files/developer-guide/comparing-documents/compare-multiple-documents/target2.docx) to download it. {{< /tab-text >}} {{< /tab >}} {{< tab "target3.docx" >}} {{< tab-text >}} `target3.docx` is a target file used in this example. Click [here](/comparison/python-net/_sample_files/developer-guide/comparing-documents/compare-multiple-documents/target3.docx) to download it. {{< /tab-text >}} {{< /tab >}} {{< tab "result.docx" >}} ```text Binary file (DOCX, 25 KB) ``` [Download full output](/comparison/python-net/_output_files/developer-guide/comparing-documents/compare-multiple-documents/compare_multiple_documents/result.docx) {{< /tab >}} {{< /tabs >}} The result is as follows: ![](/comparison/python-net/images/compare-multiple-word.png) ## Example 2: Compare several documents from streams For workflows that don't use the local file system, use streams for both inputs and the result: {{< tabs "compare-multiple-stream">}} {{< tab "compare_multiple_documents_stream.py" >}} ```python from groupdocs.comparison import Comparer def compare_multiple_documents_stream(): with open("./source.docx", "rb") as src, \ open("./target1.docx", "rb") as t1, \ open("./target2.docx", "rb") as t2, \ open("./target3.docx", "rb") as t3: with Comparer(src) as comparer: comparer.add(t1) comparer.add(t2) comparer.add(t3) with open("./result.docx", "wb") as out_stream: comparer.compare(out_stream) if __name__ == "__main__": compare_multiple_documents_stream() ``` {{< /tab >}} {{< tab "source.docx" >}} {{< tab-text >}} `source.docx` is the source file used in this example. Click [here](/comparison/python-net/_sample_files/developer-guide/comparing-documents/compare-multiple-documents/source.docx) to download it. {{< /tab-text >}} {{< /tab >}} {{< tab "target1.docx" >}} {{< tab-text >}} `target1.docx` is a target file used in this example. Click [here](/comparison/python-net/_sample_files/developer-guide/comparing-documents/compare-multiple-documents/target1.docx) to download it. {{< /tab-text >}} {{< /tab >}} {{< tab "result.docx" >}} ```text Binary file (DOCX, 25 KB) ``` [Download full output](/comparison/python-net/_output_files/developer-guide/comparing-documents/compare-multiple-documents/compare_multiple_documents_stream/result.docx) {{< /tab >}} {{< /tabs >}} ## Example 3: Compare multiple documents with specific compare settings Pass a [`CompareOptions`](https://reference.groupdocs.com/comparison/python-net/groupdocs.comparison.options/compareoptions) instance to customize how the comparison is rendered — for example, to highlight inserted items in a specific colour. {{< tabs "compare-multiple-settings">}} {{< tab "compare_multiple_documents_settings.py" >}} ```python from groupdocs.comparison import Comparer, Color from groupdocs.comparison.options import CompareOptions, StyleSettings def compare_multiple_documents_settings(): with Comparer("./source.docx") as comparer: comparer.add("./target1.docx") comparer.add("./target2.docx") comparer.add("./target3.docx") options = CompareOptions() options.inserted_item_style = StyleSettings() options.inserted_item_style.font_color = Color.from_name("yellow") comparer.compare("./result.docx", options) if __name__ == "__main__": compare_multiple_documents_settings() ``` {{< /tab >}} {{< tab "source.docx" >}} {{< tab-text >}} `source.docx` is the source file used in this example. Click [here](/comparison/python-net/_sample_files/developer-guide/comparing-documents/compare-multiple-documents/source.docx) to download it. {{< /tab-text >}} {{< /tab >}} {{< tab "target1.docx" >}} {{< tab-text >}} `target1.docx` is a target file used in this example. Click [here](/comparison/python-net/_sample_files/developer-guide/comparing-documents/compare-multiple-documents/target1.docx) to download it. {{< /tab-text >}} {{< /tab >}} {{< tab "result.docx" >}} ```text Binary file (DOCX, 25 KB) ``` [Download full output](/comparison/python-net/_output_files/developer-guide/comparing-documents/compare-multiple-documents/compare_multiple_documents_settings/result.docx) {{< /tab >}} {{< /tabs >}} ## Example 4: Compare multiple password-protected documents When the source or target documents are password-protected, supply the password through a [`LoadOptions`](https://reference.groupdocs.com/comparison/python-net/groupdocs.comparison.options/loadoptions) object when constructing the `Comparer` and when calling `add()`. {{< tabs "compare-multiple-protected">}} {{< tab "compare_multiple_documents_protected.py" >}} ```python from groupdocs.comparison import Comparer from groupdocs.comparison.options import LoadOptions def compare_multiple_documents_protected(): source_load = LoadOptions() source_load.password = "1234" with Comparer("./source_protected.docx", source_load) as comparer: for target, password in ( ("./target_protected.docx", "5678"), ("./target2_protected.docx", "5678"), ("./target3_protected.docx", "5678"), ): load_opts = LoadOptions() load_opts.password = password comparer.add(target, load_opts) comparer.compare("./result.docx") if __name__ == "__main__": compare_multiple_documents_protected() ``` {{< /tab >}} {{< tab "source_protected.docx" >}} {{< tab-text >}} `source_protected.docx` is a password-protected source file. Click [here](/comparison/python-net/_sample_files/developer-guide/comparing-documents/compare-multiple-documents/source_protected.docx) to download it. {{< /tab-text >}} {{< /tab >}} {{< tab "target_protected.docx" >}} {{< tab-text >}} `target_protected.docx` is a password-protected target file. Click [here](/comparison/python-net/_sample_files/developer-guide/comparing-documents/compare-multiple-documents/target_protected.docx) to download it. {{< /tab-text >}} {{< /tab >}} {{< tab "target2_protected.docx" >}} {{< tab-text >}} `target2_protected.docx` is a password-protected target file. Click [here](/comparison/python-net/_sample_files/developer-guide/comparing-documents/compare-multiple-documents/target2_protected.docx) to download it. {{< /tab-text >}} {{< /tab >}} {{< tab "target3_protected.docx" >}} {{< tab-text >}} `target3_protected.docx` is a password-protected target file. Click [here](/comparison/python-net/_sample_files/developer-guide/comparing-documents/compare-multiple-documents/target3_protected.docx) to download it. {{< /tab-text >}} {{< /tab >}} {{< tab "result.docx" >}} ```text Binary file (DOCX, 25 KB) ``` [Download full output](/comparison/python-net/_output_files/developer-guide/comparing-documents/compare-multiple-documents/compare_multiple_documents_protected/result.docx) {{< /tab >}} {{< /tabs >}} ## Related topics - [Compare documents]({{< ref "comparison/python-net/developer-guide/comparing-documents/compare-documents" >}}) — single-target comparison. - [Customize changes styles]({{< ref "comparison/python-net/developer-guide/comparing-documents/customize-changes-styles" >}}) — full control over how changes are rendered. - [Load password-protected documents]({{< ref "comparison/python-net/developer-guide/loading-documents/load-password-protected-documents" >}}) — single-document password handling. --- ## Install GroupDocs.Comparison for Python via .NET Path: /comparison/python-net/getting-started/installation/ GroupDocs.Comparison for Python via .NET ships as a self-contained Python wheel on [PyPI](https://pypi.org/project/groupdocs-comparison-net/). The wheel bundles the .NET runtime, so no separate .NET installation is required on Windows. On Linux and macOS, a small set of native dependencies is needed for graphics and font rendering. ## Install from PyPI The recommended way to install GroupDocs.Comparison is via pip: ```bash pip install groupdocs-comparison-net ``` To install a specific version: ```bash pip install groupdocs-comparison-net==26.4.0 ``` Verify the installation: ```bash pip show groupdocs-comparison-net ``` ## Install from a downloaded wheel If you cannot install from PyPI (for example, in an offline environment), download the wheel for your platform from the [GroupDocs releases page](https://releases.groupdocs.com/comparison/python-net/) and install it locally. Wheels are published for four target platforms: | Platform | Wheel filename suffix | |---|---| | Windows x64 | `-win_amd64.whl` | | Linux x64 | `-manylinux*_x86_64.whl` | | macOS Intel | `-macosx_*_x86_64.whl` | | macOS Apple Silicon | `-macosx_*_arm64.whl` | After downloading, install with pip: ```bash pip install ./groupdocs_comparison_net-26.4.0-py3-none-win_amd64.whl ``` Expected output: ```text Processing ./groupdocs_comparison_net-26.4.0-py3-none-win_amd64.whl Installing collected packages: groupdocs-comparison-net Successfully installed groupdocs-comparison-net-26.4.0 ``` ## Native dependencies (Linux and macOS) On Windows the wheel is self-contained. On Linux and macOS, install the following before running any examples: ### Ubuntu / Debian ```bash sudo apt update sudo apt install -y libgdiplus libfontconfig1 libicu-dev ttf-mscorefonts-installer fontconfig sudo fc-cache -f ``` `ttf-mscorefonts-installer` accepts the EULA interactively; in CI pipelines, accept it non-interactively with `echo "ttf-mscorefonts-installer msttcorefonts/accepted-mscorefonts-eula select true" | sudo debconf-set-selections` before the install. ### macOS ```bash brew install mono-libgdiplus ``` If GroupDocs.Comparison fails with `DllNotFoundException: libSkiaSharp` on macOS, the system has a stale copy that conflicts with the bundled version. Rename it so the bundled library takes precedence: ```bash sudo mv /usr/local/lib/libSkiaSharp.dylib /usr/local/lib/libSkiaSharp.dylib.bak ``` ## Verify the installation After installing, confirm that the package imports cleanly: ```bash python -c "from groupdocs.comparison import Comparer; print('OK')" ``` If this prints `OK`, you are ready to compare your first document — head to the [Quick start guide]({{< ref "comparison/python-net/getting-started/quick-start-guide" >}}). --- ## Load Custom Fonts Path: /comparison/python-net/developer-guide/loading-documents/load-custom-fonts/ [GroupDocs.Comparison for Python via .NET](https://products.groupdocs.com/comparison/python-net) can compare documents that use non-standard fonts. Register the custom font directory through a `LoadOptions` instance before opening the documents. ## Example: Connect custom fonts and compare documents {{< tabs "load-custom-fonts">}} {{< tab "load_custom_fonts.py" >}} ```python from groupdocs.comparison import Comparer from groupdocs.comparison.options import LoadOptions def load_custom_fonts(): load_options = LoadOptions() load_options.font_directories.append("./fonts/") with Comparer("./source.docx", load_options) as comparer: comparer.add("./target.docx", load_options) comparer.compare("./result.docx") if __name__ == "__main__": load_custom_fonts() ``` {{< /tab >}} {{< tab "source.docx" >}} {{< tab-text >}} `source.docx` is the source file used in this example. Click [here](/comparison/python-net/_sample_files/developer-guide/loading-documents/load-custom-fonts/source.docx) to download it. {{< /tab-text >}} {{< /tab >}} {{< tab "target.docx" >}} {{< tab-text >}} `target.docx` is the target file used in this example. Click [here](/comparison/python-net/_sample_files/developer-guide/loading-documents/load-custom-fonts/target.docx) to download it. {{< /tab-text >}} {{< /tab >}} {{< tab "result.docx" >}} ```text Binary file (DOCX, 11 KB) ``` [Download full output](/comparison/python-net/_output_files/developer-guide/loading-documents/load-custom-fonts/load_custom_fonts/result.docx) {{< /tab >}} {{< /tabs >}} The `./fonts/` directory in the example should contain the `.otf` or `.ttf` files needed to render the document accurately. --- ## AI Agents and LLM Integration Path: /comparison/python-net/agents-and-llm-integration/ ## AI agent and LLM friendly GroupDocs.Comparison for Python via .NET is designed to work seamlessly with AI agents, LLMs, and automated code generation tools. The library ships machine-readable documentation in multiple formats — including an `AGENTS.md` file inside the pip package itself — so that AI assistants can discover and use the API without manual guidance. ## MCP server GroupDocs provides an [MCP (Model Context Protocol) server](https://docs.groupdocs.com/mcp) that enables LLMs to query the documentation on demand instead of loading it all at once. This saves tokens and lets your AI assistant fetch only the information it needs for the current task. To connect your AI tool to the MCP server, add the GroupDocs endpoint to your MCP configuration: {{< tabs "mcp-setup">}} {{< tab "Claude Code / Claude Desktop" >}} ```json // Claude Code: ~/.claude/settings.json (or project .mcp.json) // Claude Desktop: ~/Library/Application Support/Claude/claude_desktop_config.json { "mcpServers": { "groupdocs-docs": { "url": "https://docs.groupdocs.com/mcp" } } } ``` {{< /tab >}} {{< tab "GitHub Copilot" >}} ```json // .vscode/mcp.json in your project root { "servers": { "groupdocs-docs": { "url": "https://docs.groupdocs.com/mcp" } } } ``` {{< /tab >}} {{< tab "Cursor" >}} ```json // .cursor/mcp.json in your project root { "mcpServers": { "groupdocs-docs": { "url": "https://docs.groupdocs.com/mcp" } } } ``` {{< /tab >}} {{< tab "OpenCode" >}} ```json // ~/.config/opencode/config.json { "mcpServers": { "groupdocs-docs": { "url": "https://docs.groupdocs.com/mcp" } } } ``` {{< /tab >}} {{< tab "Generic MCP" >}} ```json // Any MCP-compatible client { "mcpServers": { "groupdocs-docs": { "url": "https://docs.groupdocs.com/mcp" } } } ``` {{< /tab >}} {{< /tabs >}} See [https://docs.groupdocs.com/mcp](https://docs.groupdocs.com/mcp) for full setup instructions and the list of available tools. ## AGENTS.md — built into the package The `groupdocs-comparison-net` pip package includes an `AGENTS.md` file at `groupdocs/comparison/AGENTS.md`. AI coding assistants that scan installed packages (such as Claude Code, Cursor, GitHub Copilot) can automatically discover the API surface, usage patterns, and troubleshooting tips. After installing the package, you can find it at: ```bash pip show -f groupdocs-comparison-net | grep AGENTS ``` ## Machine-readable documentation Every documentation page is available as a plain Markdown file that AI tools can fetch and process directly: | Resource | URL | |---|---| | Full documentation (single file) | `https://docs.groupdocs.com/comparison/python-net/llms-full.txt` | | Full documentation (all products) | `https://docs.groupdocs.com/llms-full.txt` | | Individual page (any page) | Append `.md` to the page URL, e.g. `https://docs.groupdocs.com/comparison/python-net.md` | | Quick start guide | `https://docs.groupdocs.com/comparison/python-net/getting-started/quick-start-guide.md` | ### How to use with AI tools Point your AI assistant to the full documentation file for comprehensive context: ``` Fetch https://docs.groupdocs.com/comparison/python-net/llms-full.txt and use it as a reference for GroupDocs.Comparison for Python via .NET API. ``` Or reference individual pages for focused tasks: ``` Read https://docs.groupdocs.com/comparison/python-net/getting-started/quick-start-guide.md and help me compare two DOCX files in Python and print the detected changes. ``` ## Why GroupDocs.Comparison is a good building block for AI document workflows LLM-driven document workflows constantly need to answer one question: *what changed?* Between two contract revisions, between a model-generated draft and the human-edited version, between a vendor's quote yesterday and today, between a reviewed PDF and the latest export. GroupDocs.Comparison gives an agent a deterministic, format-aware answer instead of a token-by-token diff that confuses headings with paragraphs. Typical agent-driven tasks: - **Contract / policy review.** Detect inserted, deleted, and modified clauses between two DOCX or PDF revisions and feed only the changes to the model — far cheaper than re-reading both documents. - **AI-edit audit.** Compare the document the agent produced against the original to verify (and explain) every change it made. - **Model-vs-ground-truth evaluation.** Score a model-generated DOCX/PDF against a reference document and surface the diffs that matter (text, style, structure). - **Change-only summarisation.** Render a result document containing only the changes (`show_only_changed = True`) and pass that to the LLM instead of the full file. - **Accept/reject pipelines.** Let the agent classify each detected change, then re-emit the document honouring its accept/reject decisions via `apply_changes`. A minimal end-to-end snippet an agent can lift directly: ```python from groupdocs.comparison import Comparer from groupdocs.comparison.options import CompareOptions, ChangeType # Step 1: detect changes without writing an output document with Comparer("revision_a.docx") as comparer: comparer.add("revision_b.docx") options = CompareOptions() options.detect_style_changes = True options.calculate_coordinates = True comparer.compare(compare_options=options) changes = comparer.get_changes() for c in changes: print(f"[{c.type}] {c.text!r} at ({c.box.x:.0f}, {c.box.y:.0f})") # Step 2: filter — only feed inserts/deletes to the LLM material = [c for c in changes if c.type in (ChangeType.INSERTED, ChangeType.DELETED)] ``` For end-to-end examples — including [accept-or-reject-detected-changes]({{< ref "comparison/python-net/developer-guide/comparing-documents/accept-or-reject-detected-changes" >}}), [compare-multiple-documents]({{< ref "comparison/python-net/developer-guide/comparing-documents/compare-multiple-documents" >}}), and [get-changes-coordinates]({{< ref "comparison/python-net/developer-guide/comparing-documents/get-changes-coordinates" >}}) — see the [Developer Guide]({{< ref "comparison/python-net/developer-guide" >}}). Every code block on those pages has a runnable counterpart in the [examples repository](https://github.com/groupdocs-comparison/GroupDocs.Comparison-for-Python-via-.NET). ## Pair with GroupDocs.Conversion for cross-format comparison Comparison expects both inputs in the same family (DOCX vs DOCX, PDF vs PDF, …). When an agent needs to compare across formats — a DOCX draft against an exported PDF, a vendor's PPTX against a converted-to-PDF archive copy — chain [GroupDocs.Conversion for Python via .NET](https://docs.groupdocs.com/conversion/python-net/) first: 1. Use **GroupDocs.Conversion** to normalise both inputs to a common target (PDF or DOCX). 2. Use **GroupDocs.Comparison** to detect changes between the normalised pair. This lets a single agent handle the long tail of email, CAD, archive, and image inputs without having to special-case every source format. ## AGENTS.md reference The content below is the same `AGENTS.md` file that ships inside the `groupdocs-comparison-net` package. Copy it into your project as `AGENTS.md` or point your AI assistant to this page. ````markdown # GroupDocs.Comparison for Python via .NET -- AGENTS.md > Instructions for AI agents working with this package. Compare documents and detect text, style, and formatting changes -- Word, PDF, Excel, PowerPoint, ODT, HTML, images, and more. Includes accept/reject workflows and multi-source comparison. ## Install ```bash pip install groupdocs-comparison-net ``` **Python**: 3.5 - 3.14 | **Platforms**: Windows, Linux, macOS ## Resources | Resource | URL | |---|---| | Documentation | https://docs.groupdocs.com/comparison/python-net/ | | LLM-optimized docs | https://docs.groupdocs.com/comparison/python-net/llms-full.txt | | API reference | https://reference.groupdocs.com/comparison/python-net/ | | Code examples | https://docs.groupdocs.com/comparison/python-net/developer-guide/ | | Release notes | https://releases.groupdocs.com/comparison/python-net/release-notes/ | | PyPI | https://pypi.org/project/groupdocs-comparison-net/ | | Free support forum | https://forum.groupdocs.com/c/comparison/ | | 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.comparison import License, Metered, Comparer, ComparerSettings, Document, Color from groupdocs.comparison.common.exceptions import ComparisonException, DocumentComparisonException from groupdocs.comparison.interfaces import IDocumentInfo from groupdocs.comparison.localization import SupportedLocales from groupdocs.comparison.logging import ConsoleLogger from groupdocs.comparison.options import ( ApplyChangeOptions, CompareOptions, GetChangeOptions, LoadOptions, SaveOptions, PreviewOptions, CalculateCoordinatesModeEnumeration, ChangeType, ComparisonDisplayMode, DetalisationLevel, FolderComparisonExtension, ImagesInheritance, MetadataType, PaperSize, PasswordSaveOption, PreviewFormats, StyleSettings, OriginalSize, DiagramMasterSetting, FileAuthorMetadata, IgnoreChangeSensitivitySettings, PagesSetup, PdfCompareOptions, PreviewResolution, Size, WordCompareOptions, Color, # re-exported from groupdocs.pydrawing for styling ) from groupdocs.comparison.result import ( ChangeInfo, ComparisonAction, FileType, PageInfo, Rectangle, StyleChangeInfo, ) from groupdocs.comparison.words.revision import ( ApplyRevisionOptions, RevisionAction, RevisionHandler, RevisionInfo, RevisionType, ) ``` ## Quick Start ```python from groupdocs.comparison import Comparer with Comparer("source.docx") as comparer: comparer.add("target.docx") comparer.compare("result.docx") ``` ## Compare with Options ```python from groupdocs.comparison import Comparer from groupdocs.comparison.options import CompareOptions with Comparer("source.docx") as comparer: comparer.add("target.docx") options = CompareOptions() options.sensitivity_of_comparison = 75 options.detect_style_changes = True options.generate_summary_page = True comparer.compare("result.docx", options) ``` **Comparer constructor.** `Comparer(file_path=None, folder_path=None, compare_options=None, load_options=None, settings=None, document=None)` accepts kwargs. Pass a path string positionally, or a stream as `document=...`, or a folder via `folder_path=...`: ```python from groupdocs.comparison import Comparer, ComparerSettings from groupdocs.comparison.logging import ConsoleLogger from groupdocs.comparison.options import LoadOptions settings = ComparerSettings() settings.logger = ConsoleLogger() load = LoadOptions(); load.password = "1234" with Comparer("protected.docx", load_options=load, settings=settings) as comparer: comparer.add("target.docx", load_options=load) comparer.compare("result.docx") ``` ## Get Detected Changes ```python from groupdocs.comparison import Comparer from groupdocs.comparison.options import ChangeType with Comparer("source.docx") as comparer: comparer.add("target.docx") comparer.compare() # call with no args before get_changes() for change in comparer.get_changes(): print(f"[{change.type}] {change.text}") # Filter by change type with Comparer("source.docx") as comparer: comparer.add("target.docx") comparer.compare() inserted = comparer.get_changes(filter=ChangeType.INSERTED) ``` ## Accept / Reject Individual Changes ```python from groupdocs.comparison import Comparer from groupdocs.comparison.options import ApplyChangeOptions from groupdocs.comparison.result import ComparisonAction with Comparer("source.docx") as comparer: comparer.add("target.docx") comparer.compare() changes = comparer.get_changes() # Reject the first detected change changes[0].comparison_action = ComparisonAction.REJECT apply_opts = ApplyChangeOptions() apply_opts.changes = changes comparer.apply_changes("result.docx", apply_opts) ``` ## Multi-Source Comparison ```python from groupdocs.comparison import Comparer with Comparer("source.docx") as comparer: comparer.add("target1.docx") comparer.add("target2.docx") comparer.add("target3.docx") comparer.compare("result.docx") ``` ## Customise Change Styling (colours) `StyleSettings` controls how inserted / deleted / changed regions look in the result document. Colour properties accept anything that looks like a colour — a `Color` struct, an `(r, g, b)` or `(r, g, b, a)` tuple, a packed-ARGB `int`, a `'#RRGGBB'` / `'#AARRGGBB'` string, or a named colour string. ```python from groupdocs.comparison import Comparer, Color from groupdocs.comparison.options import CompareOptions, StyleSettings with Comparer("source.docx") as comparer: comparer.add("target.docx") options = CompareOptions() options.inserted_item_style = StyleSettings() options.inserted_item_style.font_color = Color.from_name("firebrick") options.deleted_item_style = StyleSettings() options.deleted_item_style.font_color = (200, 100, 50) # RGB tuple options.deleted_item_style.highlight_color = "#FFFF00" # hex string options.changed_item_style = StyleSettings() options.changed_item_style.font_color = 0xFF0000FF # packed ARGB comparer.compare("result.docx", options) ``` `Color` is also importable from `groupdocs.comparison.options` (next to `StyleSettings`) or directly from `groupdocs.pydrawing`. Case-insensitive named-colour access works too (`Color.red`, `Color.Red`, `Color.RED`, `Color.light_blue`). ## Render Page Previews `Document.generate_preview(PreviewOptions(...))` produces per-page PNG/JPEG/BMP previews. `PreviewOptions` accepts plain Python callables for the stream factories — no adapter classes needed. ```python from groupdocs.comparison import Comparer from groupdocs.comparison.options import PreviewOptions, PreviewFormats def create_page_stream(page_number: int): # Return a writable stream — .NET writes the rendered page into it. return open(f"page-{page_number}.png", "wb") def release_page_stream(page_number: int): # Called after .NET is done with the stream. The stream you returned # from create_page_stream is already flushed/closed by .NET. pass with Comparer("source.docx") as comparer: preview = PreviewOptions(create_page_stream, release_page_stream) preview.preview_format = PreviewFormats.PNG preview.page_numbers = [1, 2, 3] comparer.source.generate_preview(preview) ``` `PreviewOptions(create_page_stream)` is also valid — pass just the create callback and omit the release one. ## Get Change Coordinates When `CompareOptions.calculate_coordinates = True`, each `ChangeInfo.box` returns a `Rectangle` with snake_case `.x / .y / .width / .height` accessors (no PascalCase-dict gymnastics): ```python from groupdocs.comparison import Comparer from groupdocs.comparison.options import CompareOptions with Comparer("source.docx") as comparer: comparer.add("target.docx") options = CompareOptions() options.calculate_coordinates = True comparer.compare("result.docx", options) for change in comparer.get_changes(): b = change.box print(f"({b.x:.0f}, {b.y:.0f}) {b.width:.0f}x{b.height:.0f} — {change.text!r}") ``` ## Password-Protected Documents ```python from groupdocs.comparison import Comparer from groupdocs.comparison.options import LoadOptions, SaveOptions src_load = LoadOptions(); src_load.password = "1234" tgt_load = LoadOptions(); tgt_load.password = "5678" save_opts = SaveOptions(); save_opts.password = "out-secret" with Comparer("protected_source.docx", load_options=src_load) as comparer: comparer.add("protected_target.docx", load_options=tgt_load) comparer.compare("result.docx", compare_options=None, save_options=save_opts) ``` ## Compare from Stream ```python import io from groupdocs.comparison import Comparer with open("source.docx", "rb") as src, open("target.docx", "rb") as tgt: with Comparer(src) as comparer: comparer.add(tgt) comparer.compare("result.docx") # Or from in-memory bytes src_buf = io.BytesIO(source_bytes) tgt_buf = io.BytesIO(target_bytes) with Comparer(src_buf) as comparer: comparer.add(tgt_buf) comparer.compare("result.docx") ``` ## Get Document Info ```python from groupdocs.comparison import Comparer with Comparer("document.docx") as comparer: info = comparer.source.get_document_info() print(f"Pages: {info.page_count}, Size: {info.size}") ``` ## Command Line The wheel installs a `groupdocs-comparison` console script (also reachable via `python -m groupdocs.comparison`). ```bash groupdocs-comparison compare SOURCE TARGET OUTPUT [flags] groupdocs-comparison info FILE groupdocs-comparison list-formats groupdocs-comparison --license PATH ... # apply a license first groupdocs-comparison --version groupdocs-comparison --help python -m groupdocs.comparison --version # equivalent module form ``` `compare` flags: | Flag | Type | Effect | |---|---|---| | `--password` | str | Password for protected source/target documents | | `--output-password` | str | Password applied to the resultant document | | `--sensitivity` | int (0-100) | Sensitivity of comparison | | `--detect-style-changes` | flag | Detect bold / italic / colour changes | | `--mark-changed-content` | flag | Mark changed content in the result | | `--compare-bookmarks` | flag | Include bookmark comparison | | `--generate-summary-page` | flag | Append a summary page with statistics | | `--show-revisions` | flag | Show Word track-changes revisions | **Exit codes.** `0` success · `2` user error (missing input) · `1` runtime error (.NET exception body printed). **Limits.** The CLI is a thin shim over the Python API for the common case. Drop into Python for: multi-target compare in one Comparer, in-memory streams (`io.BytesIO`), accept/reject individual changes (`apply_changes`), folder comparison, custom logging or comparer settings, revision handlers. ## Licensing ```python from groupdocs.comparison 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 ## API Reference ### Comparer | Method | Returns | Description | |---|---|---| | `__init__(file_path=None, folder_path=None, compare_options=None, load_options=None, settings=None, document=None)` | | Open a source. Pass path positionally, or `folder_path=` / `document=` (stream) by kwarg | | `add(file_path=None, compare_options=None, load_options=None, document=None)` | `None` | Register a target for comparison. Call repeatedly for multi-source | | `compare(file_path=None, stream=None, compare_options=None, save_options=None)` | `Document` | Run the comparison. Call with no args before `get_changes()` to materialise without writing output | | `get_changes(get_change_options=None, filter=None)` | `list[ChangeInfo]` | Retrieve detected changes after `compare()` | | `apply_changes(file_path=None, apply_change_options=None, stream=None, save_options=None)` | `None` | Re-emit the result honoring per-change `comparison_action` | | `compare_directory(file_path=None, compare_options=None)` | `None` | Folder-level compare (set `compare_options.directory_compare = True`) | | `get_result_string()` | `str` | Result document as text | | `get_result_document_stream()` | `Stream` | Result document as a stream | | `dispose()` | `None` | Release native resources (use a `with` block instead when possible) | Properties: `source: Document`, `targets: list[Document]`, `result: Document`, `source_folder: str`, `target_folder: str`. ### CompareOptions | Property | Type | Writable | |---|---|---| | `paper_size` | `PaperSize` | yes | | `show_deleted_content` | `bool` | yes | | `show_inserted_content` | `bool` | yes | | `generate_summary_page` | `bool` | yes | | `extended_summary_page` | `bool` | yes | | `show_only_summary_page` | `bool` | yes | | `detect_style_changes` | `bool` | yes | | `mark_nested_content` | `bool` | yes | | `calculate_coordinates` | `bool` | yes | | `calculate_coordinates_mode` | `CalculateCoordinatesModeEnumeration` | yes | | `header_footers_comparison` | `bool` | yes | | `detalisation_level` | `DetalisationLevel` | yes | | `mark_changed_content` | `bool` | yes | | `inserted_item_style` | `StyleSettings` | yes | | `deleted_item_style` | `StyleSettings` | yes | | `changed_item_style` | `StyleSettings` | yes | | `mark_line_breaks` | `bool` | yes | | `compare_images_pdf` | `bool` | yes | | `images_inheritance_mode` | `ImagesInheritance` | yes | | `compare_bookmarks` | `bool` | yes | | `compare_variable_property` | `bool` | yes | | `compare_document_property` | `bool` | yes | | `word_track_changes` | `bool` | yes | | `show_only_changed` | `bool` | yes | | `directory_compare` | `bool` | yes | | `user_master_path` | `str` | yes | | `folder_comparison_extension` | `FolderComparisonExtension` | yes | | `revision_author_name` | `str` | yes | | `sensitivity_of_comparison` | `int` | yes | | `sensitivity_of_comparison_for_tables` | `int?` | yes | | `ignore_change_settings` | `IgnoreChangeSensitivitySettings` | yes | | `words_separator_chars` | `Char[]` | yes | | `password_save_option` | `PasswordSaveOption` | yes | | `original_size` | `OriginalSize` | yes | | `diagram_master_setting` | `DiagramMasterSetting` | yes | | `show_revisions` | `bool` | yes | | `leave_gaps` | `bool` | yes | ### LoadOptions | Property | Type | Writable | |---|---|---| | `password` | `str` | yes | | `font_directories` | `list` | yes | | `load_text` | `bool` | yes | | `file_type` | `FileType` | yes | ### SaveOptions | Property | Type | Writable | |---|---|---| | `password` | `str` | yes | ### ApplyChangeOptions | Property | Type | Writable | |---|---|---| | `changes` | `list[ChangeInfo]` | yes | | `save_original_state` | `bool` | yes | ### ChangeInfo | Property | Type | Description | |---|---|---| | `id` | `int` | Stable identifier for the change | | `type` | `ChangeType` | INSERTED / DELETED / STYLE_CHANGED / etc. | | `text` | `str` | Affected text | | `author` | `str` | Original author (when available) | | `comparison_action` | `ComparisonAction` | Set to ACCEPT / REJECT before `apply_changes()` | | `box` | `Rectangle` | Coordinates if `calculate_coordinates=True` was set. Read via `change.box.x / .y / .width / .height` | | `style_changes` | `list[StyleChangeInfo]` | Per-property style deltas | ## Key Patterns - **Properties**: use `snake_case` -- auto-mapped to .NET `PascalCase` - **Context managers**: `with Comparer(...) 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 - **Enums**: case-insensitive, lazy-loaded (e.g., `FileType.DOCX`) - **Collections**: `for item in result` and `len(result)` work on .NET collections - **Apply-changes flow**: `compare()` (no args) → `get_changes()` → set `comparison_action` per change → `apply_changes(out, ApplyChangeOptions(changes=...))`. Calling `compare(out)` with an output path skips the apply-changes step entirely. ## Platform Requirements | Platform | Requirements | |---|---| | Windows | None | | Linux | `apt install libgdiplus libfontconfig1 ttf-mscorefonts-installer` | | macOS | `brew install mono-libgdiplus` | ## Troubleshooting **`"Error occurred while converting document"` when comparing XLSX → XLSX** -- known upstream-side issue in `GroupDocs.Comparison.dll` SaveDocument step (reproduces in pure .NET, not a wrapper bug). DOCX/PDF/TXT/PPTX paths are unaffected. Track upstream for a fix; in the meantime convert to PDF or DOCX target instead. **`Gdip` type initializer / `libgdiplus` DllNotFoundException on macOS Apple Silicon** -- `GroupDocs.Comparison.dll`'s PDF and image diff paths go through `System.Drawing.Common`, which fails to load `libgdiplus` on mac-arm64 even when the library is installed and individually loadable. DOCX/TXT/HTML/PPTX compares are unaffected. Workarounds: (a) compare to a non-rasterized target format like DOCX or HTML when possible; (b) run the comparison on macOS x64, Linux, or Windows where this code path works. Engine-side fix needed (drop `System.Drawing.Common` in favour of SkiaSharp / Aspose.Drawing, which other GroupDocs products already use cross-platform). **`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-comparison-net` **Still stuck?** Post your question at https://forum.groupdocs.com/c/comparison/ -- the development team responds directly. ```` ## See also - [Quick Start Guide]({{< ref "comparison/python-net/getting-started/quick-start-guide" >}}) — your first comparison in five minutes - [Developer Guide]({{< ref "comparison/python-net/developer-guide" >}}) — runnable examples for every API surface - [API Reference](https://reference.groupdocs.com/comparison/python-net) — full class and method documentation --- ## Compare Folders Path: /comparison/python-net/developer-guide/compare-folders/ [GroupDocs.Comparison for Python via .NET](https://products.groupdocs.com/comparison/python-net) can compare two folders, surface which files were added, deleted, or modified, and produce either a `TXT` or `HTML` report. Steps: 1. Instantiate `CompareOptions`. 2. Set `directory_compare = True`. 3. Optionally set `folder_comparison_extension` to `FolderComparisonExtension.HTML` for an HTML report (the default is TXT). 4. Optionally set `show_only_changed = True` to filter out unchanged items. 5. Create `Comparer` with the source folder path and the `CompareOptions`. 6. Call `add()` with the target folder and the same `CompareOptions`. 7. Call `compare_directory()` with the result file path and the `CompareOptions`. ## Example: Compare two folders The example below uses the bare folder names `SourceFolder` and `TargetFolder` rather than `./SourceFolder` so that the example-runner can detect them as shared sample directories. In your own code you can use any absolute or relative path — `./source-folder`, `/home/me/projects/src`, etc. {{< tabs "compare-folders">}} {{< tab "compare_folders.py" >}} ```python from groupdocs.comparison import Comparer from groupdocs.comparison.options import CompareOptions, FolderComparisonExtension def compare_folders(): compare_options = CompareOptions() compare_options.directory_compare = True compare_options.folder_comparison_extension = FolderComparisonExtension.HTML compare_options.show_only_changed = True with Comparer("SourceFolder", compare_options) as comparer: comparer.add("TargetFolder", compare_options) comparer.compare_directory("./result.html", compare_options) print("Folders compared successfully. Check output in result.html.") if __name__ == "__main__": compare_folders() ``` {{< /tab >}} {{< tab "result.htmlResult.html" >}} ```text