# GroupDocs.Redaction for Python via .NET — Complete Documentation
> Native Python library that permanently redacts sensitive content — text, metadata, annotations, and image areas — from PDF, Word, Excel, PowerPoint, and image files on Windows, Linux, and macOS. No Microsoft Office or Adobe Acrobat required.
---
## Features Overview
Path: /redaction/python-net/features-overview/
GroupDocs.Redaction for Python via .NET removes or permanently obscures sensitive information across a wide range of [supported document formats]({{< ref "redaction/python-net/getting-started/supported-document-formats.md" >}}). Every redaction follows the same workflow: open a document with `Redactor`, apply one or more redactions with `apply()`, then `save()` the cleaned result either in its original format or as a sanitized PDF. The capabilities below can be combined freely in a single pass.
## Text redaction
Find and replace text by an exact phrase or by a regular expression, covering both whole words and complex patterns such as e-mail addresses, phone numbers, or national ID numbers. Matched text can be replaced with substitute text or covered by a colored box so the original content cannot be recovered. In spreadsheets you can narrow the search to a single worksheet or column. See [Text Redactions]({{< ref "redaction/python-net/developer-guide/basic-usage/text-redactions.md" >}}).
## Metadata redaction
Erase or rewrite document metadata — author, title, company, comments, and EXIF data on images — so no sensitive details leak through document properties. You can clear all metadata, target specific fields, or replace values with new ones. See [Metadata Redactions]({{< ref "redaction/python-net/developer-guide/basic-usage/metadata-redactions.md" >}}).
## Image-area redaction
Black out a rectangular region of an embedded image or a scanned page by drawing a filled box over a given area — useful for hiding signatures, photos, headers, or footers where confidential data is expected to appear. See [Image Redactions]({{< ref "redaction/python-net/developer-guide/basic-usage/image-redactions.md" >}}).
## Annotation redaction
Rewrite or delete annotations, comments, and notes. You can remove every annotation or use a regular expression to match only the ones that contain sensitive text. See [Annotation Redactions]({{< ref "redaction/python-net/developer-guide/basic-usage/annotation-redactions.md" >}}).
## Page removal
Remove whole pages from PDF documents, slides from presentations, and worksheets from spreadsheets. You specify a starting page and a count, together with the direction relative to the starting point. See [Remove Page Redactions]({{< ref "redaction/python-net/developer-guide/basic-usage/remove-page-redactions.md" >}}).
## Rasterization to PDF
Save the cleaned document as a PDF whose pages are rendered as raster images. The resulting file contains no searchable text and none of the original metadata, so the removed content cannot be recovered. Rasterization is the right choice when you must hand a document to third parties or conform to regulations that require PDF. You can select specific pages and request PDF/A compliance through the advanced rasterization options. See [Save in Rasterized PDF]({{< ref "redaction/python-net/developer-guide/advanced-usage/saving-documents/save-in-rasterized-pdf.md" >}}) and [Advanced Rasterization Options]({{< ref "redaction/python-net/developer-guide/advanced-usage/saving-documents/use-advanced-rasterization-options.md" >}}).
## Redaction policies
Group several redactions into a reusable policy and apply the same set of rules consistently across many documents — ideal for recurring tasks such as scrubbing a standard set of fields before publishing. See [Use Redaction Policies]({{< ref "redaction/python-net/developer-guide/advanced-usage/use-redaction-policies.md" >}}).
## Loading and saving
Load documents from a local path or from a stream, including password-protected files, and optionally pre-rasterize a document before redacting. When saving, keep the original format for further editing, overwrite the original file, rasterize to PDF, or write to a stream. See [Loading Documents]({{< ref "redaction/python-net/developer-guide/advanced-usage/loading-documents/_index.md" >}}) and [Saving Documents]({{< ref "redaction/python-net/developer-guide/advanced-usage/saving-documents/_index.md" >}}).
## On-premise
GroupDocs.Redaction for Python via .NET runs entirely on your own infrastructure — your documents never leave your environment. The package is a self-contained wheel that bundles everything it needs, so no Microsoft Office, OpenOffice, Adobe Acrobat, or separate runtime has to be installed. See [System Requirements]({{< ref "redaction/python-net/getting-started/system-requirements.md" >}}) for the supported platforms and native dependencies.
---
## Get supported file formats
Path: /redaction/python-net/get-supported-file-formats/
GroupDocs.Redaction allows to get the list of all supported file formats by these steps:
* Call [GetSupportedFileTypes](https://reference.groupdocs.com/redaction/python-net/groupdocs.redaction/filetype/get_supported_file_types/) of [FileType](https://reference.groupdocs.com/redaction/python-net/groupdocs.redaction/filetype/) class;
* Enumerate through the collection of [FileType](https://reference.groupdocs.com/redaction/python-net/groupdocs.redaction/filetype/) objects*.*
The following example demonstrates how to get supported file formats list.
{{< tabs "code-example-list-supported-formats" >}}
{{< tab "list_supported_formats.py" >}}
```python
from groupdocs.redaction import FileType
def list_supported_formats():
# Retrieve the collection of supported file types
supported_file_types = FileType.get_supported_file_types()
# Enumerate the file types sorted by extension
for file_type in sorted(supported_file_types, key=lambda x: x.extension):
print(file_type)
if __name__ == "__main__":
list_supported_formats()
```
{{< /tab >}}
{{< tab "list-supported-formats.txt" >}}
```text
Bitmap Image File (.bmp)
Comma Separated Values File (.csv)
Microsoft Word Document (.doc)
Word Open XML Macro-Enabled Document (.docm)
Microsoft Word Open XML Document (.docx)
Word Document Template (.dot)
Word Open XML Macro-Enabled Document Template (.dotm)
Word Open XML Document Template (.dotx)
Graphical Interchange Format File (.gif)
Hypertext Markup Language File (.htm)
[TRUNCATED]
```
[Download full output](/redaction/python-net/_output_files/developer-guide/basic-usage/get-supported-file-formats/list_supported_formats/list-supported-formats.txt)
{{< /tab >}}
{{< /tabs >}}
---
## Install GroupDocs.Redaction for Python via .NET
Path: /redaction/python-net/installation/
GroupDocs.Redaction for Python via .NET is distributed as a pre-built wheel on [PyPI](https://pypi.org/project/groupdocs-redaction-net/). The PyPI index hosts a separate wheel for each supported platform, and `pip` picks the correct one automatically. Each wheel is self-contained: it bundles the embedded runtime and every managed dependency, so no Microsoft Office, OpenOffice, Adobe Acrobat, or separate runtime install is required.
Before installing, confirm your environment matches the supported platforms and Python versions listed in the [System Requirements]({{< ref "redaction/python-net/getting-started/system-requirements.md" >}}) topic.
## Install Package from PyPI
Open a terminal and run the install command for your platform:
{{< tabs "install-pypi">}}
{{< tab "Windows" >}}
```ps
py -m pip install groupdocs-redaction-net
```
{{< /tab >}}
{{< tab "Linux" >}}
```bash
python3 -m pip install groupdocs-redaction-net
```
{{< /tab >}}
{{< tab "macOS" >}}
```bash
python3 -m pip install groupdocs-redaction-net
```
{{< /tab >}}
{{< /tabs >}}
After running the command you should see output similar to:
```bash
Collecting groupdocs-redaction-net
Downloading groupdocs_redaction_net-26.6.0-py3-none-win_amd64.whl.metadata (3.0 kB)
Downloading groupdocs_redaction_net-26.6.0-py3-none-win_amd64.whl (40.0 MB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 40.0/40.0 MB 2.8 MB/s eta 0:00:00
Installing collected packages: groupdocs-redaction-net
Successfully installed groupdocs-redaction-net-26.6.0
```
The wheel file name will include a platform suffix that matches your operating system — for example `manylinux1_x86_64` on Ubuntu/Debian, `macosx_11_0_arm64` on Apple Silicon, or `win_amd64` on 64-bit Windows.
## Add the Package to `requirements.txt`
For reproducible environments, pin the package version in your `requirements.txt`:
```txt
groupdocs-redaction-net==26.6.0
```
Then install all dependencies in one step:
```bash
pip install -r requirements.txt
```
## Install from a Pre-Downloaded Wheel
If your build environment cannot reach PyPI, download the appropriate wheel from the [GroupDocs Releases website](https://releases.groupdocs.com/redaction/python-net/) and install it locally. Wheels are published for the following four platforms:
- **Windows 64-bit**: file name ends with `win_amd64.whl`
- **Linux x64 (glibc)**: file name ends with `manylinux1_x86_64.whl`
- **macOS Intel**: file name ends with `macosx_10_14_x86_64.whl`
- **macOS Apple Silicon**: file name ends with `macosx_11_0_arm64.whl`
Place the downloaded wheel into your project folder, then install it:
{{< tabs "install-wheel">}}
{{< tab "Windows (64-bit)" >}}
```ps
py -m pip install ./groupdocs_redaction_net-26.6.0-py3-none-win_amd64.whl
```
{{< /tab >}}
{{< tab "Linux (glibc)" >}}
```bash
python3 -m pip install ./groupdocs_redaction_net-26.6.0-py3-none-manylinux1_x86_64.whl
```
{{< /tab >}}
{{< tab "macOS (Intel)" >}}
```bash
python3 -m pip install ./groupdocs_redaction_net-26.6.0-py3-none-macosx_10_14_x86_64.whl
```
{{< /tab >}}
{{< tab "macOS (Apple Silicon)" >}}
```bash
python3 -m pip install ./groupdocs_redaction_net-26.6.0-py3-none-macosx_11_0_arm64.whl
```
{{< /tab >}}
{{< /tabs >}}
Expected output:
```bash
Processing ./groupdocs_redaction_net-26.6.0-py3-none-*.whl
Installing collected packages: groupdocs-redaction-net
Successfully installed groupdocs-redaction-net-26.6.0
```
## Platform Prerequisites
On Windows no extra steps are required. On Linux and macOS, install the native libraries the rendering engine depends on:
{{< tabs "platform-prereqs">}}
{{< tab "Linux" >}}
```bash
apt install libgdiplus libfontconfig1 libicu-dev ttf-mscorefonts-installer
```
{{< /tab >}}
{{< tab "macOS" >}}
```bash
brew install mono-libgdiplus
```
{{< /tab >}}
{{< /tabs >}}
{{< alert style="warning" >}}
In version 26.6.0, **rasterization to PDF and image-area redaction run only on Windows** — on Linux/macOS they raise `System.PlatformNotSupportedException`, and the native packages above do not lift that restriction. Text, metadata, annotation, and page redaction and original-format saves work on every platform. See [System Requirements]({{< ref "redaction/python-net/getting-started/system-requirements.md" >}}) for the full feature-support matrix.
{{< /alert >}}
## Verify the Installation
Confirm the package imported correctly and check the installed version:
```bash
python -c "import groupdocs.redaction; print('GroupDocs.Redaction is ready')"
```
You can also list the installed package with `pip show groupdocs-redaction-net` to confirm the version and location.
## Next Steps
- Follow the [Hello, World!]({{< ref "redaction/python-net/getting-started/hello-world.md" >}}) guide to run your first redaction.
- Read the [Features Overview]({{< ref "redaction/python-net/getting-started/features-overview.md" >}}) to see everything you can redact.
- Clone the [examples repository](https://github.com/groupdocs-redaction/GroupDocs.Redaction-for-Python-via-.NET) and read [How to Run Examples]({{< ref "redaction/python-net/getting-started/how-to-run-examples.md" >}}) to try every documented scenario locally.
---
## Load from local disc
Path: /redaction/python-net/load-from-local-disc/
[GroupDocs.Redaction.Redactor](https://reference.groupdocs.com/redaction/python-net/groupdocs.redaction/redactor/) class is a main class in Redaction API, providing functionality to open a document. When document is located on the local disk, you can pass its path to [Redactor](https://reference.groupdocs.com/redaction/python-net/groupdocs.redaction/redactor) class constructor.
The following example demonstrates how to open a document from local disc:
{{< tabs "code-example-load-from-local-disc" >}}
{{< tab "load_from_local_disc.py" >}}
```python
from groupdocs.redaction import Redactor
from groupdocs.redaction.options import SaveOptions
from groupdocs.redaction.redactions import DeleteAnnotationRedaction
def load_from_local_disc():
# Specify the redaction options - remove all annotations
del_red = DeleteAnnotationRedaction()
# Load the document to be redacted from the local disc
with Redactor("./sample.docx") as redactor:
# Apply the redaction
redactor.apply(del_red)
# Save the redacted document in its original format next to the source file
so = SaveOptions()
so.add_suffix = True
so.rasterize_to_pdf = False
so.redacted_file_suffix = "redacted"
result_path = redactor.save(so)
print(f"Document redacted successfully.\nCheck output in {result_path}.")
if __name__ == "__main__":
load_from_local_disc()
```
{{< /tab >}}
{{< tab "sample.docx" >}}
{{< tab-text >}}
`sample.docx` is the sample file used in this example. Click [here](/redaction/python-net/_sample_files/developer-guide/advanced-usage/loading-documents/load-from-local-disc/sample.docx) to download it.
{{< /tab-text >}}
{{< /tab >}}
{{< tab "sample_redacted.docx" >}}
```text
Binary file (DOCX, 13 KB)
```
[Download full output](/redaction/python-net/_output_files/developer-guide/advanced-usage/loading-documents/load-from-local-disc/load_from_local_disc/sample_redacted.docx)
{{< /tab >}}
{{< /tabs >}}
---
## GroupDocs.Redaction for Python via .NET Overview
Path: /redaction/python-net/product-overview/
## What is GroupDocs.Redaction?
GroupDocs.Redaction for Python via .NET is a native Python library that **permanently removes or obscures sensitive content** from documents — across PDF, Microsoft Word, Excel, PowerPoint, and image formats — through a single, format-independent API. It runs entirely on-premise, requires no Microsoft Office or Adobe Acrobat installation, and ships as a pre-built wheel on Windows, Linux, and macOS.
Typical uses include:
- **PII / PHI removal** — strip names, SSNs, emails, and other personal data from a document before it is shared, published, or archived (GDPR, HIPAA, CCPA).
- **Legal & e-discovery redaction** — black out privileged phrases and annotations across every page of a production set.
- **Metadata sanitization** — erase or rewrite author, company, and other hidden metadata that leaks information.
- **Irreversible redaction** — rasterize the cleaned document to a PDF so the removed content can never be recovered.
- **Policy-driven batch redaction** — define a reusable set of redaction rules once and apply it across many documents in a pipeline.
## Key Capabilities
| Capability | Description |
|---|---|
| **Text Redaction** | Replace or black out text matched by an exact phrase (case-sensitive or RTL-aware) or a regular expression. See [Text Redactions]({{< ref "redaction/python-net/developer-guide/basic-usage/text-redactions.md" >}}). |
| **Metadata Redaction** | Erase metadata wholesale or by filter, or rewrite values that match a pattern. See [Metadata Redactions]({{< ref "redaction/python-net/developer-guide/basic-usage/metadata-redactions.md" >}}). |
| **Image Redaction** | Black out a rectangular area of an image or scanned page and clean embedded image metadata. See [Image Redactions]({{< ref "redaction/python-net/developer-guide/basic-usage/image-redactions.md" >}}). |
| **Annotation Redaction** | Rewrite or delete annotations, comments, and notes by pattern. See [Annotation Redactions]({{< ref "redaction/python-net/developer-guide/basic-usage/annotation-redactions.md" >}}). |
| **Page Removal** | Remove whole pages, slides, or worksheets from a document. See [Remove Page Redactions]({{< ref "redaction/python-net/developer-guide/basic-usage/remove-page-redactions.md" >}}). |
| **Rasterization & Saving** | Save in the original format, or rasterize to a PDF (optionally PDF/A) so redactions are irreversible. See [Saving Documents]({{< ref "redaction/python-net/developer-guide/advanced-usage/saving-documents/_index.md" >}}). |
| **Redaction Policies** | Bundle several redactions into a reusable policy and apply it across many documents. See [Use Redaction Policies]({{< ref "redaction/python-net/developer-guide/advanced-usage/use-redaction-policies.md" >}}). |
| **Document Inspection** | Read file type, page count, and size without modifying the document. See [Get File Info]({{< ref "redaction/python-net/developer-guide/basic-usage/get-file-info.md" >}}). |
## Quick Example
Redact every occurrence of a phrase and save the result with just a few lines of code. The example rasterizes the result to a PDF named `sample_redacted.pdf`, so the removed content cannot be recovered:
{{< tabs "product-overview-redact-text" >}}
{{< tab "redact_text.py" >}}
```python
from groupdocs.redaction import Redactor
from groupdocs.redaction.options import SaveOptions
from groupdocs.redaction.redactions import ExactPhraseRedaction, ReplacementOptions
def redact_text():
# Open the document
with Redactor("./sample.docx") as redactor:
# Replace every occurrence of "John Doe" with "[personal]"
redactor.apply(ExactPhraseRedaction("John Doe", ReplacementOptions("[personal]")))
# Rasterize the result to a PDF named sample_redacted.pdf
save_options = SaveOptions()
save_options.add_suffix = True
save_options.rasterize_to_pdf = True
save_options.redacted_file_suffix = "redacted"
redactor.save(save_options)
if __name__ == "__main__":
redact_text()
```
{{< /tab >}}
{{< tab "sample.docx" >}}
{{< tab-text >}}
`sample.docx` is the sample file used in this example. Click [here](/redaction/python-net/_sample_files/product-overview/sample.docx) to download it.
{{< /tab-text >}}
{{< /tab >}}
{{< tab "sample_redacted.pdf" >}}
```text
Binary file (PDF, 1.0 MB)
```
[Download full output](/redaction/python-net/_output_files/product-overview/redact_text/sample_redacted.pdf)
{{< /tab >}}
{{< /tabs >}}
For finer control, apply several redactions and keep the original format with `SaveOptions(rasterize_to_pdf=False)`:
{{< tabs "product-overview-redact-options" >}}
{{< tab "redact_with_options.py" >}}
```python
from groupdocs.redaction import Redactor
from groupdocs.redaction.redactions import ExactPhraseRedaction, RegexRedaction, ReplacementOptions
from groupdocs.redaction.options import SaveOptions
def redact_with_options():
with Redactor("./sample.docx") as redactor:
# Redact a name and any 2+ digit number sequences
redactor.apply(ExactPhraseRedaction("John Doe", ReplacementOptions("[personal]")))
redactor.apply(RegexRedaction(r"\d{2,}", ReplacementOptions("[number]")))
# Keep the original DOCX format instead of rasterizing to PDF
options = SaveOptions()
options.add_suffix = True
options.rasterize_to_pdf = False
options.redacted_file_suffix = "redacted"
redactor.save(options)
if __name__ == "__main__":
redact_with_options()
```
{{< /tab >}}
{{< tab "sample.docx" >}}
{{< tab-text >}}
`sample.docx` is the sample file used in this example. Click [here](/redaction/python-net/_sample_files/product-overview/sample.docx) to download it.
{{< /tab-text >}}
{{< /tab >}}
{{< tab "sample_redacted.docx" >}}
```text
Binary file (DOCX, 16 KB)
```
[Download full output](/redaction/python-net/_output_files/product-overview/redact_with_options/sample_redacted.docx)
{{< /tab >}}
{{< /tabs >}}
## Where to next
1. **Install the package** — [Installation]({{< ref "redaction/python-net/getting-started/installation.md" >}}) walks through PyPI and offline wheel installation for Windows, Linux, and macOS.
2. **Run your first redaction** — [Hello, World!]({{< ref "redaction/python-net/getting-started/hello-world.md" >}}) redacts a document in under five minutes.
3. **Explore runnable examples** — [How to Run Examples]({{< ref "redaction/python-net/getting-started/how-to-run-examples.md" >}}) clones the GitHub repository and runs every documented scenario locally or in Docker.
4. **Use it in depth** — the [Developer Guide]({{< ref "redaction/python-net/developer-guide/_index.md" >}}) covers every API surface with runnable, copy-paste code examples.
5. **Plug it into AI pipelines** — [AI Agents & LLM Integration]({{< ref "redaction/python-net/agents-and-llm-integration.md" >}}) explains the bundled `AGENTS.md`, the MCP server, and machine-readable docs.
---
## Save in original format
Path: /redaction/python-net/save-in-original-format/
The following example demonstrates how to save file in its original format with current date as a suffix:
{{< tabs "code-example-save-in-original-format" >}}
{{< tab "save_in_original_format.py" >}}
```python
from datetime import datetime
from groupdocs.redaction import Redactor
from groupdocs.redaction.options import SaveOptions
from groupdocs.redaction.redactions import ExactPhraseRedaction, ReplacementOptions
def save_in_original_format():
# Specify the redaction options
repl_opt = ReplacementOptions("[personal]")
ex_red = ExactPhraseRedaction("John Doe", repl_opt)
# Load the document to be redacted
with Redactor("./sample.docx") as redactor:
# Apply the redaction
redactor.apply(ex_red)
# Save the redacted document in its original format with the current date as a suffix
so = SaveOptions()
so.add_suffix = True
so.rasterize_to_pdf = False
date_time_str = datetime.now().strftime("%Y-%m-%d %H-%M-%S")
so.redacted_file_suffix = date_time_str
result_path = redactor.save(so)
print(f"Document redacted successfully.\nCheck output in {result_path}.")
if __name__ == "__main__":
save_in_original_format()
```
{{< /tab >}}
{{< tab "sample.docx" >}}
{{< tab-text >}}
`sample.docx` is the sample file used in this example. Click [here](/redaction/python-net/_sample_files/developer-guide/advanced-usage/saving-documents/save-in-original-format/sample.docx) to download it.
{{< /tab-text >}}
{{< /tab >}}
{{< tab "sample_2026-06-11 17-10-50.docx" >}}
```text
Binary file (DOCX, 16 KB)
```
[Download full output](/redaction/python-net/_output_files/developer-guide/advanced-usage/saving-documents/save-in-original-format/save_in_original_format/sample_2026-06-11 17-10-50.docx)
{{< /tab >}}
{{< /tabs >}}
---
## Get file info
Path: /redaction/python-net/get-file-info/
GroupDocs.Redaction provides general document information, which includes:
* FileType
* PageCount
* FileSize
The following code examples demonstrate how to get document information.
## Get file info for a file from local disk
{{< tabs "code-example-get-local-file-info" >}}
{{< tab "get_local_file_info.py" >}}
```python
from groupdocs.redaction import Redactor
def get_local_file_info():
# Load the document from local disk
with Redactor("./sample.docx") as redactor:
# Retrieve general document information
info = redactor.get_document_info()
print(f"File type: {info.file_type}")
print(f"Number of pages: {info.page_count}")
print(f"Document size: {info.size} bytes")
if __name__ == "__main__":
get_local_file_info()
```
{{< /tab >}}
{{< tab "sample.docx" >}}
{{< tab-text >}}
`sample.docx` is the sample file used in this example. Click [here](/redaction/python-net/_sample_files/developer-guide/basic-usage/get-file-info/sample.docx) to download it.
{{< /tab-text >}}
{{< /tab >}}
{{< tab "get-local-file-info.txt" >}}
```text
File type: Microsoft Word Open XML Document (.docx)
Number of pages: 1
Document size: 19370 bytes
```
[Download full output](/redaction/python-net/_output_files/developer-guide/basic-usage/get-file-info/get_local_file_info/get-local-file-info.txt)
{{< /tab >}}
{{< /tabs >}}
## Get file info for a file from Stream
{{< tabs "code-example-get-file-info-from-stream" >}}
{{< tab "get_file_info_from_stream.py" >}}
```python
from groupdocs.redaction import Redactor
def get_file_info_from_stream():
# Open the document as a binary stream
with open("./sample.docx", "rb") as stream:
# Load the document from the stream
with Redactor(stream) as redactor:
# Retrieve general document information
info = redactor.get_document_info()
print(f"File type: {info.file_type}")
print(f"Number of pages: {info.page_count}")
print(f"Document size: {info.size} bytes")
if __name__ == "__main__":
get_file_info_from_stream()
```
{{< /tab >}}
{{< tab "sample.docx" >}}
{{< tab-text >}}
`sample.docx` is the sample file used in this example. Click [here](/redaction/python-net/_sample_files/developer-guide/basic-usage/get-file-info/sample.docx) to download it.
{{< /tab-text >}}
{{< /tab >}}
{{< tab "get-file-info-from-stream.txt" >}}
```text
File type: Microsoft Word Open XML Document (.docx)
Number of pages: 1
Document size: 19370 bytes
```
[Download full output](/redaction/python-net/_output_files/developer-guide/basic-usage/get-file-info/get_file_info_from_stream/get-file-info-from-stream.txt)
{{< /tab >}}
{{< /tabs >}}
---
## Hello, World!
Path: /redaction/python-net/hello-world/
## Introduction
A "Hello, World!" example is often the first step when exploring GroupDocs.Redaction for Python via .NET. It serves as a simple test to confirm that your development environment is correctly set up and that the library is functioning as expected.
## Overview
GroupDocs.Redaction for Python via .NET lets you search, redact, and remove sensitive information from various document formats. A wide range of [supported formats](/redaction/python-net/getting-started/supported-document-formats/) makes it versatile for different use cases.
## How to redact a document
The following steps demonstrate how to redact sensitive information from a document using GroupDocs.Redaction for Python via .NET:
1. Import the `groupdocs.redaction` classes you need.
2. Describe the redaction (here, an exact phrase to replace with a colored box).
3. Instantiate a `Redactor` with the path to the sample document.
4. Apply the redaction.
5. Save the result.
## Complete example
The example below replaces every occurrence of the phrase "John Doe" with a semi-transparent red box and saves the redacted document:
{{< tabs "code-example-hello-world" >}}
{{< tab "hello_world.py" >}}
```python
from groupdocs.redaction import Redactor
from groupdocs.redaction.options import SaveOptions
from groupdocs.redaction.redactions import ExactPhraseRedaction, ReplacementOptions
from groupdocs.pydrawing import Color
def hello_world():
# Draw a semi-transparent red box over every occurrence of "John Doe"
options = ReplacementOptions(Color.from_argb(128, 255, 0, 0))
redaction = ExactPhraseRedaction("John Doe", options)
# Load the document, apply the redaction, and save the result
with Redactor("./sample.docx") as redactor:
redactor.apply(redaction)
save_options = SaveOptions()
save_options.add_suffix = True
save_options.rasterize_to_pdf = True
save_options.redacted_file_suffix = "redacted"
result_path = redactor.save(save_options)
print(f"Document redacted successfully. Output saved to {result_path}.")
if __name__ == "__main__":
hello_world()
```
{{< /tab >}}
{{< tab "sample.docx" >}}
{{< tab-text >}}
`sample.docx` is the sample file used in this example. Click [here](/redaction/python-net/_sample_files/getting-started/hello-world/sample.docx) to download it.
{{< /tab-text >}}
{{< /tab >}}
{{< tab "sample_redacted.pdf" >}}
```text
Binary file (PDF, 1.0 MB)
```
[Download full output](/redaction/python-net/_output_files/getting-started/hello-world/hello_world/sample_redacted.pdf)
{{< /tab >}}
{{< /tabs >}}
This example rasterizes the result to a PDF named `sample_redacted.pdf`, so the redacted content cannot be recovered (`save()` rasterizes to PDF by default; the `redacted_file_suffix` option just controls the output name). To keep the original format instead, set `rasterize_to_pdf = False`.
## Additional resources
This demo references the GroupDocs.Redaction for Python via .NET [code samples](https://github.com/groupdocs-redaction/GroupDocs.Redaction-for-Python-via-.NET/).
---
## Load from Stream
Path: /redaction/python-net/load-from-stream/
As an alternative to a local file, [Redactor](https://reference.groupdocs.com/redaction/python-net/groupdocs.redaction/redactor/) can open a document from stream.
The following example demonstrates how to load and redact a document using Stream:
{{< tabs "code-example-load-from-stream" >}}
{{< tab "load_from_stream.py" >}}
```python
from groupdocs.redaction import Redactor
from groupdocs.redaction.options import RasterizationOptions
from groupdocs.redaction.redactions import DeleteAnnotationRedaction
def load_from_stream():
# Specify the redaction options - remove all annotations
del_red = DeleteAnnotationRedaction()
# Load the document as a stream to be redacted
with open("./sample.docx", "rb") as stream_in:
with Redactor(stream_in) as redactor:
# Apply the redaction
redactor.apply(del_red)
# Save the redacted document to a stream as a rasterized PDF
with open("./redacted-sample.pdf", "wb") as stream_out:
ro = RasterizationOptions()
redactor.save(stream_out, ro)
print("Document redacted successfully.")
if __name__ == "__main__":
load_from_stream()
```
{{< /tab >}}
{{< tab "sample.docx" >}}
{{< tab-text >}}
`sample.docx` is the sample file used in this example. Click [here](/redaction/python-net/_sample_files/developer-guide/advanced-usage/loading-documents/load-from-stream/sample.docx) to download it.
{{< /tab-text >}}
{{< /tab >}}
{{< tab "redacted-sample.pdf" >}}
```text
Binary file (PDF, 1.2 MB)
```
[Download full output](/redaction/python-net/_output_files/developer-guide/advanced-usage/loading-documents/load-from-stream/load_from_stream/redacted-sample.pdf)
{{< /tab >}}
{{< /tabs >}}
---
## Save in rasterized PDF
Path: /redaction/python-net/save-in-rasterized-pdf/
The following example demonstrates how to save the document as a rasterized PDF file:
{{< tabs "code-example-save-in-rasterized-pdf" >}}
{{< tab "save_in_rasterized_pdf.py" >}}
```python
from groupdocs.redaction import Redactor
from groupdocs.redaction.options import SaveOptions
from groupdocs.redaction.redactions import ExactPhraseRedaction, ReplacementOptions
def save_in_rasterized_pdf():
# Specify the redaction options
repl_opt = ReplacementOptions("[personal]")
ex_red = ExactPhraseRedaction("John Doe", repl_opt)
# Load the document to be redacted
with Redactor("./sample.docx") as redactor:
# Apply the redaction
redactor.apply(ex_red)
# Save the redacted document as a rasterized PDF
so = SaveOptions()
so.add_suffix = False
so.rasterize_to_pdf = True
result_path = redactor.save(so)
print(f"Document redacted successfully.\nCheck output in {result_path}.")
if __name__ == "__main__":
save_in_rasterized_pdf()
```
{{< /tab >}}
{{< tab "sample.docx" >}}
{{< tab-text >}}
`sample.docx` is the sample file used in this example. Click [here](/redaction/python-net/_sample_files/developer-guide/advanced-usage/saving-documents/save-in-rasterized-pdf/sample.docx) to download it.
{{< /tab-text >}}
{{< /tab >}}
{{< tab "sample.pdf" >}}
```text
Binary file (PDF, 1024 KB)
```
[Download full output](/redaction/python-net/_output_files/developer-guide/advanced-usage/saving-documents/save-in-rasterized-pdf/save_in_rasterized_pdf/sample.pdf)
{{< /tab >}}
{{< /tabs >}}
---
## Supported Document Formats
Path: /redaction/python-net/supported-document-formats/
## Supported File Formats
The following table indicates the file formats, supported by GroupDocs.Redaction for Python via .NET.
| Format | Description | Document body | Metadata | Annotations(comments) | Remarks | Embedded images | OCR | Remove Page | Page Filters |
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
| [PDF](https://docs.fileformat.com/pdf/) | Saves the document as PDF (Adobe Portable Document) format |  |  |  | |  |  |  |  |
| [DOC](https://docs.fileformat.com/word-processing/doc) | Microsoft Word 97 - 2007 Document. |  |  |  | |  |  |  | |
| [DOT](https://docs.fileformat.com/word-processing/dot/) | Microsoft Word 97 - 2007 Template. |  |  |  | |  |  |  | |
| [DOCX](https://docs.fileformat.com/word-processing/docx/) | Office Open XML WordprocessingML Document (macro-free) |  |  |  | |  |  |  | |
| [DOCM](https://docs.fileformat.com/word-processing/docm/) | Office Open XML WordprocessingML Macro-Enabled Document |  |  |  | |  |  |  | |
| [DOTX](https://docs.fileformat.com/word-processing/dotx/) | Office Open XML WordprocessingML Template (macro-free) |  |  |  | |  |  |  | |
| [DOTM](https://docs.fileformat.com/word-processing/dotm/) | Office Open XML WordprocessingML Macro-Enabled Template. |  |  |  | |  |  |  | |
| [RTF](https://docs.fileformat.com/word-processing/rtf/) | RTF format. |  |  |  | |  |  | |
| [XLSX](https://docs.fileformat.com/spreadsheet/xlsx/) | OOXML 2007-2010 |  |  |  | | | |  | |
| [XLSM](https://docs.fileformat.com/spreadsheet/xlsm/) | OOXML Macro Enabled Workbook |  |  |  | | | |  | |
| [XLTX](https://docs.fileformat.com/spreadsheet/xltx/) | OOXML Workbook Template |  |  |  | | | |  | |
| [XLTM](https://docs.fileformat.com/spreadsheet/xltm/) | OOXML Macro Enabled Workbook Template |  |  |  | | | |  | |
| [XLS](https://docs.fileformat.com/spreadsheet/xls/) | Excel Workbook 97-2003 |  |  |  | | | |  | |
| [XLT](https://docs.fileformat.com/spreadsheet/xlt/) | Excel Workbook Template 97-2003 |  |  |  | | | |  | |
| [CSV](https://docs.fileformat.com/spreadsheet/csv/) | CSV (Comma Separated Value) file. |  |  |  | | | | | |
| [PPTX](https://docs.fileformat.com/presentation/pptx/) | OOXML Microsoft PowerPoint Presentations format |  |  |  | |  |  |  |  |
| [PPT](https://docs.fileformat.com/presentation/ppt/) | PowerPoint Presentation 97-2003 |  |  |  | |  |  |  |  |
| [PPSX](https://docs.fileformat.com/presentation/ppsx/) | PowerPoint Open XML |  |  |  | |  |  |  |  |
| [POT](https://docs.fileformat.com/presentation/pot/) | PowerPoint template files |  |  |  | |  |  |  |  |
| [PPS](https://docs.fileformat.com/presentation/pps/) | Microsoft PowerPoint 97-2003 Slide Show |  |  |  | |  |  |  |  |
| [PPTM](https://docs.fileformat.com/presentation/pptm/) | Microsoft PowerPoint Open XML Macro-Enabled Presentation file |  |  |  | |  |  |  |  |
| [PPSM](https://docs.fileformat.com/presentation/ppsm/) | Microsoft PowerPoint Open XML Macro-Enabled Slide Show file |  |  |  | |  |  |  |  |
| [POTM](https://docs.fileformat.com/presentation/potm/) | Microsoft PowerPoint template |  |  |  | |  |  |  |  |
| [JPEG](https://docs.fileformat.com/image/jpeg/) | The image file format was standardized by the Joint Photographic Experts Group. |  |  | | | |  | |  |
| [TIF/TIFF](https://docs.fileformat.com/image/tiff/) | Tagged Image File Format |  |  | | | |  |  |  |
| [PNG](https://docs.fileformat.com/image/png/) | Portable Network Graphics Image |  |  | | | |  | |  |
| [BMP](https://docs.fileformat.com/image/bmp/) | Bitmap Image Files |  |  | | | |  | |  |
| [GIF](https://docs.fileformat.com/image/gif/) | Graphical Interchange Format Image |  |  | | | | |  | |
| [DJVU](https://docs.fileformat.com/image/djvu/) | DjVu Document Format |  | | | | | |  | |
{{< alert style="tip" >}}
**Can’t find your file format?**
We’re here to help! Please post a request on our [Free Support Forum](https://forum.groupdocs.com/c/redaction/33), and our team will assist you.
{{< /alert >}}
---
## Use PDF redaction filters
Path: /redaction/python-net/use-pdf-redaction-filters/
You can combine [PageRangeFilter](https://reference.groupdocs.com/redaction/python-net/groupdocs.redaction.redactions/pagerangefilter/) and [PageAreaFilter](https://reference.groupdocs.com/redaction/python-net/groupdocs.redaction.redactions/pageareafilter/) filters in one set in order to set the scope of redaction to an area on a specific page. You have to set an array of instances to **Filters** property of the [ReplacementOptions](https://reference.groupdocs.com/redaction/python-net/groupdocs.redaction.redactions/replacementoptions/).
The following example demonstrates how to apply redaction to the bottom half of the last page in a PDF document.
{{< tabs "code-example-use-pdf-redaction-filters" >}}
{{< tab "use_pdf_redaction_filters.py" >}}
```python
from groupdocs.redaction import Redactor
from groupdocs.redaction.options import SaveOptions
from groupdocs.redaction.redactions import (
ExactPhraseRedaction,
ReplacementOptions,
PageRangeFilter,
PageAreaFilter,
PageSeekOrigin,
)
from groupdocs.pydrawing import Point, Size
def use_pdf_redaction_filters():
# Load the document to be redacted
with Redactor("./multipage_sample.pdf") as redactor:
# Get the actual size information for the last page
doc_info = redactor.get_document_info()
last_page = doc_info.pages[doc_info.page_count - 1]
# Define the redaction area start point
sample_point = Point(0, int(last_page.height / 2))
# Define the redaction area size
sample_size = Size(last_page.width, int(last_page.height / 2))
# Combine page-range and page-area filters to scope the redaction
filters = [
PageRangeFilter(PageSeekOrigin.END, 0, 1),
PageAreaFilter(sample_point, sample_size),
]
# Specify the redaction options with the filters
repl_opt = ReplacementOptions("[secret]")
repl_opt.filters = filters
ex_red = ExactPhraseRedaction("bibliography", False, repl_opt)
# Apply the redaction
redactor.apply(ex_red)
# Save the redacted document
save_options = SaveOptions()
save_options.add_suffix = True
save_options.rasterize_to_pdf = True
save_options.redacted_file_suffix = "redacted"
result_path = redactor.save(save_options)
print(f"Document redacted successfully.\nCheck output in {result_path}.")
if __name__ == "__main__":
use_pdf_redaction_filters()
```
{{< /tab >}}
{{< tab "multipage_sample.pdf" >}}
{{< tab-text >}}
`multipage_sample.pdf` is the sample file used in this example. Click [here](/redaction/python-net/_sample_files/developer-guide/advanced-usage/using-redaction-filters/use-pdf-redaction-filters/multipage_sample.pdf) to download it.
{{< /tab-text >}}
{{< /tab >}}
{{< tab "multipage_sample_redacted.pdf" >}}
```text
Binary file (PDF, 2.5 MB)
```
[Download full output](/redaction/python-net/_output_files/developer-guide/advanced-usage/using-redaction-filters/use-pdf-redaction-filters/use_pdf_redaction_filters/multipage_sample_redacted.pdf)
{{< /tab >}}
{{< /tabs >}}
---
## Load password-protected file
Path: /redaction/python-net/load-password-protected-file/
In order to open password-protected documents, you have to pass your password to [LoadOptions](https://reference.groupdocs.com/redaction/python-net/groupdocs.redaction.options/loadoptions/) class constructor or assign it to its [Password](https://reference.groupdocs.com/redaction/python-net/groupdocs.redaction.options/loadoptions/password/) property of an instance of [LoadOptions](https://reference.groupdocs.com/redaction/python-net/groupdocs.redaction.options/loadoptions/) class:
{{< tabs "code-example-load-password-protected-file" >}}
{{< tab "load_password_protected_file.py" >}}
```python
from groupdocs.redaction import Redactor
from groupdocs.redaction.options import SaveOptions, LoadOptions
from groupdocs.redaction.redactions import ExactPhraseRedaction, ReplacementOptions
def load_password_protected_file():
# Specify the load options with the document password
load_opt = LoadOptions("mypassword")
# Specify the redaction options
repl_opt = ReplacementOptions("[personal]")
ex_red = ExactPhraseRedaction("John Doe", repl_opt)
# Load the password-protected document to be redacted
with Redactor("./protected.docx", load_opt) as redactor:
# Apply the redaction
redactor.apply(ex_red)
# Save the redacted document in its original format
so = SaveOptions()
so.add_suffix = True
so.rasterize_to_pdf = False
so.redacted_file_suffix = "redacted"
result_path = redactor.save(so)
print(f"Document redacted successfully.\nCheck output in {result_path}.")
if __name__ == "__main__":
load_password_protected_file()
```
{{< /tab >}}
{{< tab "protected.docx" >}}
{{< tab-text >}}
`protected.docx` is the sample file used in this example. Click [here](/redaction/python-net/_sample_files/developer-guide/advanced-usage/loading-documents/load-password-protected-file/protected.docx) to download it.
{{< /tab-text >}}
{{< /tab >}}
{{< tab "protected_redacted.docx" >}}
```text
Binary file (DOCX, 16 KB)
```
[Download full output](/redaction/python-net/_output_files/developer-guide/advanced-usage/loading-documents/load-password-protected-file/load_password_protected_file/protected_redacted.docx)
{{< /tab >}}
{{< /tabs >}}
---
## Save overwriting original file
Path: /redaction/python-net/save-overwriting-original-file/
The following example demonstrates how to save the redacted document, replacing an original file:
{{< tabs "code-example-save-overwriting-original-file" >}}
{{< tab "save_overwriting_original_file.py" >}}
```python
from groupdocs.redaction import Redactor, RedactionStatus
from groupdocs.redaction.options import SaveOptions
from groupdocs.redaction.redactions import ExactPhraseRedaction, ReplacementOptions
from groupdocs.pydrawing import Color
def save_overwriting_original_file():
# Define the color of redaction
color = Color.from_argb(255, 220, 20, 60)
# Specify the redaction options
repl_opt = ReplacementOptions(color)
ex_red = ExactPhraseRedaction("John Doe", repl_opt)
# Load the document to be redacted
with Redactor("./sample.docx") as redactor:
# Apply the redaction
result = redactor.apply(ex_red)
if result.status != RedactionStatus.FAILED:
# Save the redacted document, overwriting the original file
so = SaveOptions()
so.add_suffix = False
so.rasterize_to_pdf = False
result_path = redactor.save(so)
print(f"Document redacted successfully.\nCheck output in {result_path}")
else:
print("Redaction failed!")
if __name__ == "__main__":
save_overwriting_original_file()
```
{{< /tab >}}
{{< tab "sample.docx" >}}
```text
Binary file (DOCX, 17 KB)
```
[Download full output](/redaction/python-net/_output_files/developer-guide/advanced-usage/saving-documents/save-overwriting-original-file/save_overwriting_original_file/sample.docx)
{{< /tab >}}
{{< /tabs >}}
---
## Redaction basics
Path: /redaction/python-net/redaction-basics/
GroupDocs.Redaction supports an effective set of document redaction features. It allows to apply redactions for [text]({{< ref "redaction/python-net/developer-guide/basic-usage/text-redactions.md" >}}), [metadata]({{< ref "redaction/python-net/developer-guide/basic-usage/metadata-redactions.md" >}}), [annotations]({{< ref "redaction/python-net/developer-guide/basic-usage/annotation-redactions.md" >}}), [images]({{< ref "redaction/python-net/developer-guide/basic-usage/image-redactions.md" >}}).
Wide range of document formats is supported, such as: PDF, DOC, DOCX, PPT, PPTX, XLS, XLSX and others. See full list of supported formats at [supported document formats]({{< ref "redaction/python-net/getting-started/supported-document-formats.md" >}}) article
## Redaction types
GroupDocs.Redaction comes with the following redaction types:
| Type | Description | Classes |
| --- | --- | --- |
| [Text]({{< ref "redaction/python-net/developer-guide/basic-usage/text-redactions.md" >}}) | Replaces or hides with color block a portion of text within document body | [ExactPhraseRedaction](https://reference.groupdocs.com/redaction/python-net/groupdocs.redaction.redactions/exactphraseredaction/), [RegexRedaction](https://reference.groupdocs.com/redaction/python-net/groupdocs.redaction.redactions/regexredaction/) |
| [Metadata]({{< ref "redaction/python-net/developer-guide/basic-usage/metadata-redactions.md" >}}) | Replace metadata values with empty ones or redacts metadata texts | [EraseMetadataRedaction](https://reference.groupdocs.com/redaction/python-net/groupdocs.redaction.redactions/erasemetadataredaction/), [MetadataSearchRedaction](https://reference.groupdocs.com/redaction/python-net/groupdocs.redaction.redactions/metadatasearchredaction/) |
| [Annotations]({{< ref "redaction/python-net/developer-guide/basic-usage/annotation-redactions.md" >}}) | Deletes annotations from document or redacts its texts | [DeleteAnnotationRedaction](https://reference.groupdocs.com/redaction/python-net/groupdocs.redaction.redactions/deleteannotationredaction/), [AnnotationRedaction](https://reference.groupdocs.com/redaction/python-net/groupdocs.redaction.redactions/annotationredaction/) |
| [Images]({{< ref "redaction/python-net/developer-guide/basic-usage/image-redactions.md" >}}) | Replaces specific area of an image with a colored box | [ImageAreaRedaction](https://reference.groupdocs.com/redaction/python-net/groupdocs.redaction.redactions/imagearearedaction/) |
| [Pages]({{< ref "redaction/python-net/developer-guide/basic-usage/remove-page-redactions.md" >}}) | Removes specific range of pages (slides, worksheets, etc.) | [RemovePageRedaction](https://reference.groupdocs.com/redaction/python-net/groupdocs.redaction.redactions/removepageredaction/) |
## Apply redaction
Applying redaction to a document is done through [Redactor.Apply](https://reference.groupdocs.com/redaction/python-net/groupdocs.redaction/redactor/apply/) method. As a result, you receive [RedactorChangeLog](https://reference.groupdocs.com/redaction/python-net/groupdocs.redaction/redactorchangelog/) instance, containing a log entry for each redaction applied. The entry contains reference to [Redacton](https://reference.groupdocs.com/redaction/python-net/groupdocs.redaction/redaction/) instance including its options, status of the operation (see below) and textual descriptions when applicable. If at least one redaction failed, you will see [Status == RedactionStatus.Failed](https://reference.groupdocs.com/redaction/python-net/groupdocs.redaction/redactionstatus/):
{{< tabs "code-example-apply-redaction" >}}
{{< tab "apply_redaction.py" >}}
```python
from groupdocs.redaction import Redactor, RedactionStatus
from groupdocs.redaction.options import SaveOptions
from groupdocs.redaction.redactions import ExactPhraseRedaction, ReplacementOptions
def apply_redaction():
# Specify the redaction options
repl_opt = ReplacementOptions("[personal]")
ex_red = ExactPhraseRedaction("John Doe", repl_opt)
# Load the document to be redacted
with Redactor("./sample.docx") as redactor:
# Apply the redaction
result = redactor.apply(ex_red)
if result.status != RedactionStatus.FAILED:
# Save the redacted document next to the source file
so = SaveOptions()
so.add_suffix = True
so.rasterize_to_pdf = False
so.redacted_file_suffix = "redacted"
redactor.save(so)
if __name__ == "__main__":
apply_redaction()
```
{{< /tab >}}
{{< tab "sample.docx" >}}
{{< tab-text >}}
`sample.docx` is the sample file used in this example. Click [here](/redaction/python-net/_sample_files/developer-guide/basic-usage/redaction-basics/sample.docx) to download it.
{{< /tab-text >}}
{{< /tab >}}
{{< tab "sample_redacted.docx" >}}
```text
Binary file (DOCX, 16 KB)
```
[Download full output](/redaction/python-net/_output_files/developer-guide/basic-usage/redaction-basics/apply_redaction/sample_redacted.docx)
{{< /tab >}}
{{< /tabs >}}
All possible statuses of the [RedactionStatus](https://reference.groupdocs.com/redaction/python-net/groupdocs.redaction/redactionstatus/) enumeration are listed in this table:
| Status | Description | Possible reasons |
| --- | --- | --- |
| *Applied* | Redaction was fully and successfully applied | All operations within redaction process were successfully applied |
| *PartiallyApplied* | Redaction was applied only to a part of its matches | 1) Trial limitations for replacements were exceeded2) At least one change was rejected by user |
| *Skipped* | Redaction was skipped (not applied) | 1) Trial limitations for redactions were exceeded2) Redaction cannot be applied to this type of document3) All replacements were rejected by user and no changes were made |
| *Failed* | Redaction failed with exception | An exception occurred in process of redaction |
For detailed information you have to iterate through redaction log entries in [RedactorChangeLog.RedactionLog](https://reference.groupdocs.com/redaction/python-net/groupdocs.redaction/redactorchangelog/redaction_log/) and check for [ErrorMessage](https://reference.groupdocs.com/redaction/python-net/groupdocs.redaction/redactionresult/error_message/) property of any items with status other than *Applied*:
```python
result = redactor.apply(redaction)
if result.status != RedactionStatus.FAILED:
# By default, the redacted document is saved in PDF format
save_options = SaveOptions()
save_options.add_suffix = True
save_options.rasterize_to_pdf = True
save_options.redacted_file_suffix = "redacted"
result_path = redactor.save(save_options)
print(f"Document redacted successfully.\nCheck output in {result_path}")
else:
# Dump all failed or skipped redactions
print("Redaction failed!")
for log_entry in result.redaction_log:
if log_entry.result.status != RedactionStatus.APPLIED:
print(f"Status is {log_entry.result.status}, details: {log_entry.result.error_message}")
```
## Apply multiple redactions
You can apply as much redactions as you need in a single call to [Redactor.Apply](https://reference.groupdocs.com/redaction/python-net/groupdocs.redaction/redactor/apply/) method, since its overload accepts an array of redactions and redaction policy. In this case, redactions will be applied in the same order as they appear in the array. As an alternative to specifying redaction sets in your code, you can create an XML file with redaction policy, as described [here]({{< ref "redaction/python-net/developer-guide/advanced-usage/use-redaction-policies.md" >}}).
{{< tabs "code-example-apply-multiple-redactions" >}}
{{< tab "apply_multiple_redactions.py" >}}
```python
from groupdocs.redaction import Redactor, RedactionStatus
from groupdocs.redaction.options import SaveOptions
from groupdocs.redaction.redactions import (
ExactPhraseRedaction,
RegexRedaction,
ReplacementOptions,
DeleteAnnotationRedaction,
EraseMetadataRedaction,
MetadataFilters,
)
from groupdocs.pydrawing import Color
def apply_multiple_redactions():
# Define the color of the redaction box
color = Color.from_argb(255, 220, 20, 60)
# Provide a list of redactions to apply in order
redaction_list = [
ExactPhraseRedaction("John Doe", ReplacementOptions("[Client]")),
RegexRedaction("Redaction", ReplacementOptions("[Product]")),
RegexRedaction("\\d{2}\\s*\\d{2}[^\\d]*\\d{6}", ReplacementOptions(color)),
DeleteAnnotationRedaction(),
EraseMetadataRedaction(MetadataFilters.ALL),
]
# Load the document to be redacted
with Redactor("./sample.docx") as redactor:
# Apply the list of redactions
result = redactor.apply(redaction_list)
if result.status != RedactionStatus.FAILED:
# By default, the redacted document is saved in PDF format
save_options = SaveOptions()
save_options.add_suffix = True
save_options.rasterize_to_pdf = True
save_options.redacted_file_suffix = "redacted"
redactor.save(save_options)
else:
# Dump all failed or skipped redactions
print("Redaction failed!")
for log_entry in result.redaction_log:
if log_entry.result.status != RedactionStatus.APPLIED:
print(f"Status is {log_entry.result.status}, details: {log_entry.result.error_message}")
if __name__ == "__main__":
apply_multiple_redactions()
```
{{< /tab >}}
{{< tab "sample.docx" >}}
{{< tab-text >}}
`sample.docx` is the sample file used in this example. Click [here](/redaction/python-net/_sample_files/developer-guide/basic-usage/redaction-basics/sample.docx) to download it.
{{< /tab-text >}}
{{< /tab >}}
{{< tab "sample_redacted.pdf" >}}
```text
Binary file (PDF, 1.2 MB)
```
[Download full output](/redaction/python-net/_output_files/developer-guide/basic-usage/redaction-basics/apply_multiple_redactions/sample_redacted.pdf)
{{< /tab >}}
{{< /tabs >}}
---
## Save with default options
Path: /redaction/python-net/save-with-default-options/
The simplest way to save the document is it provide no parameters to [Save](https://reference.groupdocs.com/redaction/python-net/groupdocs.redaction/redactor/save/) method. In this case the document will be rasterized to PDF and will have the same name as the original one except its extension (.PDF). The PDF file will be overwritten.
The following example demonstrates usage of [Save()](https://reference.groupdocs.com/redaction/python-net/groupdocs.redaction/redactor/save/) method with default options.
{{< tabs "code-example-save-with-default-options" >}}
{{< tab "save_with_default_options.py" >}}
```python
from groupdocs.redaction import Redactor
from groupdocs.redaction.options import SaveOptions
from groupdocs.redaction.redactions import ExactPhraseRedaction, ReplacementOptions
def save_with_default_options():
# Specify the redaction options
repl_opt = ReplacementOptions("[personal]")
ex_red = ExactPhraseRedaction("John Doe", repl_opt)
# Load the document to be redacted
with Redactor("./sample.docx") as redactor:
# Apply the redaction
redactor.apply(ex_red)
# Save the document with default options (convert pages into images, save as PDF)
save_options = SaveOptions()
save_options.add_suffix = True
save_options.rasterize_to_pdf = True
save_options.redacted_file_suffix = "redacted"
result_path = redactor.save(save_options)
print(f"Document redacted successfully.\nCheck output in {result_path}.")
if __name__ == "__main__":
save_with_default_options()
```
{{< /tab >}}
{{< tab "sample.docx" >}}
{{< tab-text >}}
`sample.docx` is the sample file used in this example. Click [here](/redaction/python-net/_sample_files/developer-guide/advanced-usage/saving-documents/save-with-default-options/sample.docx) to download it.
{{< /tab-text >}}
{{< /tab >}}
{{< tab "sample_redacted.pdf" >}}
```text
Binary file (PDF, 1024 KB)
```
[Download full output](/redaction/python-net/_output_files/developer-guide/advanced-usage/saving-documents/save-with-default-options/save_with_default_options/sample_redacted.pdf)
{{< /tab >}}
{{< /tabs >}}
---
## Showcases
Path: /redaction/python-net/showcases/
{{< alert style="info" >}}Want to try GroupDocs.Redaction for Python via .NET by yourself? Explore the Python code examples, the real-world use cases below, and the free online demonstration to learn more about the document redaction features.{{< /alert >}}
## GitHub Examples
To get started with GroupDocs.Redaction for Python via .NET, explore the runnable code examples on GitHub. The repository provides standalone scripts that showcase every documented capability — text, metadata, image-area, annotation, and page redactions, as well as loading, saving, rasterizing to PDF, and reusable policies.
[GroupDocs.Redaction for Python via .NET GitHub Repository](https://github.com/groupdocs-redaction/GroupDocs.Redaction-for-Python-via-.NET)
See [How to Run Examples]({{< ref "redaction/python-net/getting-started/how-to-run-examples.md" >}}) to set up the project and run everything locally, and the [Developer Guide]({{< ref "redaction/python-net/developer-guide/_index.md" >}}) for step-by-step explanations.
## Use cases
GroupDocs.Redaction fits a wide range of document-sanitization scenarios:
- **GDPR and PII removal** — strip personally identifiable information such as names, e-mail addresses, phone numbers, and national ID numbers from documents before they are stored, shared, or published. Regular-expression text redaction combined with metadata erasure removes both visible and hidden personal data. See [Text Redactions]({{< ref "redaction/python-net/developer-guide/basic-usage/text-redactions.md" >}}) and [Metadata Redactions]({{< ref "redaction/python-net/developer-guide/basic-usage/metadata-redactions.md" >}}).
- **Legal and e-discovery redaction** — black out privileged or confidential passages in evidence and case files, delete reviewer comments and annotations, and remove pages that should not be disclosed. Rasterizing the result to PDF guarantees the hidden text cannot be recovered. See [Annotation Redactions]({{< ref "redaction/python-net/developer-guide/basic-usage/annotation-redactions.md" >}}) and [Remove Page Redactions]({{< ref "redaction/python-net/developer-guide/basic-usage/remove-page-redactions.md" >}}).
- **Sharing scrubbed PDFs** — produce a sanitized, flattened PDF whose pages are raster images, carrying no searchable text and no original metadata, ready to hand to clients, contractors, or the public. Optional PDF/A compliance suits long-term archival. See [Save in Rasterized PDF]({{< ref "redaction/python-net/developer-guide/advanced-usage/saving-documents/save-in-rasterized-pdf.md" >}}).
- **Batch compliance pipelines** — bundle a standard set of redactions into a reusable policy and apply it consistently across thousands of documents in an automated workflow. See [Use Redaction Policies]({{< ref "redaction/python-net/developer-guide/advanced-usage/use-redaction-policies.md" >}}).
## Online Demo
To experience GroupDocs.Redaction without any installation, try the free online redaction app. It lets you upload a document, redact sensitive content, and download the cleaned result right in your browser:
[Free Online Document Redaction App](https://products.groupdocs.app/redaction)
The online demo is a convenient way to evaluate the library's capabilities in a real-world environment and decide whether it fits your document-sanitization needs.
---
## Use redaction policies
Path: /redaction/python-net/use-redaction-policies/
If you have a corporate sensitive data removal policy as a list of redaction rules, you don't need to specify them in your code. You can specify an XML document with a list of pre-configured redactions.
Below is an example of redaction policy XML file (code properties mapping is obvious):
**RedactionPolicy.xml**
```xml
```
You can use RedactionPolicy.save() method to create XML documents of this structure, configuring redactions in runtime.
The following example demonstrates how to save a [RedactionPolicy](https://reference.groupdocs.com/redaction/python-net/groupdocs.redaction/redactionpolicy/) to an XML file.
{{< tabs "code-example-create-redaction-policy" >}}
{{< tab "create_redaction_policy.py" >}}
```python
from groupdocs.redaction import RedactionPolicy
from groupdocs.redaction.redactions import (
ExactPhraseRedaction,
ReplacementOptions,
RegexRedaction,
DeleteAnnotationRedaction,
EraseMetadataRedaction,
MetadataFilters,
)
from groupdocs.pydrawing import Color
def create_redaction_policy():
# Define the color of redaction
color = Color.from_argb(255, 220, 20, 60)
# Configure the redactions
redactions = [
ExactPhraseRedaction("Redaction", ReplacementOptions("[Product]")),
RegexRedaction("\\d{2}\\s*\\d{2}[^\\d]*\\d{6}", ReplacementOptions(color)),
DeleteAnnotationRedaction(),
EraseMetadataRedaction(MetadataFilters.ALL),
]
# Create the policy
policy = RedactionPolicy(redactions)
# Save the redaction policy to an XML file
policy.save("./sample_policy.xml")
print("Redactions policy saved to ./sample_policy.xml")
if __name__ == "__main__":
create_redaction_policy()
```
{{< /tab >}}
{{< tab "sample_policy.xml" >}}
```text
```
[Download full output](/redaction/python-net/_output_files/developer-guide/advanced-usage/use-redaction-policies/create_redaction_policy/sample_policy.xml)
{{< /tab >}}
{{< /tabs >}}
You can have as many policies as you need, loading them to redact your documents.
The example below loads a redaction policy from an XML file and applies every rule it contains to a document in a single `apply` call:
{{< tabs "code-example-use-redaction-policy" >}}
{{< tab "use_redaction_policy.py" >}}
```python
from groupdocs.redaction import Redactor, RedactionPolicy
from groupdocs.redaction.options import SaveOptions
def use_redaction_policy():
# Load the redaction policy from an XML file
policy = RedactionPolicy.load("./redaction_policy.xml")
# Load the document and apply the whole policy in one call
with Redactor("./sample.docx") as redactor:
redactor.apply(policy)
# Keep the original format and append a suffix to the output name
save_options = SaveOptions()
save_options.add_suffix = True
save_options.rasterize_to_pdf = False
save_options.redacted_file_suffix = "redacted"
result_path = redactor.save(save_options)
print(f"Redaction policy applied. Output saved to {result_path}.")
if __name__ == "__main__":
use_redaction_policy()
```
{{< /tab >}}
{{< tab "redaction_policy.xml" >}}
{{< tab-text >}}
`redaction_policy.xml` is the policy file used in this example. Click [here](/redaction/python-net/_sample_files/developer-guide/advanced-usage/use-redaction-policies/redaction_policy.xml) to download it.
{{< /tab-text >}}
{{< /tab >}}
{{< tab "sample.docx" >}}
{{< tab-text >}}
`sample.docx` is the document redacted in this example. Click [here](/redaction/python-net/_sample_files/developer-guide/advanced-usage/use-redaction-policies/sample.docx) to download it.
{{< /tab-text >}}
{{< /tab >}}
{{< tab "sample_redacted.docx" >}}
```text
Binary file (DOCX, 16 KB)
```
[Download full output](/redaction/python-net/_output_files/developer-guide/advanced-usage/use-redaction-policies/use_redaction_policy/sample_redacted.docx)
{{< /tab >}}
{{< /tabs >}}
---
## Licensing and evaluation
Path: /redaction/python-net/licensing-and-subscription/
To explore the system effectively, you may want immediate access to the API. GroupDocs.Redaction simplifies this by offering various purchase plans, along with a Free Trial and a 30-day Temporary License for evaluation.
{{< alert style="info" >}}
To learn more about licensing options, purchasing, and evaluation policies, refer to the [Purchase Policies and FAQ](https://purchase.groupdocs.com/policies) section.
{{< /alert >}}
## Purchased License
After purchasing GroupDocs.Redaction for Python via .NET, you will receive a license file that unlocks the full functionality of the API. A few rules apply:
- Apply the license **only once** per process, in your start-up code.
- Apply it **before** constructing any `Redactor` or other GroupDocs.Redaction object.
- A license can be applied from a file path, from a binary stream (handy when the license is an embedded resource), or as a [Metered License](https://purchase.groupdocs.com/faqs/licensing/metered/) that bills by usage.
Use the [set_license](https://reference.groupdocs.com/redaction/python-net/groupdocs.redaction/license/set_license/) method to license the component. Calling it more than once is harmless — it simply wastes a little processor time.
### Set a license from a file
The example below applies a license from a file path. It reads the path from the `GROUPDOCS_LIC_PATH` environment variable and falls back to a local `GroupDocs.Redaction.lic` file:
{{< tabs "code-example-set-license-from-file" >}}
{{< tab "set_license_from_file.py" >}}
```python
import os
from groupdocs.redaction import License
def set_license_from_file():
# Resolve the license path from the environment, with a local fallback
license_path = os.environ.get("GROUPDOCS_LIC_PATH", "./GroupDocs.Redaction.lic")
# Apply the license before using any redaction features
if os.path.exists(license_path):
License().set_license(license_path)
print("License set successfully.")
else:
print("License file not found. Running in evaluation mode.")
if __name__ == "__main__":
set_license_from_file()
```
{{< /tab >}}
{{< /tabs >}}
### Set a license from a stream
You can also apply a license from any readable binary stream — useful when the license ships as an embedded resource:
{{< tabs "code-example-set-license-from-stream" >}}
{{< tab "set_license_from_stream.py" >}}
```python
import os
from groupdocs.redaction import License
def set_license_from_stream():
# Resolve the license path from the environment, with a local fallback
license_path = os.environ.get("GROUPDOCS_LIC_PATH", "./GroupDocs.Redaction.lic")
# Apply the license from an open binary stream
if os.path.exists(license_path):
with open(license_path, "rb") as stream:
License().set_license(stream)
print("License set successfully.")
else:
print("License file not found. Running in evaluation mode.")
if __name__ == "__main__":
set_license_from_stream()
```
{{< /tab >}}
{{< /tabs >}}
### Set a metered license
A Metered License lets you pay for what you use. Set the public and private keys with [set_metered_key](https://reference.groupdocs.com/redaction/python-net/groupdocs.redaction/metered/set_metered_key/) before using the API, then query consumption at any time:
{{< tabs "code-example-set-metered-license" >}}
{{< tab "set_metered_license.py" >}}
```python
from groupdocs.redaction import Metered
def set_metered_license():
# Replace these placeholders with your real metered public/private keys
public_key = "*****"
private_key = "*****"
# Skip the call until real keys are supplied (placeholder keys are rejected)
if "*" in public_key or "*" in private_key:
print("Provide real metered keys to enable metered licensing.")
return
# Apply the metered keys before using any redaction features
Metered().set_metered_key(public_key, private_key)
# Query the current metered consumption
quantity = Metered().get_consumption_quantity()
credit = Metered().get_consumption_credit()
print(f"Consumption quantity: {quantity}, credit: {credit}")
if __name__ == "__main__":
set_metered_license()
```
{{< /tab >}}
{{< /tabs >}}
### Changing the license file name
You are not required to keep the license file name as `GroupDocs.Redaction.lic`. You can rename it to any preferred name and use that name when applying the license in your application.
### "Cannot find license filename" exception
When you download the license from the GroupDocs website it is saved as `GroupDocs.Redaction.lic`. However, some web browsers may automatically append `.xml`, resulting in `GroupDocs.Redaction.lic.xml`.
If your Windows settings are configured to hide file extensions (the default), the file may still appear as `GroupDocs.Redaction.lic` in File Explorer even though the actual name is `GroupDocs.Redaction.lic.xml`. This discrepancy can cause `set_license` to throw an exception. To fix it, manually rename the file to remove the `.xml` extension, or disable "Hide extensions for known file types" in Windows.
## How to evaluate GroupDocs.Redaction
You can evaluate GroupDocs.Redaction for Python via .NET without purchasing a license by using one of the following options.
### Free Trial
The evaluation version is identical to the purchased one; it becomes fully licensed once you set a license. Without a license the Free Trial gives you access to the API's features, but with some limitations:
- Only **one document** can be opened per process (a subsequent open raises a `TrialLimitationsException`).
- Only **one redaction** can be applied to the document.
- Any redaction is limited to **four replacements/deletions**, even if there are more matches.
- Trial badges are placed at the top of each page of the output document.
### Temporary License
To experience the complete features of GroupDocs.Redaction without the limitations of the Free Trial, you can request a 30-day ["Temporary License"](https://purchase.groupdocs.com/temporary-license).
---
## Pre-rasterize
Path: /redaction/python-net/pre-rasterize/
In some cases, you might need to pre-rasterize the document before opening it and applying redactions.
For instance, you might need to use an [ImageAreaRedaction](https://reference.groupdocs.com/redaction/python-net/groupdocs.redaction.redactions/imagearearedaction/) for a whole page of a document with search-able text and images. In order to do that, you will need to pass the Boolean flag to the [LoadOptions](https://reference.groupdocs.com/redaction/python-net/groupdocs.redaction.options/loadoptions/) class constructor.
The following example demonstrates how to pre-rasterize a Microsoft Word document:
{{< tabs "code-example-pre-rasterize-document" >}}
{{< tab "pre_rasterize_document.py" >}}
```python
from groupdocs.redaction import Redactor, RedactionStatus
from groupdocs.redaction.options import SaveOptions
from groupdocs.redaction.redactions import ExactPhraseRedaction, ReplacementOptions
def pre_rasterize_document():
# Specify the redaction options
repl_opt = ReplacementOptions("[personal]")
ex_red = ExactPhraseRedaction("John Doe", repl_opt)
# Load the document to be redacted
with Redactor("./sample.docx") as redactor:
# Apply the redaction
result = redactor.apply(ex_red)
if result.status != RedactionStatus.FAILED:
# By default, the redacted document is saved in PDF format
save_options = SaveOptions()
save_options.add_suffix = True
save_options.rasterize_to_pdf = True
save_options.redacted_file_suffix = "redacted"
result_path = redactor.save(save_options)
print(f"Document redacted successfully.\nCheck output in {result_path}")
else:
print("Redaction failed!")
if __name__ == "__main__":
pre_rasterize_document()
```
{{< /tab >}}
{{< tab "sample.docx" >}}
{{< tab-text >}}
`sample.docx` is the sample file used in this example. Click [here](/redaction/python-net/_sample_files/developer-guide/advanced-usage/loading-documents/pre-rasterize/sample.docx) to download it.
{{< /tab-text >}}
{{< /tab >}}
{{< tab "sample_redacted.pdf" >}}
```text
Binary file (PDF, 1024 KB)
```
[Download full output](/redaction/python-net/_output_files/developer-guide/advanced-usage/loading-documents/pre-rasterize/pre_rasterize_document/sample_redacted.pdf)
{{< /tab >}}
{{< /tabs >}}
---
## Select specific pages for rasterized PDF
Path: /redaction/python-net/select-specific-pages-for-rasterized-pdf/
Saving document as a rasterized PDF, you can specify starting page index (zero based) and the number of pages from this index to save. Also, you can change the Compliance level from PDF/A-1b, which is used by default, to PDF/A-1a:
{{< tabs "code-example-select-specific-pages-for-rasterized-pdf" >}}
{{< tab "select_specific_pages_for_rasterized_pdf.py" >}}
```python
from groupdocs.redaction import Redactor, RedactionStatus
from groupdocs.redaction.options import SaveOptions, PdfComplianceLevel
from groupdocs.redaction.redactions import ExactPhraseRedaction, ReplacementOptions
from groupdocs.pydrawing import Color
def select_specific_pages_for_rasterized_pdf():
# Define the color of redaction
color = Color.from_argb(255, 220, 20, 60)
# Specify the redaction options
repl_opt = ReplacementOptions(color)
ex_red = ExactPhraseRedaction("John Doe", repl_opt)
# Load the document to be redacted
with Redactor("./multipage_sample.docx") as redactor:
# Apply the redaction
result = redactor.apply(ex_red)
if result.status != RedactionStatus.FAILED:
# Save the processed document, selecting the page range and compliance level
so = SaveOptions()
so.rasterization.enabled = True # convert pages to images for compatibility
so.rasterization.page_index = 5 # start from 6th page (index is 0-based)
so.rasterization.page_count = 1 # save only one page
so.rasterization.compliance = PdfComplianceLevel.PDF_A1A # PDF/A-1a format
so.add_suffix = False
result_path = redactor.save(so)
print(f"Document redacted successfully.\nCheck output in {result_path}")
else:
print("Redaction failed!")
if __name__ == "__main__":
select_specific_pages_for_rasterized_pdf()
```
{{< /tab >}}
{{< tab "multipage_sample.docx" >}}
{{< tab-text >}}
`multipage_sample.docx` is the sample file used in this example. Click [here](/redaction/python-net/_sample_files/developer-guide/advanced-usage/saving-documents/select-specific-pages-for-rasterized-pdf/multipage_sample.docx) to download it.
{{< /tab-text >}}
{{< /tab >}}
{{< tab "multipage_sample.pdf" >}}
```text
Binary file (PDF, 10.8 MB)
```
[Download full output](/redaction/python-net/_output_files/developer-guide/advanced-usage/saving-documents/select-specific-pages-for-rasterized-pdf/select_specific_pages_for_rasterized_pdf/multipage_sample.pdf)
{{< /tab >}}
{{< /tabs >}}
---
## Text redaction
Path: /redaction/python-net/text-redactions/
GroupDocs.Redaction allows to easily redact data of sensitive or private nature from your documents. The most popular redaction case is to remove a text from a document.
With GroupDocs.Redaction API you can apply text redaction using exact phrase or [regular expression](https://docs.microsoft.com/en-us/dotnet/standard/base-types/regular-expressions) for documents of different formats like PDF, DOC, DOCX, PPT, PPTX, XLS, XLSX and others. See full list at [supported document formats]({{< ref "redaction/python-net/getting-started/supported-document-formats.md" >}}) article.
## Use exact phrase redaction
In the example below, we apply textual redaction, replacing personal exact phrase "John Doe" with "\[personal\]" (or any exemption code):
{{< tabs "code-example-redact-exact-phrase" >}}
{{< tab "redact_exact_phrase.py" >}}
```python
from groupdocs.redaction import Redactor
from groupdocs.redaction.options import SaveOptions
from groupdocs.redaction.redactions import ExactPhraseRedaction, ReplacementOptions
def redact_exact_phrase():
# Specify the redaction options
repl_opt = ReplacementOptions("[personal]")
ex_red = ExactPhraseRedaction("John Doe", repl_opt)
# Load the document to be redacted
with Redactor("./sample.docx") as redactor:
# Apply the redaction
result = redactor.apply(ex_red)
# Save the redacted document next to the source file
so = SaveOptions()
so.add_suffix = True
so.rasterize_to_pdf = False
so.redacted_file_suffix = "redacted"
redactor.save(so)
if __name__ == "__main__":
redact_exact_phrase()
```
{{< /tab >}}
{{< tab "sample.docx" >}}
{{< tab-text >}}
`sample.docx` is the sample file used in this example. Click [here](/redaction/python-net/_sample_files/developer-guide/basic-usage/text-redactions/sample.docx) to download it.
{{< /tab-text >}}
{{< /tab >}}
{{< tab "sample_redacted.docx" >}}
```text
Binary file (DOCX, 16 KB)
```
[Download full output](/redaction/python-net/_output_files/developer-guide/basic-usage/text-redactions/redact_exact_phrase/sample_redacted.docx)
{{< /tab >}}
{{< /tabs >}}
By default, search for exact phase is case insensitive. For a case-sensitive redaction, there is a constructor parameter and corresponding public property:
{{< tabs "code-example-redact-case-sensitive-phrase" >}}
{{< tab "redact_case_sensitive_phrase.py" >}}
```python
from groupdocs.redaction import Redactor
from groupdocs.redaction.options import SaveOptions
from groupdocs.redaction.redactions import ExactPhraseRedaction, ReplacementOptions
def redact_case_sensitive_phrase():
# Enable case-sensitive matching
case_sensitive = True
# Specify the redaction options
repl_opt = ReplacementOptions("[personal]")
ex_red = ExactPhraseRedaction("John Doe", case_sensitive, repl_opt)
# Load the document to be redacted
with Redactor("./sample.docx") as redactor:
# Apply the redaction
result = redactor.apply(ex_red)
# Save the redacted document next to the source file
so = SaveOptions()
so.add_suffix = True
so.rasterize_to_pdf = False
so.redacted_file_suffix = "redacted"
redactor.save(so)
if __name__ == "__main__":
redact_case_sensitive_phrase()
```
{{< /tab >}}
{{< tab "sample.docx" >}}
{{< tab-text >}}
`sample.docx` is the sample file used in this example. Click [here](/redaction/python-net/_sample_files/developer-guide/basic-usage/text-redactions/sample.docx) to download it.
{{< /tab-text >}}
{{< /tab >}}
{{< tab "sample_redacted.docx" >}}
```text
Binary file (DOCX, 16 KB)
```
[Download full output](/redaction/python-net/_output_files/developer-guide/basic-usage/text-redactions/redact_case_sensitive_phrase/sample_redacted.docx)
{{< /tab >}}
{{< /tabs >}}
If you need a color box over the redacted text, you can use color instead of replacement string. The redaction will erase matched text and put a rectangle of the specified color in place of redacted text:
{{< tabs "code-example-redact-with-color-box" >}}
{{< tab "redact_with_color_box.py" >}}
```python
from groupdocs.redaction import Redactor
from groupdocs.redaction.options import SaveOptions
from groupdocs.redaction.redactions import ExactPhraseRedaction, ReplacementOptions
from groupdocs.pydrawing import Color
def redact_with_color_box():
# Define the color of the redaction box
color = Color.from_argb(255, 220, 20, 60)
# Specify the redaction options
repl_opt = ReplacementOptions(color)
ex_red = ExactPhraseRedaction("John Doe", repl_opt)
# Load the document to be redacted
with Redactor("./sample.docx") as redactor:
# Apply the redaction
result = redactor.apply(ex_red)
# Save the redacted document next to the source file
so = SaveOptions()
so.add_suffix = True
so.rasterize_to_pdf = False
so.redacted_file_suffix = "redacted"
redactor.save(so)
if __name__ == "__main__":
redact_with_color_box()
```
{{< /tab >}}
{{< tab "sample.docx" >}}
{{< tab-text >}}
`sample.docx` is the sample file used in this example. Click [here](/redaction/python-net/_sample_files/developer-guide/basic-usage/text-redactions/sample.docx) to download it.
{{< /tab-text >}}
{{< /tab >}}
{{< tab "sample_redacted.docx" >}}
```text
Binary file (DOCX, 17 KB)
```
[Download full output](/redaction/python-net/_output_files/developer-guide/basic-usage/text-redactions/redact_with_color_box/sample_redacted.docx)
{{< /tab >}}
{{< /tabs >}}
You might need to apply redaction to a right-to-left document, such as Arabic or Hebrew. The following example demonstrates how to apply ExactPhraseRedaction to an Arabic PDF document:
{{< tabs "code-example-redact-right-to-left-text" >}}
{{< tab "redact_right_to_left_text.py" >}}
```python
from groupdocs.redaction import Redactor
from groupdocs.redaction.options import SaveOptions
from groupdocs.redaction.redactions import ExactPhraseRedaction, ReplacementOptions
def redact_right_to_left_text():
# Specify the redaction options with an Arabic phrase
repl_opt = ReplacementOptions("[test]")
ex_red = ExactPhraseRedaction("انتقد", repl_opt)
# Load the document to be redacted
with Redactor("./arabic.pdf") as redactor:
# Apply the redaction
result = redactor.apply(ex_red)
# Save the redacted document next to the source file
so = SaveOptions()
so.add_suffix = True
so.rasterize_to_pdf = False
so.redacted_file_suffix = "redacted"
redactor.save(so)
if __name__ == "__main__":
redact_right_to_left_text()
```
{{< /tab >}}
{{< tab "arabic.pdf" >}}
{{< tab-text >}}
`arabic.pdf` is the sample file used in this example. Click [here](/redaction/python-net/_sample_files/developer-guide/basic-usage/text-redactions/arabic.pdf) to download it.
{{< /tab-text >}}
{{< /tab >}}
{{< tab "arabic_redacted.pdf" >}}
```text
Binary file (PDF, 23 KB)
```
[Download full output](/redaction/python-net/_output_files/developer-guide/basic-usage/text-redactions/redact_right_to_left_text/arabic_redacted.pdf)
{{< /tab >}}
{{< /tabs >}}
## Use regular expression
Behind the scenes, "exact phrase" redaction works though regular expressions, which are the baseline approach for redaction. In the example below, we redact out any text, matching "2 digits, space or nothing, 2 digits, again space and 6 digits" with a blue color box:
{{< tabs "code-example-redact-with-regex" >}}
{{< tab "redact_with_regex.py" >}}
```python
from groupdocs.redaction import Redactor
from groupdocs.redaction.options import SaveOptions
from groupdocs.redaction.redactions import RegexRedaction, ReplacementOptions
from groupdocs.pydrawing import Color
def redact_with_regex():
# Define the color of the redaction box
color = Color.from_argb(255, 220, 20, 60)
# Specify the redaction options
repl_opt = ReplacementOptions(color)
reg_red = RegexRedaction("\\d{2}\\s*\\d{2}[^\\d]*\\d{6}", repl_opt)
# Load the document to be redacted
with Redactor("./sample.docx") as redactor:
# Apply the redaction
result = redactor.apply(reg_red)
# Save the redacted document next to the source file
so = SaveOptions()
so.add_suffix = True
so.rasterize_to_pdf = False
so.redacted_file_suffix = "redacted"
redactor.save(so)
if __name__ == "__main__":
redact_with_regex()
```
{{< /tab >}}
{{< tab "sample.docx" >}}
{{< tab-text >}}
`sample.docx` is the sample file used in this example. Click [here](/redaction/python-net/_sample_files/developer-guide/basic-usage/text-redactions/sample.docx) to download it.
{{< /tab-text >}}
{{< /tab >}}
{{< tab "sample_redacted.docx" >}}
```text
Binary file (DOCX, 16 KB)
```
[Download full output](/redaction/python-net/_output_files/developer-guide/basic-usage/text-redactions/redact_with_regex/sample_redacted.docx)
{{< /tab >}}
{{< /tabs >}}
If you need to apply redact a whole paragraph, you might also need to use RegexRedaction. The following example demonstrates how to redact the whole paragraph in a PDF document:
{{< tabs "code-example-redact-whole-paragraph" >}}
{{< tab "redact_whole_paragraph.py" >}}
```python
from groupdocs.redaction import Redactor
from groupdocs.redaction.options import SaveOptions
from groupdocs.redaction.redactions import RegexRedaction, ReplacementOptions
from groupdocs.pydrawing import Color
def redact_whole_paragraph():
# Define the color of the redaction box
color = Color.from_argb(255, 220, 20, 60)
# Specify the redaction options that match an entire paragraph
repl_opt = ReplacementOptions(color)
reg_red = RegexRedaction("(Lorem(\n|.)+?urna)", repl_opt)
# Load the document to be redacted
with Redactor("./sample.pdf") as redactor:
# Apply the redaction
result = redactor.apply(reg_red)
# Save the redacted document next to the source file
so = SaveOptions()
so.add_suffix = True
so.rasterize_to_pdf = False
so.redacted_file_suffix = "redacted"
redactor.save(so)
if __name__ == "__main__":
redact_whole_paragraph()
```
{{< /tab >}}
{{< tab "sample.pdf" >}}
{{< tab-text >}}
`sample.pdf` is the sample file used in this example. Click [here](/redaction/python-net/_sample_files/developer-guide/basic-usage/text-redactions/sample.pdf) to download it.
{{< /tab-text >}}
{{< /tab >}}
{{< tab "sample_redacted.pdf" >}}
```text
Binary file (PDF, 68 KB)
```
[Download full output](/redaction/python-net/_output_files/developer-guide/basic-usage/text-redactions/redact_whole_paragraph/sample_redacted.pdf)
{{< /tab >}}
{{< /tabs >}}
---
## AI agents and LLM integration
Path: /redaction/python-net/agents-and-llm-integration/
GroupDocs.Redaction for Python via .NET is designed to work smoothly with AI coding assistants such as Claude Code, Cursor, and GitHub Copilot in agent mode.
## Built into the package
The `groupdocs-redaction-net` wheel ships a bundled `AGENTS.md` reference. Once the package is installed, AI tools discover it automatically at `groupdocs/redaction/AGENTS.md`. It covers the canonical imports, the load → apply → save workflow, per-operation recipes, licensing, the full API-surface tables, and troubleshooting — everything an agent needs to write correct redaction code without guessing.
## MCP server
For on-demand documentation lookups, point your AI tool at the GroupDocs MCP server:
```json
{
"mcpServers": {
"groupdocs-docs": {
"url": "https://docs.groupdocs.com/mcp"
}
}
}
```
This works with Claude Code (`~/.claude/settings.json`), Cursor (`.cursor/mcp.json`), VS Code Copilot (`.vscode/mcp.json`), and any MCP-compatible client.
## Machine-readable documentation
LLM-optimized documentation for retrieval-augmented generation and context loading is available at [`https://docs.groupdocs.com/redaction/python-net/llms-full.txt`](https://docs.groupdocs.com/redaction/python-net/llms-full.txt).
## AGENTS.md reference
The complete reference bundled inside the wheel is reproduced below.
````markdown
# GroupDocs.Redaction for Python via .NET -- AGENTS.md
> Instructions for AI agents working with this package.
Permanently remove sensitive content from documents -- redact text by exact phrase or regex, scrub or rewrite metadata, replace or delete annotations, black out image regions, remove pages, and rasterize the result so nothing redacted can be recovered. Works across Word, Excel, PowerPoint, PDF, images, and text formats through one unified API, with no MS Office or external software installed.
## Install
```bash
pip install groupdocs-redaction-net
```
**Python**: 3.5 - 3.14 | **Platforms**: Windows, Linux, macOS
## Resources
| Resource | URL |
|---|---|
| Documentation | https://docs.groupdocs.com/redaction/python-net/ |
| LLM-optimized docs | https://docs.groupdocs.com/redaction/python-net/llms-full.txt |
| API reference | https://reference.groupdocs.com/redaction/python-net/ |
| Code examples | https://docs.groupdocs.com/redaction/python-net/developer-guide/ |
| Release notes | https://releases.groupdocs.com/redaction/python-net/release-notes/ |
| PyPI | https://pypi.org/project/groupdocs-redaction-net/ |
| Free support forum | https://forum.groupdocs.com/c/redaction/ |
| 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.redaction import (
License, Metered, Redactor, RedactionPolicy,
RedactionResult, RedactionStatus, RedactorChangeLog, RedactorLogEntry,
FileType, IDocumentInfo,
)
from groupdocs.redaction.redactions import (
# Text
ExactPhraseRedaction, RegexRedaction, CellColumnRedaction, CellFilter,
PageAreaRedaction, ReplacementOptions, RegionReplacementOptions,
# Metadata
EraseMetadataRedaction, MetadataSearchRedaction, MetadataFilters,
# Annotations
AnnotationRedaction, DeleteAnnotationRedaction,
# Image / page
ImageAreaRedaction, RemovePageRedaction, PageSeekOrigin,
# Custom rules / callback
ICustomRedactionHandler, CustomRedactionContext, CustomRedactionResult,
IRedactionCallback, RedactionDescription, RedactionType, RedactionActionType,
)
from groupdocs.redaction.options import (
LoadOptions, SaveOptions, RasterizationOptions, AdvancedRasterizationOptions,
PdfComplianceLevel, PreviewOptions, PreviewFormats, RedactorSettings,
)
from groupdocs.redaction.exceptions import (
GroupDocsRedactionException, DocumentFormatException,
IncorrectPasswordException, PasswordRequiredException, TrialLimitationsException,
)
from groupdocs.pydrawing import Color, Point, Size # for box / image-area redactions
```
## Load + Apply + Save (the core workflow)
`Redactor` is the entry point. The flow is always: **open → one or more `apply(...)` calls → `save()`**. Each redaction mutates the in-memory document, so you can apply several before a single save. Use `Redactor` as a context manager so the native document handle is released.
```python
from groupdocs.redaction import Redactor
from groupdocs.redaction.redactions import ExactPhraseRedaction, ReplacementOptions
with Redactor("document.docx") as redactor:
redactor.apply(ExactPhraseRedaction("confidential", ReplacementOptions("[REDACTED]")))
redactor.save()
```
**Redactor constructor.** `Redactor(file_path)` or `Redactor(stream)`, optionally with `load_options` and/or `RedactorSettings`: `Redactor(file_path, LoadOptions(password="..."))`, `Redactor(stream, LoadOptions(...), RedactorSettings(...))`.
**`apply(...)`** accepts a single `Redaction`, a list of redactions, or a `RedactionPolicy`. It returns a `RedactorChangeLog` whose `.status` is a `RedactionStatus` (`APPLIED`, `PARTIALLY_APPLIED`, `SKIPPED`, `FAILED`).
**`save(...)`** writes the current state and returns the output path (when saving to a file). **By default it rasterizes the document to a PDF and appends a `_Redacted` suffix.** To control this, pass `SaveOptions` or `RasterizationOptions` (see Rasterization below).
## Operations
### Text redaction (exact phrase / regex)
```python
from groupdocs.redaction import Redactor
from groupdocs.redaction.redactions import ExactPhraseRedaction, RegexRedaction, ReplacementOptions
from groupdocs.pydrawing import Color
with Redactor("document.docx") as redactor:
redactor.apply(ExactPhraseRedaction("John Doe", ReplacementOptions("[CUSTOMER]"))) # case-insensitive
redactor.apply(ExactPhraseRedaction("ACME", True, ReplacementOptions("[CO]"))) # case-sensitive
redactor.apply(RegexRedaction(r"\d{2,}", ReplacementOptions("[NUM]"))) # regex match
redactor.apply(RegexRedaction(r"\bsecret\b", ReplacementOptions(Color.BLACK))) # draw a black box
redactor.save()
```
`ReplacementOptions(text)` replaces the match with a string; `ReplacementOptions(Color)` draws a filled box over it. `ExactPhraseRedaction` also exposes `is_right_to_left`. `CellColumnRedaction(CellFilter, regex, ReplacementOptions)` targets a spreadsheet column.
### Metadata redaction
```python
from groupdocs.redaction import Redactor
from groupdocs.redaction.redactions import EraseMetadataRedaction, MetadataSearchRedaction, MetadataFilters
with Redactor("document.docx") as redactor:
redactor.apply(EraseMetadataRedaction(MetadataFilters.ALL)) # erase everything
redactor.apply(EraseMetadataRedaction(MetadataFilters.AUTHOR)) # erase one field
redactor.apply(MetadataSearchRedaction(".*@acme\\.com", "[EMAIL]")) # rewrite by value pattern
redactor.save()
```
`MetadataFilters` is a flags-style enum: `AUTHOR`, `COMPANY`, `COMMENTS`, `MANAGER`, `TITLE`, `SUBJECT`, `KEYWORDS`, `CONTENT_STATUS`, … and `ALL`. `MetadataSearchRedaction(value_pattern, replacement, key_pattern=...)` can match on key and/or value.
### Annotation redaction
```python
from groupdocs.redaction import Redactor
from groupdocs.redaction.redactions import AnnotationRedaction, DeleteAnnotationRedaction
with Redactor("document.pdf") as redactor:
redactor.apply(AnnotationRedaction("(?i)approved", "[REVIEW]")) # rewrite annotation text
redactor.apply(DeleteAnnotationRedaction("(?i)internal")) # delete matching annotations
redactor.save()
```
### Image-area and page-area redaction
```python
from groupdocs.redaction import Redactor
from groupdocs.redaction.redactions import ImageAreaRedaction, PageAreaRedaction, RegionReplacementOptions, ReplacementOptions
from groupdocs.pydrawing import Point, Size, Color
with Redactor("scan.pdf") as redactor:
# black out a fixed rectangle on every page
redactor.apply(ImageAreaRedaction(Point(50, 60), RegionReplacementOptions(Color.BLACK, Size(200, 80))))
# redact text AND its image rendering in a page area
redactor.apply(PageAreaRedaction(r"\d{3}-\d{2}-\d{4}", ReplacementOptions("[SSN]"),
RegionReplacementOptions(Color.BLACK, Size(120, 20))))
redactor.save()
```
### Page removal
```python
from groupdocs.redaction import Redactor
from groupdocs.redaction.redactions import RemovePageRedaction, PageSeekOrigin
with Redactor("document.pdf") as redactor:
redactor.apply(RemovePageRedaction(PageSeekOrigin.BEGIN, 0, 1)) # drop the first page
redactor.save()
```
### Custom redaction rule / callback
A `RedactorSettings(callback=...)` receives every redaction description and decides whether to accept it. Pass a plain Python callable -- the binding wraps it as the .NET `IRedactionCallback` automatically. `RedactorSettings` is the **third** Redactor argument, after `load_options`, so pass `LoadOptions()` (or a configured one) as well.
```python
from groupdocs.redaction import Redactor
from groupdocs.redaction.redactions import ExactPhraseRedaction, ReplacementOptions
from groupdocs.redaction.options import LoadOptions, RedactorSettings
def accept(description):
# description.original_text, .redaction_type, .action_type
return "keep-me" not in (description.original_text or "") # return False to skip this match
with Redactor("document.docx", LoadOptions(), RedactorSettings(callback=accept)) as redactor:
redactor.apply(ExactPhraseRedaction("secret", ReplacementOptions("[X]")))
redactor.save()
```
The callback returns `bool` (accept/reject) -- `IRedactionCallback.accept_redaction` returns a boolean. For text-rewriting rules use `ICustomRedactionHandler` via `ReplacementOptions.custom_redaction`.
### Rasterization (flatten to PDF)
```python
from groupdocs.redaction import Redactor
from groupdocs.redaction.redactions import ExactPhraseRedaction, ReplacementOptions
from groupdocs.redaction.options import SaveOptions, RasterizationOptions, AdvancedRasterizationOptions
with Redactor("document.docx") as redactor:
redactor.apply(ExactPhraseRedaction("secret", ReplacementOptions("[X]")))
# (a) default: rasterize to PDF, "_Redacted" suffix
redactor.save()
# (b) keep original format, no rasterization
redactor.save(SaveOptions(rasterize_to_pdf=False))
# (c) rasterize with anti-extraction effects
ro = RasterizationOptions()
ro.enabled = True
ro.add_advanced_option(AdvancedRasterizationOptions.NOISE)
ro.add_advanced_option(AdvancedRasterizationOptions.GRAYSCALE)
redactor.save(ro)
```
`RasterizationOptions`: `enabled`, `page_index`, `page_count`, `compliance` (`PdfComplianceLevel.AUTO` / `PDF_A1A`), `add_advanced_option(AdvancedRasterizationOptions.{TILT,NOISE,BORDER,GRAYSCALE})`.
### Save to a stream
`save(stream, rasterization_options)` writes to any writable stream. Return a path-backed or `io.BytesIO` stream; `BytesIO` is updated after the call.
```python
import io
from groupdocs.redaction.options import RasterizationOptions
with Redactor("document.docx") as redactor:
redactor.apply(ExactPhraseRedaction("secret", ReplacementOptions("[X]")))
ro = RasterizationOptions(); ro.enabled = False # keep original format
buf = io.BytesIO()
redactor.save(buf, ro)
data = buf.getvalue()
```
### Redaction policy (reusable rule set)
```python
from groupdocs.redaction import Redactor, RedactionPolicy
from groupdocs.redaction.redactions import ExactPhraseRedaction, RegexRedaction, ReplacementOptions
policy = RedactionPolicy([
ExactPhraseRedaction("ACME", ReplacementOptions("[CO]")),
RegexRedaction(r"\d{2,}", ReplacementOptions("[NUM]")),
])
with Redactor("document.docx") as redactor:
redactor.apply(policy=policy)
redactor.save()
```
Build the policy in memory and reuse it across documents. (A policy can also be authored as an XML file and read with `RedactionPolicy.load(path)`.)
### Document info & preview
```python
with Redactor("document.pdf") as redactor:
info = redactor.get_document_info()
print(info.file_type.file_format, info.page_count, info.size)
```
`get_document_info()` returns an `IDocumentInfo`: `file_type` (a `FileType`), `page_count`, `size`, `pages`. `generate_preview(PreviewOptions(...))` renders pages to images (`PreviewFormats.PNG`/`JPEG`/`BMP`) via a `create_page_stream(page_number)` callback that returns a writable file/path stream (not `BytesIO`).
## Licensing
```python
from groupdocs.redaction 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"`
Metered licensing is also available:
```python
from groupdocs.redaction import Metered
Metered().set_metered_key("public-key", "private-key")
print(Metered().get_consumption_quantity(), Metered().get_consumption_credit())
```
**Evaluation vs licensed.** Without a license the library still runs, but **only one document may be opened per process** (subsequent opens raise a trial-limitation error), PDF output carries an evaluation watermark, and other formats show an equivalent evaluation mark. Set `GROUPDOCS_LIC_PATH` (or call `License().set_license(...)`) and re-run to clear these. A 30-day full license is free: https://purchase.groupdocs.com/temporary-license
## API Reference
### Redactor
| Method | Returns | Description |
|---|---|---|
| `Redactor(file_path / stream [, load_options [, settings]])` | | Open by path or binary stream; optional `LoadOptions` and `RedactorSettings`. Use as a context manager. |
| `apply(redaction)` / `apply(redactions=[...])` / `apply(policy=...)` | `RedactorChangeLog` | Apply one redaction, a list, or a `RedactionPolicy`. `.status` is a `RedactionStatus`. |
| `save([save_options])` | `str` | Write to disk; default rasterizes to PDF + `_Redacted` suffix. Returns the output path. |
| `save(stream [, rasterization_options])` | `str` | Write to a stream (file/path stream or `io.BytesIO`). |
| `generate_preview(preview_options)` | `None` | Render pages to images via a `create_page_stream` callback. |
| `get_document_info()` | `IDocumentInfo` | `file_type`, `page_count`, `size`, `pages`. |
| `dispose()` | `None` | Release native resources (handled by `with`). |
### Redactions
| Type | Notes |
|---|---|
| `ExactPhraseRedaction(phrase [, is_case_sensitive], options)` | Replace/box an exact phrase. `is_right_to_left` for RTL. |
| `RegexRedaction(pattern, options)` | Replace/box a regex match. |
| `CellColumnRedaction(CellFilter, regex, options)` | Redact a spreadsheet column. |
| `PageAreaRedaction(regex, options, RegionReplacementOptions)` | Text + image redaction over a page area. |
| `EraseMetadataRedaction(MetadataFilters)` | Erase metadata by filter. |
| `MetadataSearchRedaction(value_pattern, replacement [, key_pattern])` | Rewrite metadata by key/value pattern. |
| `AnnotationRedaction(pattern, replacement)` / `DeleteAnnotationRedaction(pattern)` | Rewrite or delete annotations. |
| `ImageAreaRedaction(Point, RegionReplacementOptions)` | Black out a rectangle on a page. |
| `RemovePageRedaction(PageSeekOrigin, index, count)` | Remove pages from the start/end. |
| `ReplacementOptions(text)` / `ReplacementOptions(Color)` | Text replacement vs. a filled box. `filters`, `custom_redaction`. |
| `RegionReplacementOptions(fill_color, size [, font, expected_text])` | Box geometry for image/page-area redactions. |
### Options & enums
| Type | Notes |
|---|---|
| `LoadOptions(password=..., pre_rasterize=...)` | Open protected / pre-rasterized input. |
| `SaveOptions(rasterize_to_pdf=..., suffix=...)` | Control format + `_Redacted` suffix. |
| `RasterizationOptions()` | `enabled`, `page_index`, `page_count`, `compliance`, `add_advanced_option(...)`. |
| `AdvancedRasterizationOptions` | `NONE`, `TILT`, `NOISE`, `BORDER`, `GRAYSCALE`. |
| `PdfComplianceLevel` | `AUTO`, `PDF_A1A`. |
| `PreviewOptions(create_page_stream [, release_page_stream])` | `width`, `height`, `page_numbers`, `preview_format`. |
| `PreviewFormats` | `PNG`, `JPEG`, `BMP`. |
| `RedactorSettings(logger=..., callback=..., ocr_connector=...)` | Inject a logger, an `IRedactionCallback`, or OCR. |
| `MetadataFilters` | `AUTHOR`, `COMPANY`, `COMMENTS`, `MANAGER`, `TITLE`, `SUBJECT`, `KEYWORDS`, …, `ALL`. |
| `RedactionStatus` | `APPLIED`, `PARTIALLY_APPLIED`, `SKIPPED`, `FAILED`. |
| `RedactionType` / `RedactionActionType` | `TEXT`/`METADATA`/`ANNOTATION`/`IMAGE_AREA`/`PAGE`; `REPLACEMENT`/`CLEANUP`/`DELETION`. |
| `PageSeekOrigin` | `BEGIN`, `END`. |
### License / Metered
`License().set_license(path_or_stream)` · `Metered().set_metered_key(public, private)` · `Metered().get_consumption_quantity()` · `Metered().get_consumption_credit()`
## Key Patterns
- **Properties**: use `snake_case` -- auto-mapped to .NET `PascalCase`
- **Context managers**: `with Redactor(...) as r:` ensures the document handle is released
- **Chaining**: each `apply()` mutates in place; run several before one `save()`
- **Default save rasterizes**: `save()` produces a PDF + `_Redacted` suffix; pass `SaveOptions(rasterize_to_pdf=False)` to keep the source format
- **Colors / geometry**: `Color`, `Point`, `Size` come from `groupdocs.pydrawing`; `ReplacementOptions(Color)` draws a box
- **Regex args**: pass a plain Python regex string -- the binding wraps it as a .NET `Regex`
- **Streams**: pass `open("file", "rb")` or `io.BytesIO(data)` where .NET expects a Stream; `BytesIO` is updated after `save(stream)`
- **Enums**: case-insensitive, lazy-loaded (e.g., `MetadataFilters.ALL`, `PreviewFormats.PNG`)
- **Callbacks**: a Python callable is accepted for `IRedactionCallback`; it returns `bool` to accept/reject each match
- **Exceptions**: catch `PasswordRequiredException` / `IncorrectPasswordException` / `DocumentFormatException` / `TrialLimitationsException` (all subclass `GroupDocsRedactionException`)
## Platform Requirements
| Platform | Requirements |
|---|---|
| Windows | None |
| Linux | `apt install libgdiplus libfontconfig1 ttf-mscorefonts-installer` |
| macOS | `brew install mono-libgdiplus` |
## Troubleshooting
**`Trial mode allows only 1 document to open` / `TrialLimitationsException`** -- no license. Apply one with `License().set_license(...)` or set `GROUPDOCS_LIC_PATH`; a free 30-day license is at https://purchase.groupdocs.com/temporary-license
**`PasswordRequiredException` / `IncorrectPasswordException`** -- the source is encrypted. Open it with `Redactor(path, LoadOptions(password="..."))`.
**`DocumentFormatException`** -- the file format isn't supported or the file is corrupted. Check it against the supported-formats list.
**`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-redaction-net`
**Still stuck?** Post your question at https://forum.groupdocs.com/c/redaction/ -- the development team responds directly.
````
---
## Extend supported extensions list
Path: /redaction/python-net/extend-supported-extensions-list/
This method can be used when for some reason files have non-standard extensions or if its format is supported, but not pre-configured. For instance, all kinds of plain text files (batch, command files, etc.) could be opened. In this case you do not need to create your own format handler. As it is shown below, you can add file extension (e.g. ".dump") as being handled by the same *[DocumentFormatInstance](https://reference.groupdocs.com/redaction/python-net/groupdocs.redaction.integration/documentformatinstance/)* as all plain text files:
{{< tabs "code-example-extend-supported-extensions-list" >}}
{{< tab "extend_supported_extensions_list.py" >}}
```python
from groupdocs.redaction import Redactor
from groupdocs.redaction.configuration import RedactorConfiguration
from groupdocs.redaction.options import SaveOptions
from groupdocs.redaction.redactions import ExactPhraseRedaction, ReplacementOptions
def extend_supported_extensions_list():
# Add the .dump format to the list of supported formats, handled as plain text
config = RedactorConfiguration.get_instance()
settings = config.find_format(".txt")
settings.extension_filter = settings.extension_filter + ",.dump"
# Specify the redaction options
repl_opt = ReplacementOptions("[redacted]")
ex_red = ExactPhraseRedaction("dolor", repl_opt)
# Load the document with the newly supported extension
with Redactor("./sample.dump") as redactor:
# Apply the redaction
redactor.apply(ex_red)
# Save the redacted document
save_options = SaveOptions()
save_options.add_suffix = True
save_options.rasterize_to_pdf = True
save_options.redacted_file_suffix = "redacted"
result_path = redactor.save(save_options)
print(f"Document redacted successfully.\nCheck output in {result_path}.")
if __name__ == "__main__":
extend_supported_extensions_list()
```
{{< /tab >}}
{{< tab "sample_redacted.pdf" >}}
```text
Binary file (PDF, 1.9 MB)
```
[Download full output](/redaction/python-net/_output_files/developer-guide/advanced-usage/extend-supported-extensions-list/extend_supported_extensions_list/sample_redacted.pdf)
{{< /tab >}}
{{< /tabs >}}
In detail, creating your own document format instances is covered in another article.
---
## Metadata redactions
Path: /redaction/python-net/metadata-redactions/
With GroupDocs.Redaction API you can apply metadata redactions for documents of different formats like PDF, DOC, DOCX, PPT, PPTX, XLS, XLSX and others. See full list at [supported document formats]({{< ref "redaction/python-net/getting-started/supported-document-formats.md" >}}) article.
GroupDocs.Redactions provides a flexible API that allows to replace or remove metadata using filters or search by regular expression.
## Filter metadata
Base functionality for all redactions, derived from [MetadataRedaction](https://reference.groupdocs.com/redaction/python-net/groupdocs.redaction.redactions/metadataredaction/) base class is *metadata filtering* and it is mandatory for metadata redactions. It uses flagged enumeration [MetadataFilters](https://reference.groupdocs.com/redaction/python-net/groupdocs.redaction.redactions/metadatafilters/), containing items for most frequent metadata entries. You can set the filter to *All*, or any combination of metadata. For instance, the example below sets filter to *Author*, *Manager* and *NameOfApplication* - for textual redaction or cleaning them out:
```python
# redaction derived from MetadataRedaction
redaction.filter = MetadataFilters.AUTHOR | MetadataFilters.MANAGER | MetadataFilters.NAME_OF_APPLICATION
```
Below is the table with full list of [MetadataFilters](https://reference.groupdocs.com/redaction/python-net/groupdocs.redaction.redactions/metadatafilters/) items:
| Filter | Numeric value | Description |
| --- | --- | --- |
| *None* | 0 | Empty filter setting, matches no metadata items |
| *Author* | 1 | Author of the document |
| *Category* | 2 | Category of the document |
| *Comments* | 4 | Document comment |
| *Company* | 8 | Company of the Author |
| *ContentStatus* | 16 | Content status |
| *CreatedTime* | 32 | Created time |
| *HyperlinkBase* | 64 | Hyperlink base |
| *LastPrinted* | 128 | Last printed date and time |
| *LastSavedBy* | 256 | Last saved by user |
| *LastSavedTime* | 1024 | Last saved date and time |
| *NameOfApplication* | 2048 | Name of application where the document was created |
| *Manager* | 4096 | Author's manager name |
| *RevisionNumber* | 8192 | Revision number |
| *Subject* | 16384 | Subject of the document |
| *Template* | 32768 | Document template name |
| *Title* | 65536 | Document title |
| *TotalEditingTime* | 131072 | Total editing time |
| *Version* | 262144 | Document's version |
| *Description* | 524288 | Document's description |
| *Keywords* | 1048576 | Document's keywords |
| *ContentType* | 2097152 | Content type |
| *All* | 2147483647 | All types of the metadata items |
## Clean metadata
You can replace all or specific metadata in the document with empty (blank or minimal) values using [EraseMetadataRedaction](https://reference.groupdocs.com/redaction/python-net/groupdocs.redaction.redactions/erasemetadataredaction/) class. The example below blanks out all properties of the document:
{{< tabs "code-example-clean-all-metadata" >}}
{{< tab "clean_all_metadata.py" >}}
```python
from groupdocs.redaction import Redactor
from groupdocs.redaction.options import SaveOptions
from groupdocs.redaction.redactions import EraseMetadataRedaction, MetadataFilters
def clean_all_metadata():
# Specify the redaction options to erase all metadata
met_red = EraseMetadataRedaction(MetadataFilters.ALL)
# Load the document to be redacted
with Redactor("./sample.docx") as redactor:
# Apply the redaction
result = redactor.apply(met_red)
# Save the redacted document next to the source file
so = SaveOptions()
so.add_suffix = True
so.rasterize_to_pdf = False
so.redacted_file_suffix = "redacted"
redactor.save(so)
if __name__ == "__main__":
clean_all_metadata()
```
{{< /tab >}}
{{< tab "sample.docx" >}}
{{< tab-text >}}
`sample.docx` is the sample file used in this example. Click [here](/redaction/python-net/_sample_files/developer-guide/basic-usage/metadata-redactions/sample.docx) to download it.
{{< /tab-text >}}
{{< /tab >}}
{{< tab "sample_redacted.docx" >}}
```text
Binary file (DOCX, 16 KB)
```
[Download full output](/redaction/python-net/_output_files/developer-guide/basic-usage/metadata-redactions/clean_all_metadata/sample_redacted.docx)
{{< /tab >}}
{{< /tabs >}}
You can specify [MetadataFilter.All](https://reference.groupdocs.com/redaction/python-net/groupdocs.redaction.redactions/metadatafilters/) or use default constructor to blank out all metadata within given document, Custom - to clear all custom metadata entries.
## Redact metadata
You can use [MetadataSearchRedaction](https://reference.groupdocs.com/redaction/python-net/groupdocs.redaction.redactions/metadatasearchredaction/) to remove sensitive data from document's metadata using regular expressions. For instance, we can remove any mention of "Company Ltd.":
{{< tabs "code-example-redact-metadata" >}}
{{< tab "redact_metadata.py" >}}
```python
from groupdocs.redaction import Redactor
from groupdocs.redaction.options import SaveOptions
from groupdocs.redaction.redactions import MetadataSearchRedaction
def redact_metadata():
# Specify the redaction options: search pattern and replacement string
met_red = MetadataSearchRedaction("Company Ltd.", "--company--")
# Load the document to be redacted
with Redactor("./sample.docx") as redactor:
# Apply the redaction
result = redactor.apply(met_red)
# Save the redacted document next to the source file
so = SaveOptions()
so.add_suffix = True
so.rasterize_to_pdf = False
so.redacted_file_suffix = "redacted"
redactor.save(so)
if __name__ == "__main__":
redact_metadata()
```
{{< /tab >}}
{{< tab "sample.docx" >}}
{{< tab-text >}}
`sample.docx` is the sample file used in this example. Click [here](/redaction/python-net/_sample_files/developer-guide/basic-usage/metadata-redactions/sample.docx) to download it.
{{< /tab-text >}}
{{< /tab >}}
{{< tab "sample_redacted.docx" >}}
```text
Binary file (DOCX, 16 KB)
```
[Download full output](/redaction/python-net/_output_files/developer-guide/basic-usage/metadata-redactions/redact_metadata/sample_redacted.docx)
{{< /tab >}}
{{< /tabs >}}
First argument is regular expression, second is a replacement string. You can also set scope for redaction by setting filter, e.g. to [MetadataFilter.Company](https://reference.groupdocs.com/redaction/python-net/groupdocs.redaction.redactions/metadatafilters/). - it will leave the regular expressions matches undone in all metadata items, except "Company" property:
{{< tabs "code-example-redact-metadata-with-filter" >}}
{{< tab "redact_metadata_with_filter.py" >}}
```python
from groupdocs.redaction import Redactor
from groupdocs.redaction.options import SaveOptions
from groupdocs.redaction.redactions import MetadataSearchRedaction, MetadataFilters
def redact_metadata_with_filter():
# Specify the redaction options: search pattern and replacement string
met_red = MetadataSearchRedaction("Company Ltd.", "--company--")
# Limit the redaction scope to the Company metadata item only
met_red.filter = MetadataFilters.COMPANY
# Load the document to be redacted
with Redactor("./sample.docx") as redactor:
# Apply the redaction
result = redactor.apply(met_red)
# Save the redacted document next to the source file
so = SaveOptions()
so.add_suffix = True
so.rasterize_to_pdf = False
so.redacted_file_suffix = "redacted"
redactor.save(so)
if __name__ == "__main__":
redact_metadata_with_filter()
```
{{< /tab >}}
{{< tab "sample.docx" >}}
{{< tab-text >}}
`sample.docx` is the sample file used in this example. Click [here](/redaction/python-net/_sample_files/developer-guide/basic-usage/metadata-redactions/sample.docx) to download it.
{{< /tab-text >}}
{{< /tab >}}
{{< tab "sample_redacted.docx" >}}
```text
Binary file (DOCX, 16 KB)
```
[Download full output](/redaction/python-net/_output_files/developer-guide/basic-usage/metadata-redactions/redact_metadata_with_filter/sample_redacted.docx)
{{< /tab >}}
{{< /tabs >}}
## Metadata redaction status
All metadata redactions apply to each metadata item separately, and even if metadata item redaction fails, the rest of the metadata items will be updated. You can find a list of failed, skipped (rejected) metadata items and reasons for that in [ErrorMessage](https://reference.groupdocs.com/redaction/python-net/groupdocs.redaction/redactionresult/error_message/) property of [RedactorLogEntry.Result](https://reference.groupdocs.com/redaction/python-net/groupdocs.redaction/redactorlogentry/result/).
---
## Save to Stream
Path: /redaction/python-net/save-to-stream/
You might need to save a document to any custom file at any location on the local disc or a even a Stream.
The following example demonstrates how to save a document to any location.
{{< tabs "code-example-save-to-stream" >}}
{{< tab "save_to_stream.py" >}}
```python
from groupdocs.redaction import Redactor, RedactionStatus
from groupdocs.redaction.options import RasterizationOptions
from groupdocs.redaction.redactions import ExactPhraseRedaction, ReplacementOptions
from groupdocs.pydrawing import Color
def save_to_stream():
# Define the color of redaction
color = Color.from_argb(255, 220, 20, 60)
# Specify the redaction options
repl_opt = ReplacementOptions(color)
ex_red = ExactPhraseRedaction("John Doe", repl_opt)
# Load the document to be redacted
with Redactor("./sample.docx") as redactor:
# Apply the redaction
result = redactor.apply(ex_red)
if result.status != RedactionStatus.FAILED:
# Save the document to a stream and convert its pages to images
ro = RasterizationOptions()
ro.enabled = True
with open("./redacted-sample.pdf", "wb") as stream_out:
redactor.save(stream_out, ro)
print("Document redacted successfully.\nCheck output in ./redacted-sample.pdf")
else:
print("Redaction failed!")
if __name__ == "__main__":
save_to_stream()
```
{{< /tab >}}
{{< tab "sample.docx" >}}
{{< tab-text >}}
`sample.docx` is the sample file used in this example. Click [here](/redaction/python-net/_sample_files/developer-guide/advanced-usage/saving-documents/save-to-stream/sample.docx) to download it.
{{< /tab-text >}}
{{< /tab >}}
{{< tab "redacted-sample.pdf" >}}
```text
Binary file (PDF, 1024 KB)
```
[Download full output](/redaction/python-net/_output_files/developer-guide/advanced-usage/saving-documents/save-to-stream/save_to_stream/redacted-sample.pdf)
{{< /tab >}}
{{< /tabs >}}
---
## System Requirements
Path: /redaction/python-net/system-requirements/
{{< alert style="info" >}}
GroupDocs.Redaction for Python via .NET operates independently of external software like Microsoft Word, Excel, PowerPoint, or Adobe Acrobat. To install it, simply follow one of the methods described in the [Installation]({{< ref "redaction/python-net/getting-started/installation.md" >}}) section.
{{< /alert >}}
## Overview
GroupDocs.Redaction for Python via .NET does not require Microsoft Office, OpenOffice, Adobe Acrobat, or any other external software to be installed. The package is a self-contained wheel that bundles everything it needs, so the only prerequisites are a supported version of Python and the operating-system packages listed below.
## Supported Python Versions
GroupDocs.Redaction for Python via .NET supports the following Python versions:
* Python 3.5
* Python 3.6
* Python 3.7
* Python 3.8
* Python 3.9
* Python 3.10
* Python 3.11
* Python 3.12
* Python 3.13
* Python 3.14
## Supported Operating Systems
The package is distributed as a self-contained wheel that runs on the following platforms:
### Windows
* Windows x64
No additional dependencies are required on Windows.
### Linux
* Linux x64
On Linux you need to install a few system packages for graphics, fonts, and globalization:
```bash
apt install libgdiplus libfontconfig1 libicu-dev ttf-mscorefonts-installer
```
### macOS
* macOS x64 (Intel)
* macOS ARM64 (Apple Silicon)
On macOS install the graphics library via Homebrew:
```bash
brew install mono-libgdiplus
```
## Platform-Specific Feature Support
{{< alert style="warning" >}}
**Rasterization to PDF and image-area redaction currently require Windows.** In version 26.6.0 the bundled engine renders rasterized output and processes images through `System.Drawing.Common`, which the embedded .NET runtime supports only on Windows. On Linux and macOS these specific operations raise a `System.PlatformNotSupportedException` ("System.Drawing.Common is not supported on this platform"). Installing `libgdiplus` / `mono-libgdiplus` does **not** lift this restriction.
{{< /alert >}}
The following redaction operations work on **all** platforms — Windows, Linux, and macOS:
* Text redaction (exact phrase and regular expression)
* Metadata redaction (erase, and search-and-replace)
* Annotation redaction (rewrite and delete)
* Page removal
* Saving in the **original** format with `SaveOptions(rasterize_to_pdf=False)`
The following operations currently require **Windows**:
* The default `save()` — which rasterizes the result to a PDF — and any `RasterizationOptions` or rasterized-PDF save path
* `ImageAreaRedaction` and image cleaning / image-export operations
On Linux and macOS, keep the source format with `SaveOptions(rasterize_to_pdf=False)`, or perform the rasterization and image-redaction steps on Windows.
## No Third-Party Software Required
Unlike many document-processing tools, GroupDocs.Redaction for Python via .NET does not depend on Microsoft Office, OpenOffice, Adobe Acrobat, or any other application being installed on the machine. All loading, redacting, and saving of Word Processing documents, Spreadsheets, Presentations, PDFs, and images is performed entirely by the bundled engine.
---
## Annotation redactions
Path: /redaction/python-net/annotation-redactions/
With GroupDocs.Redaction API you can apply annotation redactions for documents of different formats like PDF, DOC, DOCX, PPT, PPTX, XLS, XLSX and others. See full list at [supported document formats]({{< ref "redaction/python-net/getting-started/supported-document-formats.md" >}}) article.
GroupDocs.Redactions provides a flexible API that allows to remove sensitive data from annotation text, or completely remove annotations by a regular expression.
## Remove annotations (comments etc)
You can use GroupDocs.Redaction to remove all or specific comments and other annotations from the document. For example, we can remove all comments from the document, containing texts like "use", "show" or "describe" in its body:
{{< tabs "code-example-remove-all-annotations" >}}
{{< tab "remove_all_annotations.py" >}}
```python
from groupdocs.redaction import Redactor
from groupdocs.redaction.options import SaveOptions
from groupdocs.redaction.redactions import DeleteAnnotationRedaction
def remove_all_annotations():
# Specify the redaction options to delete annotations matching the pattern
a_red = DeleteAnnotationRedaction("(?im:(use|show|describe))")
# Load the document to be redacted
with Redactor("./annotated.xlsx") as redactor:
# Apply the redaction
result = redactor.apply(a_red)
# Save the redacted document next to the source file
so = SaveOptions()
so.add_suffix = True
so.rasterize_to_pdf = False
so.redacted_file_suffix = "redacted"
redactor.save(so)
if __name__ == "__main__":
remove_all_annotations()
```
{{< /tab >}}
{{< tab "annotated.xlsx" >}}
{{< tab-text >}}
`annotated.xlsx` is the sample file used in this example. Click [here](/redaction/python-net/_sample_files/developer-guide/basic-usage/annotation-redactions/annotated.xlsx) to download it.
{{< /tab-text >}}
{{< /tab >}}
{{< tab "annotated_redacted.xlsx" >}}
```text
Binary file (XLSX, 12 KB)
```
[Download full output](/redaction/python-net/_output_files/developer-guide/basic-usage/annotation-redactions/remove_all_annotations/annotated_redacted.xlsx)
{{< /tab >}}
{{< /tabs >}}
You can use constructor without arguments to remove all annotations within the document.
## Redact annotations
Instead of removing all or specific annotations, you can remove sensitive data from the annotation text. For instance, we can remove all mentions of "John" in the given document, e.g.:
{{< tabs "code-example-redact-annotations" >}}
{{< tab "redact_annotations.py" >}}
```python
from groupdocs.redaction import Redactor
from groupdocs.redaction.options import SaveOptions
from groupdocs.redaction.redactions import AnnotationRedaction
def redact_annotations():
# Specify the redaction options: search pattern and replacement string
a_red = AnnotationRedaction("(?im:john)", "[redacted]")
# Load the document to be redacted
with Redactor("./annotated.xlsx") as redactor:
# Apply the redaction
result = redactor.apply(a_red)
# Save the redacted document next to the source file
so = SaveOptions()
so.add_suffix = True
so.rasterize_to_pdf = False
so.redacted_file_suffix = "redacted"
redactor.save(so)
if __name__ == "__main__":
redact_annotations()
```
{{< /tab >}}
{{< tab "annotated.xlsx" >}}
{{< tab-text >}}
`annotated.xlsx` is the sample file used in this example. Click [here](/redaction/python-net/_sample_files/developer-guide/basic-usage/annotation-redactions/annotated.xlsx) to download it.
{{< /tab-text >}}
{{< /tab >}}
{{< tab "annotated_redacted.xlsx" >}}
```text
Binary file (XLSX, 12 KB)
```
[Download full output](/redaction/python-net/_output_files/developer-guide/basic-usage/annotation-redactions/redact_annotations/annotated_redacted.xlsx)
{{< /tab >}}
{{< /tabs >}}
---
## How to Run Examples
Path: /redaction/python-net/how-to-run-examples/
{{< alert style="warning" >}}Before running an example make sure that GroupDocs.Redaction for Python via .NET has been installed successfully.{{< /alert >}}
The complete examples project for **GroupDocs.Redaction for Python via .NET** is hosted on [GitHub](https://github.com/groupdocs-redaction/GroupDocs.Redaction-for-Python-via-.NET). It contains standalone, runnable scripts together with the sample documents they use, so the examples work out of the box.
## Prerequisites
- [Python](https://www.python.org/) 3.5 – 3.14 installed and on your `PATH`.
- [git](https://git-scm.com/) to clone the repository (or download the ZIP).
- On Linux and macOS, the native libraries listed in the [System Requirements]({{< ref "redaction/python-net/getting-started/system-requirements.md" >}}) (`libgdiplus`, `libfontconfig1`, `libicu-dev`, and fonts).
- Optionally, a GroupDocs.Redaction license to remove the [evaluation limitations]({{< ref "redaction/python-net/getting-started/licensing-and-subscription.md" >}}).
## Get the code
Clone the repository with your favourite git client, or download the ZIP from GitHub:
```bash
git clone https://github.com/groupdocs-redaction/GroupDocs.Redaction-for-Python-via-.NET.git
cd GroupDocs.Redaction-for-Python-via-.NET
```
## Project Structure
The examples live under the `Examples/` folder, organized by topic. Directory names are kebab-case and each script is standalone:
```text
GroupDocs.Redaction-for-Python-via-.NET/
├── Dockerfile
└── Examples/
├── requirements.txt
├── run_all_examples.py
├── licensing/
│ └── set_license_from_file.py
├── getting-started/
│ └── hello-world/
│ └── hello_world.py
└── developer-guide/
├── basic-usage/
│ ├── text-redactions.py
│ ├── metadata-redactions.py
│ ├── image-redactions.py
│ ├── annotation-redactions.py
│ └── remove-page-redactions.py
└── advanced-usage/
├── use-redaction-policies.py
├── loading-documents/
└── saving-documents/
```
## Setup
Create and activate a virtual environment, then install the dependencies listed in `Examples/requirements.txt`:
{{< tabs "setup-venv">}}
{{< tab "Windows" >}}
```ps
py -m venv .venv
.venv\Scripts\activate
py -m pip install -r Examples/requirements.txt
```
{{< /tab >}}
{{< tab "Linux" >}}
```bash
python3 -m venv .venv
source .venv/bin/activate
python3 -m pip install -r Examples/requirements.txt
```
{{< /tab >}}
{{< tab "macOS" >}}
```bash
python3 -m venv .venv
source .venv/bin/activate
python3 -m pip install -r Examples/requirements.txt
```
{{< /tab >}}
{{< /tabs >}}
To run the examples without evaluation limitations, point the `GROUPDOCS_LIC_PATH` environment variable at your license file. The example scripts read this variable and apply the license automatically:
{{< tabs "setup-license">}}
{{< tab "Windows" >}}
```ps
$env:GROUPDOCS_LIC_PATH = "C:\path\to\GroupDocs.Redaction.lic"
```
{{< /tab >}}
{{< tab "Linux" >}}
```bash
export GROUPDOCS_LIC_PATH="/path/to/GroupDocs.Redaction.lic"
```
{{< /tab >}}
{{< tab "macOS" >}}
```bash
export GROUPDOCS_LIC_PATH="/path/to/GroupDocs.Redaction.lic"
```
{{< /tab >}}
{{< /tabs >}}
See [Licensing and Evaluation]({{< ref "redaction/python-net/getting-started/licensing-and-subscription.md" >}}) for details on obtaining and applying a license.
## Run
Run every example at once with the runner script:
```bash
python Examples/run_all_examples.py
```
Or run a single example by passing its path directly:
```bash
python Examples/developer-guide/basic-usage/text-redactions.py
```
The repository ships with all the sample documents and resources used by the examples, so the scripts run out of the box.
{{< alert style="info" >}}Without a license the examples run in evaluation mode, which raises a `TrialLimitationsException` if more than one document is opened in the same process. The `run_all_examples.py` runner launches each example in its own process so they all complete even unlicensed, but redaction output is limited (one redaction per document, up to four replacements, and trial badges on each page).{{< /alert >}}
## Run with Docker
The repository includes a `Dockerfile` that installs the native dependencies and Python packages so you can run the examples in a clean, reproducible container. From the repository root:
```bash
docker build -t groupdocs-redaction-examples .
docker run --rm groupdocs-redaction-examples
```
To use a license inside the container, mount it and pass `GROUPDOCS_LIC_PATH`:
```bash
docker run --rm \
-v /path/to/GroupDocs.Redaction.lic:/app/GroupDocs.Redaction.lic:ro \
-e GROUPDOCS_LIC_PATH=/app/GroupDocs.Redaction.lic \
groupdocs-redaction-examples
```
## Continuous integration
Because the examples run headlessly and exit with a non-zero status on failure, they fit naturally into a CI pipeline. Install `Examples/requirements.txt`, supply the license through the `GROUPDOCS_LIC_PATH` environment variable (store the license as a protected secret), make sure the Linux native dependencies are present on the runner, and invoke `python Examples/run_all_examples.py` as a build step. The provided `Dockerfile` is a convenient base image for such jobs.
## Troubleshooting
- **"…rasterization / image-export step is not supported on this platform" on Linux/macOS** — expected on non-Windows in 26.6.0. The rasterized-PDF and image-redaction paths use `System.Drawing.Common`, which the bundled runtime supports only on Windows, so they raise `System.PlatformNotSupportedException`. The `run_all_examples.py` runner catches this and logs the note so the suite still completes; the example's text/metadata/annotation steps still run. To exercise rasterization and image redaction, run on Windows, or save in the original format with `SaveOptions(rasterize_to_pdf=False)`. See [System Requirements]({{< ref "redaction/python-net/getting-started/system-requirements.md" >}}) for the full platform-support matrix. Installing `libgdiplus` does **not** remove this restriction.
- **Missing or substituted fonts** — install fonts so rasterized output (on Windows) matches the original: `apt install libfontconfig1 ttf-mscorefonts-installer`.
- **ICU / globalization errors on Linux** — install ICU: `apt install libicu-dev`.
- **`TrialLimitationsException`** — you are running unlicensed in evaluation mode, which permits only one document open per process, one redaction, and up to four replacements. Set `GROUPDOCS_LIC_PATH` to a valid license to remove these limits.
## Contribute
If you would like to add or improve an example, we encourage you to contribute to the project. All examples in this repository are open source and can be freely used in your own applications. To contribute, fork the repository, edit the code, and create a pull request. We will review the changes and include them if found helpful.
---
## Technical Support
Path: /redaction/python-net/technical-support/
GroupDocs provides unlimited free technical support for all of its products. Support is available to all users, including evaluation. The support is provided at the [Free Support Forum](https://forum.groupdocs.com/) and the [Paid Support Helpdesk](https://helpdesk.groupdocs.com/).
{{< alert style="info" >}}
Please note that GroupDocs does not provide technical support over the phone. Phone support is only available for sales and purchase questions.
{{< /alert >}}
## GroupDocs Free Support Forum
If you need help with GroupDocs.Redaction, consider the following:
* Make sure you are using the latest GroupDocs.Redaction version before reporting an issue. See [PyPI](https://pypi.org/project/groupdocs-redaction-net) to find out about the latest version.
* Have a look through the forums, this documentation, and the [API Reference](https://reference.groupdocs.com/redaction/python-net/) before reporting an issue – perhaps your question has already been answered.
* Post your question at the [GroupDocs.Redaction Free Support Forum](https://forum.groupdocs.com/c/redaction), and we'll assist you. Questions are answered directly by the GroupDocs.Redaction development team.
* When expecting a reply on the forums, please allow for time zone differences.
## Paid Support Helpdesk
Paid support issues have higher priority compared to free support requests.
* Post your question at the [Paid Support Helpdesk](https://helpdesk.groupdocs.com/) to set a higher priority for the issue.
## Report an Issue or Feature Request
When posting your issue, question, or feature request with GroupDocs.Redaction, follow these simple steps to make sure it is resolved in the most efficient way:
* Include the original document and, if possible, the code snippet that is causing the problem. If you need to attach a few files, zip them into one. It is safe to attach your documents to the GroupDocs forums because only you and the GroupDocs developers will have access to the attached files.
* Add information about the environment you are facing the issue in — operating system, Python version, and GroupDocs.Redaction version.
* Try to report one issue per thread. If you have another issue, question, or feature request, please report it in a separate thread.
---
## Use advanced rasterization options
Path: /redaction/python-net/use-advanced-rasterization-options/
## Use advanced rasterization options
In order to use the advanced rasterization options you have to pass one of the options to [Save](https://reference.groupdocs.com/redaction/python-net/groupdocs.redaction/redactor/save/) method. In this case the document will be rasterized to PDF, but the scan-like effects will be applied to its pages.
The following example demonstrates how to apply the [AdvancedRasterizationOptions](https://reference.groupdocs.com/redaction/python-net/groupdocs.redaction.options/advancedrasterizationoptions/) with default settings.
{{< tabs "code-example-use-advanced-rasterization-options" >}}
{{< tab "use_advanced_rasterization_options.py" >}}
```python
from groupdocs.redaction import Redactor
from groupdocs.redaction.options import SaveOptions, AdvancedRasterizationOptions
from groupdocs.redaction.redactions import ExactPhraseRedaction, ReplacementOptions
def use_advanced_rasterization_options():
# Specify the redaction options
repl_opt = ReplacementOptions("[personal]")
ex_red = ExactPhraseRedaction("John Doe", repl_opt)
# Load the document to be redacted
with Redactor("./sample.docx") as redactor:
# Apply the redaction
redactor.apply(ex_red)
# Save the document with advanced options (convert pages into images, and save PDF with scan-like pages)
so = SaveOptions()
so.rasterization.enabled = True
so.redacted_file_suffix = "_scan"
so.rasterization.add_advanced_option(AdvancedRasterizationOptions.BORDER)
so.rasterization.add_advanced_option(AdvancedRasterizationOptions.NOISE)
so.rasterization.add_advanced_option(AdvancedRasterizationOptions.GRAYSCALE)
so.rasterization.add_advanced_option(AdvancedRasterizationOptions.TILT)
result_path = redactor.save(so)
print(f"Document redacted successfully.\nCheck output in {result_path}")
if __name__ == "__main__":
use_advanced_rasterization_options()
```
{{< /tab >}}
{{< tab "sample.docx" >}}
{{< tab-text >}}
`sample.docx` is the sample file used in this example. Click [here](/redaction/python-net/_sample_files/developer-guide/advanced-usage/saving-documents/use-advanced-rasterization-options/sample.docx) to download it.
{{< /tab-text >}}
{{< /tab >}}
{{< tab "sample.pdf" >}}
```text
Binary file (PDF, 1.0 MB)
```
[Download full output](/redaction/python-net/_output_files/developer-guide/advanced-usage/saving-documents/use-advanced-rasterization-options/use_advanced_rasterization_options/sample.pdf)
{{< /tab >}}
{{< /tabs >}}
### Use grayscale rasterization option
The following example demonstrates how to apply the grayscale advanced rasterization option.
{{< tabs "code-example-use-grayscale-rasterization-option" >}}
{{< tab "use_grayscale_rasterization_option.py" >}}
```python
from groupdocs.redaction import Redactor
from groupdocs.redaction.options import SaveOptions, AdvancedRasterizationOptions
def use_grayscale_rasterization_option():
# Load the document to be redacted
with Redactor("./sample.docx") as redactor:
# Save the document with the custom grayscale effect
so = SaveOptions()
so.rasterization.enabled = True
so.redacted_file_suffix = "_scan"
so.rasterization.add_advanced_option(AdvancedRasterizationOptions.GRAYSCALE)
result_path = redactor.save(so)
print(f"Document redacted successfully.\nCheck output in {result_path}")
if __name__ == "__main__":
use_grayscale_rasterization_option()
```
{{< /tab >}}
{{< tab "sample.docx" >}}
{{< tab-text >}}
`sample.docx` is the sample file used in this example. Click [here](/redaction/python-net/_sample_files/developer-guide/advanced-usage/saving-documents/use-advanced-rasterization-options/sample.docx) to download it.
{{< /tab-text >}}
{{< /tab >}}
{{< tab "sample.pdf" >}}
```text
Binary file (PDF, 979 KB)
```
[Download full output](/redaction/python-net/_output_files/developer-guide/advanced-usage/saving-documents/use-advanced-rasterization-options/use_grayscale_rasterization_option/sample.pdf)
{{< /tab >}}
{{< /tabs >}}
---
## Create PDF with Image Redaction
Path: /redaction/python-net/create-pdf-with-image-redaction/
In some cases you might need to redact the pages of a document as images, redacting entire areas of the page instead or in addition to a specific text. With GroupDocs.Redaction you can use the following approach:
* open the document and apply all required redactions to the document's body (text, annotations, etc.);
* save it as a rasterized PDF file (containing images of the original document's pages);
* apply ImageAreaRedaction to remove specific areas on the pages within the PDF document.
The following example demonstrates how to create a rasterized PDF from a Microsoft Word document and apply image redactions to its pages:
{{< tabs "code-example-create-pdf-with-image-redaction" >}}
{{< tab "create_pdf_with_image_redaction.py" >}}
```python
from io import BytesIO
from groupdocs.redaction import Redactor, RedactionStatus
from groupdocs.redaction.options import RasterizationOptions
from groupdocs.redaction.redactions import ImageAreaRedaction, RegionReplacementOptions
from groupdocs.pydrawing import Point, Size, Color
def create_pdf_with_image_redaction():
# Create an in-memory binary stream
stream = BytesIO()
# Load the document and rasterize it to a PDF in the stream
with Redactor("./sample.docx") as redactor:
# Save the rasterized document to the stream
ro = RasterizationOptions()
ro.enabled = True
redactor.save(stream, ro)
stream.seek(0)
# Define the position on the image
sample_point = Point(40, 160)
# Define the size of the area which needs to be redacted
sample_size = Size(350, 75)
# Define the color of redaction
color = Color.from_argb(255, 220, 20, 60)
# Specify the redaction options
repl_opt = RegionReplacementOptions(color, sample_size)
img_red = ImageAreaRedaction(sample_point, repl_opt)
# Load the stream to be redacted
with Redactor(stream) as redactor:
# Apply the redaction
result = redactor.apply(img_red)
# Re-open the rasterized PDF document to redact its pages as images
if result.status != RedactionStatus.FAILED:
# Save the document to a file and convert its pages to images
ro = RasterizationOptions()
ro.enabled = True
with open("./redacted-sample.pdf", "wb") as stream_out:
redactor.save(stream_out, ro)
print("Document redacted successfully.\nCheck output in ./redacted-sample.pdf")
else:
print("Redaction failed!")
if __name__ == "__main__":
create_pdf_with_image_redaction()
```
{{< /tab >}}
{{< tab "sample.docx" >}}
{{< tab-text >}}
`sample.docx` is the sample file used in this example. Click [here](/redaction/python-net/_sample_files/developer-guide/advanced-usage/create-pdf-with-image-redaction/sample.docx) to download it.
{{< /tab-text >}}
{{< /tab >}}
{{< tab "redacted-sample.pdf" >}}
```text
Binary file (PDF, 879 KB)
```
[Download full output](/redaction/python-net/_output_files/developer-guide/advanced-usage/create-pdf-with-image-redaction/create_pdf_with_image_redaction/redacted-sample.pdf)
{{< /tab >}}
{{< /tabs >}}
Please, note that you don't have to use GroupDocs.Redaction to create a rasterized PDF from an office document. You will be able to use it, if you don't have any other tool for that.
---
## Spreadsheet redactions
Path: /redaction/python-net/spreadsheet-redactions/
GroupDocs.Redaction allows to redact data of sensitive or private nature from your XLS, XLSX, ODS spreadsheet document formats and others. See full list at [supported document formats]({{< ref "redaction/python-net/getting-started/supported-document-formats.md" >}}) article.
## Redact spreadsheet content
{{< tabs "code-example-redact-spreadsheet-content" >}}
{{< tab "redact_spreadsheet_content.py" >}}
```python
from groupdocs.redaction import Redactor
from groupdocs.redaction.options import SaveOptions
from groupdocs.redaction.redactions import ExactPhraseRedaction, ReplacementOptions
def redact_spreadsheet_content():
# Specify the redaction options
repl_opt = ReplacementOptions("-redacted-")
ex_red = ExactPhraseRedaction("John Doe", repl_opt)
# Load the spreadsheet to be redacted
with Redactor("./sample.xlsx") as redactor:
# Apply the redaction
result = redactor.apply(ex_red)
# Save the redacted document next to the source file
so = SaveOptions()
so.add_suffix = True
so.rasterize_to_pdf = False
so.redacted_file_suffix = "redacted"
redactor.save(so)
if __name__ == "__main__":
redact_spreadsheet_content()
```
{{< /tab >}}
{{< tab "sample.xlsx" >}}
{{< tab-text >}}
`sample.xlsx` is the sample file used in this example. Click [here](/redaction/python-net/_sample_files/developer-guide/basic-usage/spreadsheet-redactions/sample.xlsx) to download it.
{{< /tab-text >}}
{{< /tab >}}
{{< tab "sample_redacted.xlsx" >}}
```text
Binary file (XLSX, 15 KB)
```
[Download full output](/redaction/python-net/_output_files/developer-guide/basic-usage/spreadsheet-redactions/redact_spreadsheet_content/sample_redacted.xlsx)
{{< /tab >}}
{{< /tabs >}}
---
## Image redactions
Path: /redaction/python-net/image-redactions/
GroupDocs.Redactions provides a set of features to redact data of sensitive nature from images of various formats like JPG, PNG, TIFF and others. See full list at [supported document formats]({{< ref "redaction/python-net/getting-started/supported-document-formats.md" >}}) article.
GroupDocs.Redaction supports two ways of redacting images, both in separate image files and embedded images:
* You can put a colored box over a given area, such as header, footer, or an area, where customer's data are expected to appear.
* You can use any 3-rd party OCR engine to process the image, search it for text and redact sensitive data within the image.
GroupDocs.Redaction for Python via .NET also allows you to change image metadata (e.g. edit EXIF data of an image or act as an "EXIF eraser").
## Redact image area
In order to redact image area, you have to use [ImageAreaRedaction](https://reference.groupdocs.com/redaction/python-net/groupdocs.redaction.redactions/imagearearedaction/) class:
{{< tabs "code-example-redact-image-area" >}}
{{< tab "redact_image_area.py" >}}
```python
from groupdocs.redaction import Redactor, RedactionStatus
from groupdocs.redaction.options import SaveOptions
from groupdocs.redaction.redactions import ImageAreaRedaction, RegionReplacementOptions
from groupdocs.pydrawing import Color, Point, Size
def redact_image_area():
# Define the top-left position of the area to redact
sample_point = Point(385, 485)
# Define the size of the area which needs to be redacted
sample_size = Size(1793, 2069)
# Define the color of the redaction box
color = Color.from_argb(255, 220, 20, 60)
# Specify the redaction options
repl_opt = RegionReplacementOptions(color, sample_size)
img_red = ImageAreaRedaction(sample_point, repl_opt)
# Load the document to be redacted
with Redactor("./sample.jpg") as redactor:
# Apply the redaction
result = redactor.apply(img_red)
if result.status != RedactionStatus.FAILED:
# By default, the redacted document is saved in PDF format
save_options = SaveOptions()
save_options.add_suffix = True
save_options.rasterize_to_pdf = True
save_options.redacted_file_suffix = "redacted"
redactor.save(save_options)
if __name__ == "__main__":
redact_image_area()
```
{{< /tab >}}
{{< tab "sample.jpg" >}}
{{< tab-text >}}
`sample.jpg` is the sample file used in this example. Click [here](/redaction/python-net/_sample_files/developer-guide/basic-usage/image-redactions/sample.jpg) to download it.
{{< /tab-text >}}
{{< /tab >}}
{{< tab "sample_redacted.pdf" >}}
```text
Binary file (PDF, 2.7 MB)
```
[Download full output](/redaction/python-net/_output_files/developer-guide/basic-usage/image-redactions/redact_image_area/sample_redacted.pdf)
{{< /tab >}}
{{< /tabs >}}
If the redaction cannot be applied to this type of files, e.g. MS Word document without embedded images, [RedactorChangeLog.Status](https://reference.groupdocs.com/redaction/python-net/groupdocs.redaction/redactorchangelog/status/) will be [RedactionStatus.Skipped](https://reference.groupdocs.com/redaction/python-net/groupdocs.redaction/redactionstatus/).
## Clean image metadata
The following example demonstrates how to edit exif data (erase them) from a photo or any other image:
{{< tabs "code-example-clean-image-metadata" >}}
{{< tab "clean_image_metadata.py" >}}
```python
from groupdocs.redaction import Redactor
from groupdocs.redaction.options import SaveOptions
from groupdocs.redaction.redactions import EraseMetadataRedaction, MetadataFilters
def clean_image_metadata():
# Specify the redaction options to remove all image metadata (e.g. EXIF)
er_opt = EraseMetadataRedaction(MetadataFilters.ALL)
# Load the image to be redacted
with Redactor("./sample.jpg") as redactor:
# Apply the redaction
result = redactor.apply(er_opt)
# Save the redacted image next to the source file
so = SaveOptions()
so.add_suffix = True
so.rasterize_to_pdf = False
so.redacted_file_suffix = "redacted"
redactor.save(so)
if __name__ == "__main__":
clean_image_metadata()
```
{{< /tab >}}
{{< tab "sample.jpg" >}}
{{< tab-text >}}
`sample.jpg` is the sample file used in this example. Click [here](/redaction/python-net/_sample_files/developer-guide/basic-usage/image-redactions/sample.jpg) to download it.
{{< /tab-text >}}
{{< /tab >}}
{{< tab "sample_redacted.jpg" >}}
```text
Binary file (JPG, 3.1 MB)
```
[Download full output](/redaction/python-net/_output_files/developer-guide/basic-usage/image-redactions/clean_image_metadata/sample_redacted.jpg)
{{< /tab >}}
{{< /tabs >}}
If the redaction cannot be applied to this type of files, e.g. BMP image, [RedactorChangeLog.Status](https://reference.groupdocs.com/redaction/python-net/groupdocs.redaction/redactorchangelog/status/) will be [RedactionStatus.Skipped](https://reference.groupdocs.com/redaction/python-net/groupdocs.redaction/redactionstatus/).
## Redact embedded images
You can redact image area within all kinds of embedded images inside a document.
The following example demonstrates how to redact all embedded images within a Microsoft Word document:
{{< tabs "code-example-redact-embedded-images" >}}
{{< tab "redact_embedded_images.py" >}}
```python
from groupdocs.redaction import Redactor, RedactionStatus
from groupdocs.redaction.options import SaveOptions
from groupdocs.redaction.redactions import ImageAreaRedaction, RegionReplacementOptions
from groupdocs.pydrawing import Color, Point, Size
def redact_embedded_images():
# Define the top-left position of the area to redact
sample_point = Point(516, 311)
# Define the size of the area which needs to be redacted
sample_size = Size(170, 35)
# Define the color of the redaction box
color = Color.from_argb(255, 220, 20, 60)
# Specify the redaction options
repl_opt = RegionReplacementOptions(color, sample_size)
img_red = ImageAreaRedaction(sample_point, repl_opt)
# Load the document to be redacted
with Redactor("./sample.docx") as redactor:
# Apply the redaction to all embedded images
result = redactor.apply(img_red)
if result.status != RedactionStatus.FAILED:
# By default, the redacted document is saved in PDF format
save_options = SaveOptions()
save_options.add_suffix = True
save_options.rasterize_to_pdf = True
save_options.redacted_file_suffix = "redacted"
redactor.save(save_options)
if __name__ == "__main__":
redact_embedded_images()
```
{{< /tab >}}
{{< tab "sample.docx" >}}
{{< tab-text >}}
`sample.docx` is the sample file used in this example. Click [here](/redaction/python-net/_sample_files/developer-guide/basic-usage/image-redactions/sample.docx) to download it.
{{< /tab-text >}}
{{< /tab >}}
{{< tab "sample_redacted.pdf" >}}
```text
Binary file (PDF, 1022 KB)
```
[Download full output](/redaction/python-net/_output_files/developer-guide/basic-usage/image-redactions/redact_embedded_images/sample_redacted.pdf)
{{< /tab >}}
{{< /tabs >}}
If the redaction cannot be applied to this type of files, e.g. a spreadsheet document, [RedactorChangeLog.Status](https://reference.groupdocs.com/redaction/python-net/groupdocs.redaction/redactorchangelog/status/) will be [RedactionStatus.Skipped](https://reference.groupdocs.com/redaction/python-net/groupdocs.redaction/redactionstatus/).
## Multi-frame images
You can remove frames from a multi-frame image with a given origin and frame count. For additional information look at [remove page redactions]({{< ref "redaction/python-net/developer-guide/basic-usage/remove-page-redactions.md" >}}) article.
Some image formats, such as DjVu documents, require [pre-rasterization]({{< ref "redaction/python-net/developer-guide/advanced-usage/loading-documents/pre-rasterize.md" >}}) and further saving in PDF format.
---
## Remove page redactions
Path: /redaction/python-net/remove-page-redactions/
GroupDocs.Redaction allows to easily to remove pages from PDF documents, slides from presentations and worksheets from spreadsheet documents.
With GroupDocs.Redaction API you can remove pages by specifying the page range by means of its relative position (the beginning or the end), zero-based index and the count of pages to remove. At this time the supported formats are: PDF, presentations (Microsoft PowerPoint, OpenOffice Presentations), word processing documents (Microsoft Word, OpenOffice Texts, Rich Text Files), spreadsheets (Microsoft Excel, OpenOffice Spreadsheets, etc.) and multi-frame images.
## Remove page range
In the example below, we remove 2nd, 3rd and 4th pages from the document, if the document has enough pages:
{{< tabs "code-example-remove-page-range" >}}
{{< tab "remove_page_range.py" >}}
```python
from groupdocs.redaction import Redactor
from groupdocs.redaction.options import SaveOptions
from groupdocs.redaction.redactions import RemovePageRedaction, PageSeekOrigin
def remove_page_range():
# Load the document to be redacted
with Redactor("./multipage_sample.pdf") as redactor:
# Get document info
doc_info = redactor.get_document_info()
# Requires at least 4 pages
if doc_info.page_count > 3:
# Remove 3 pages starting from the 2nd one (zero-based index 1)
rem_opt = RemovePageRedaction(PageSeekOrigin.BEGIN, 1, 3)
# Apply the redaction
result = redactor.apply(rem_opt)
# Save the redacted document next to the source file
so = SaveOptions()
so.add_suffix = True
so.rasterize_to_pdf = False
so.redacted_file_suffix = "redacted"
redactor.save(so)
if __name__ == "__main__":
remove_page_range()
```
{{< /tab >}}
{{< tab "multipage_sample.pdf" >}}
{{< tab-text >}}
`multipage_sample.pdf` is the sample file used in this example. Click [here](/redaction/python-net/_sample_files/developer-guide/basic-usage/remove-page-redactions/multipage_sample.pdf) to download it.
{{< /tab-text >}}
{{< /tab >}}
{{< /tabs >}}
## Remove last page
In some cases you might need to delete the last page or a number of pages, no matter how many pages are there.
The following example demonstrates how to remove the last page from a document:
{{< tabs "code-example-remove-last-page" >}}
{{< tab "remove_last_page.py" >}}
```python
from groupdocs.redaction import Redactor
from groupdocs.redaction.options import SaveOptions
from groupdocs.redaction.redactions import RemovePageRedaction, PageSeekOrigin
def remove_last_page():
# Remove 1 page counting from the end of the document
rem_opt = RemovePageRedaction(PageSeekOrigin.END, 0, 1)
# Load the document to be redacted
with Redactor("./multipage_sample.pdf") as redactor:
# Get document info
doc_info = redactor.get_document_info()
# Requires at least 2 pages so the document is not left empty
if doc_info.page_count > 1:
# Apply the redaction
result = redactor.apply(rem_opt)
# Save the redacted document next to the source file
so = SaveOptions()
so.add_suffix = True
so.rasterize_to_pdf = False
so.redacted_file_suffix = "redacted"
redactor.save(so)
if __name__ == "__main__":
remove_last_page()
```
{{< /tab >}}
{{< tab "multipage_sample.pdf" >}}
{{< tab-text >}}
`multipage_sample.pdf` is the sample file used in this example. Click [here](/redaction/python-net/_sample_files/developer-guide/basic-usage/remove-page-redactions/multipage_sample.pdf) to download it.
{{< /tab-text >}}
{{< /tab >}}
{{< tab "multipage_sample_redacted.pdf" >}}
```text
Binary file (PDF, 190 KB)
```
[Download full output](/redaction/python-net/_output_files/developer-guide/basic-usage/remove-page-redactions/remove_last_page/multipage_sample_redacted.pdf)
{{< /tab >}}
{{< /tabs >}}
## Remove frame from image
In case of a multi-frame image you might need to delete a number of frames (treated as "pages").
The following example demonstrates how to remove 3 frames from an animated GIF image:
{{< tabs "code-example-remove-frame-from-image" >}}
{{< tab "remove_frame_from_image.py" >}}
```python
from groupdocs.redaction import Redactor
from groupdocs.redaction.options import SaveOptions
from groupdocs.redaction.redactions import RemovePageRedaction, PageSeekOrigin
def remove_frame_from_image():
# Remove frames starting from the 3rd one (zero-based index 2)
rem_opt = RemovePageRedaction(PageSeekOrigin.BEGIN, 2, 5)
# Load the multi-frame image to be redacted
with Redactor("./sample.gif") as redactor:
# Get document info
doc_info = redactor.get_document_info()
# Requires at least 7 frames
if doc_info.page_count >= 7:
# Apply the redaction
result = redactor.apply(rem_opt)
# Save the redacted image next to the source file
so = SaveOptions()
so.add_suffix = True
so.rasterize_to_pdf = False
so.redacted_file_suffix = "redacted"
redactor.save(so)
if __name__ == "__main__":
remove_frame_from_image()
```
{{< /tab >}}
{{< tab "sample.gif" >}}
{{< tab-text >}}
`sample.gif` is the sample file used in this example. Click [here](/redaction/python-net/_sample_files/developer-guide/basic-usage/remove-page-redactions/sample.gif) to download it.
{{< /tab-text >}}
{{< /tab >}}
{{< tab "sample_redacted.gif" >}}
```text
Binary file (GIF, 704 KB)
```
[Download full output](/redaction/python-net/_output_files/developer-guide/basic-usage/remove-page-redactions/remove_frame_from_image/sample_redacted.gif)
{{< /tab >}}
{{< /tabs >}}