Python API Reference ==================== .. module:: pdftl.api This reference documents the dynamic Python API exposed by ``pdftl``. All operations return an :class:`pdftl.core.types.OpResult` object. .. note:: These functions are generated dynamically at runtime via ``pdftl.api``. .. py:function:: add_bookmarks(*, inputs: list[str] = None, opened_pdfs: list[pikepdf._core.Pdf] = None, operation_args: list[str] = None, password: str = None, output: str = None, run_cli_hook: bool = False, full_result: bool = False, aliases: dict[str, typing.Any] = None, options: dict[str, typing.Any] = None) -> pdftl.core.core_types.OpResult Add one or more top-level bookmarks to a PDF outline. .. py:function:: add_text(*, inputs: list[str] = None, opened_pdfs: list[pikepdf._core.Pdf] = None, operation_args: list[str] = None, password: str = None, output: str = None, run_cli_hook: bool = False, full_result: bool = False, aliases: dict[str, typing.Any] = None, options: dict[str, typing.Any] = None) -> pdftl.core.core_types.OpResult Applies all parsed add_text rules to a PDF **in-place**. This function coordinates the parser and the TextDrawer to apply text overlays to the input PDF. .. py:function:: attach_files(*, inputs: list[str] = None, opened_pdfs: list[pikepdf._core.Pdf] = None, operation_args: list[str] = None, password: str = None, output: str = None, run_cli_hook: bool = False, full_result: bool = False, aliases: dict[str, typing.Any] = None, options: dict[str, typing.Any] = None) -> pdftl.core.core_types.OpResult Attach files to a PDF document, according to the specified options .. py:function:: background(*, inputs: list[str] = None, opened_pdfs: list[pikepdf._core.Pdf] = None, operation_args: list[str] = None, password: str = None, output: str = None, run_cli_hook: bool = False, full_result: bool = False, aliases: dict[str, typing.Any] = None, options: dict[str, typing.Any] = None) -> pdftl.core.core_types.OpResult Apply overlay or underlay with optional OCG layering and page-range filtering. .. py:function:: booklet(*, inputs: list[str] = None, opened_pdfs: list[pikepdf._core.Pdf] = None, operation_args: list[str] = None, password: str = None, output: str = None, run_cli_hook: bool = False, full_result: bool = False, aliases: dict[str, typing.Any] = None, options: dict[str, typing.Any] = None) -> 'OpResult' Imposes pages into a booklet sequence. .. py:function:: burst(*, inputs: list[str] = None, opened_pdfs: list[pikepdf._core.Pdf] = None, operation_args: list[str] = None, password: str = None, output: str = None, run_cli_hook: bool = False, full_result: bool = False, aliases: dict[str, typing.Any] = None, options: dict[str, typing.Any] = None) -> pdftl.core.core_types.OpResult Split one or more PDFs into multiple files, single-page files by default. Args: opened_pdfs (list): A list of opened PDF files to burst operation_args (list): User-supplied arguments output_pattern (str): A C-style format string for the output filenames, e.g., "page_%03d.pdf". Return: the first input pdf (for pipeline chainability) Note: Uses the hook side-effect to actually burst Bugs: * Discards various parts of the PDF file that may still be relevant to single-page files, e.g., internal links .. py:function:: cat(*, inputs: list[str] = None, opened_pdfs: list[pikepdf._core.Pdf] = None, operation_args: list[str] = None, password: str = None, output: str = None, run_cli_hook: bool = False, full_result: bool = False, aliases: dict[str, typing.Any] = None, options: dict[str, typing.Any] = None) -> pdftl.core.core_types.OpResult Concatenates pages from input PDFs into a new PDF, then rebuilds all links and named destinations, including transforming link target coordinates. .. py:function:: chop(*, inputs: list[str] = None, opened_pdfs: list[pikepdf._core.Pdf] = None, operation_args: list[str] = None, password: str = None, output: str = None, run_cli_hook: bool = False, full_result: bool = False, aliases: dict[str, typing.Any] = None, options: dict[str, typing.Any] = None) -> pdftl.core.core_types.OpResult Chops specified pages of a PDF into multiple smaller pages. BUG FIXME: currently does strange things with page rotation (pages out of order?) .. py:function:: clip(*, inputs: list[str] = None, opened_pdfs: list[pikepdf._core.Pdf] = None, operation_args: list[str] = None, password: str = None, output: str = None, run_cli_hook: bool = False, full_result: bool = False, aliases: dict[str, typing.Any] = None, options: dict[str, typing.Any] = None) -> pdftl.core.core_types.OpResult Crop or clip pages in a PDF using specs like '1-3(10pt,5%)'. .. py:function:: crop(*, inputs: list[str] = None, opened_pdfs: list[pikepdf._core.Pdf] = None, operation_args: list[str] = None, password: str = None, output: str = None, run_cli_hook: bool = False, full_result: bool = False, aliases: dict[str, typing.Any] = None, options: dict[str, typing.Any] = None) -> pdftl.core.core_types.OpResult Crop or clip pages in a PDF using specs like '1-3(10pt,5%)'. .. py:function:: delete(*, inputs: list[str] = None, opened_pdfs: list[pikepdf._core.Pdf] = None, operation_args: list[str] = None, password: str = None, output: str = None, run_cli_hook: bool = False, full_result: bool = False, aliases: dict[str, typing.Any] = None, options: dict[str, typing.Any] = None) -> pdftl.core.core_types.OpResult Deletes pages from input PDF, and otherwise leaves the PDF structure essentially unchanged. .. py:function:: delete_annots(*, inputs: list[str] = None, opened_pdfs: list[pikepdf._core.Pdf] = None, operation_args: list[str] = None, password: str = None, output: str = None, run_cli_hook: bool = False, full_result: bool = False, aliases: dict[str, typing.Any] = None, options: dict[str, typing.Any] = None) -> pdftl.core.core_types.OpResult Delete annotations from a PDF, optionally filtered by selector specs. Without selectors, deletes all annotations from all pages. .. py:function:: delete_attachments(*, inputs: list[str] = None, opened_pdfs: list[pikepdf._core.Pdf] = None, operation_args: list[str] = None, password: str = None, output: str = None, run_cli_hook: bool = False, full_result: bool = False, aliases: dict[str, typing.Any] = None, options: dict[str, typing.Any] = None) -> pdftl.core.core_types.OpResult Deletes attachments matching criteria from the document NameTree and scrubs corresponding page annotations. .. py:function:: delete_blank(*, inputs: list[str] = None, opened_pdfs: list[pikepdf._core.Pdf] = None, operation_args: list[str] = None, password: str = None, output: str = None, run_cli_hook: bool = False, full_result: bool = False, aliases: dict[str, typing.Any] = None, options: dict[str, typing.Any] = None) -> pdftl.core.core_types.OpResult Delete pages that are blank or visually uniform. Each spec is evaluated independently. A page is deleted if any spec marks it as blank. Deletion happens in reverse page order so indices remain valid throughout. .. py:function:: delete_bookmarks(*, inputs: list[str] = None, opened_pdfs: list[pikepdf._core.Pdf] = None, operation_args: list[str] = None, password: str = None, output: str = None, run_cli_hook: bool = False, full_result: bool = False, aliases: dict[str, typing.Any] = None, options: dict[str, typing.Any] = None) -> pdftl.core.core_types.OpResult Delete bookmarks from a PDF outline, optionally filtered by page spec. .. py:function:: delete_images(*, inputs: list[str] = None, opened_pdfs: list[pikepdf._core.Pdf] = None, operation_args: list[str] = None, password: str = None, output: str = None, run_cli_hook: bool = False, full_result: bool = False, aliases: dict[str, typing.Any] = None, options: dict[str, typing.Any] = None) -> pdftl.core.core_types.OpResult Overwrites images matching criteria with 1x1 transparent stubs. Defaults to global search if no page range is provided. .. py:function:: dump_annots(*, inputs: list[str] = None, opened_pdfs: list[pikepdf._core.Pdf] = None, operation_args: list[str] = None, password: str = None, output: str = None, run_cli_hook: bool = False, full_result: bool = False, aliases: dict[str, typing.Any] = None, options: dict[str, typing.Any] = None) -> pdftl.core.core_types.OpResult Dumps all annotations from a PDF in JSON format, with compact arrays. Optionally filtered by selector specs using the same syntax as modify_annots. .. py:function:: dump_bookmarks(*, inputs: list[str] = None, opened_pdfs: list[pikepdf._core.Pdf] = None, operation_args: list[str] = None, password: str = None, output: str = None, run_cli_hook: bool = False, full_result: bool = False, aliases: dict[str, typing.Any] = None, options: dict[str, typing.Any] = None) -> pdftl.core.core_types.OpResult Extracts the document's Table of Contents (bookmarks) into a highly readable and editable YAML format (or JSON). This faithful extraction preserves both the hierarchical structure and the complex properties of your bookmarks. The resulting file can be easily edited in any text editor and applied back to the same (or a different) PDF using the `update_bookmarks` operation. ### Supported Bookmark Properties Each bookmark node is represented as a dictionary (key-value mapping). The extractor natively supports and outputs the following properties: * **`title`**: The display text of the bookmark. * **`page`**: The 1-indexed target page number. * **`children`**: A nested list of sub-bookmarks to maintain outline hierarchy. * **`color`**: An RGB array for the bookmark text color (e.g., `[1.0, 0.0, 0.0]` for red). * **`bold`** / **`italic`**: Boolean flags for text styling (`true` or `false`). * **`uri`**: An external web link (used if the bookmark points to a URL rather than a page). * **`dest`**: A string reference to a Named Destination embedded inside the PDF. * **`view`**: The precise zoom/viewport array (e.g., `["XYZ", 0, 700, 2.5]`, `["FitH", 500]`). ### Format Example ```yaml - title: Chapter 1 page: 1 bold: true children: - title: Sub-section A page: 2 view: ["FitH", 800] - title: Important Chart page: 3 color: [1.0, 0.0, 0.0] - title: External Resources uri: [https://example.com](https://example.com) ``` ### Dependency note YAML extraction requires the `pyyaml` library. If it is not installed, you can install it via `pip install pdftl[yaml-bookmarks]`, or simply use the `json` flag to extract using Python's standard JSON library instead. .. py:function:: dump_colorspaces(*, inputs: list[str] = None, opened_pdfs: list[pikepdf._core.Pdf] = None, operation_args: list[str] = None, password: str = None, output: str = None, run_cli_hook: bool = False, full_result: bool = False, aliases: dict[str, typing.Any] = None, options: dict[str, typing.Any] = None) -> pdftl.core.core_types.OpResult Report color spaces used throughout a PDF document. .. py:function:: dump_data(*, inputs: list[str] = None, opened_pdfs: list[pikepdf._core.Pdf] = None, operation_args: list[str] = None, password: str = None, output: str = None, run_cli_hook: bool = False, full_result: bool = False, aliases: dict[str, typing.Any] = None, options: dict[str, typing.Any] = None) -> pdftl.core.core_types.OpResult Imitate pdftk's dump_data output, writing to a file or stdout. .. py:function:: dump_data_annots(*, inputs: list[str] = None, opened_pdfs: list[pikepdf._core.Pdf] = None, operation_args: list[str] = None, password: str = None, output: str = None, run_cli_hook: bool = False, full_result: bool = False, aliases: dict[str, typing.Any] = None, options: dict[str, typing.Any] = None) -> pdftl.core.core_types.OpResult Dumps annotation data from a PDF in pdftk style .. py:function:: dump_data_fields(*, inputs: list[str] = None, opened_pdfs: list[pikepdf._core.Pdf] = None, operation_args: list[str] = None, password: str = None, output: str = None, run_cli_hook: bool = False, full_result: bool = False, aliases: dict[str, typing.Any] = None, options: dict[str, typing.Any] = None) -> pdftl.core.core_types.OpResult Extracts form field data from the PDF using a Hybrid Tree Walk. .. py:function:: dump_data_fields_utf8(*, inputs: list[str] = None, opened_pdfs: list[pikepdf._core.Pdf] = None, operation_args: list[str] = None, password: str = None, output: str = None, run_cli_hook: bool = False, full_result: bool = False, aliases: dict[str, typing.Any] = None, options: dict[str, typing.Any] = None) -> pdftl.core.core_types.OpResult Extracts form field data from the PDF using a Hybrid Tree Walk. .. py:function:: dump_data_utf8(*, inputs: list[str] = None, opened_pdfs: list[pikepdf._core.Pdf] = None, operation_args: list[str] = None, password: str = None, output: str = None, run_cli_hook: bool = False, full_result: bool = False, aliases: dict[str, typing.Any] = None, options: dict[str, typing.Any] = None) -> pdftl.core.core_types.OpResult Imitate pdftk's dump_data output, writing to a file or stdout. .. py:function:: dump_dests(*, inputs: list[str] = None, opened_pdfs: list[pikepdf._core.Pdf] = None, operation_args: list[str] = None, password: str = None, output: str = None, run_cli_hook: bool = False, full_result: bool = False, aliases: dict[str, typing.Any] = None, options: dict[str, typing.Any] = None) -> pdftl.core.core_types.OpResult Traverses the /Dests name tree of a PDF using pikepdf.NameTree. This provides a robust, iterable interface to the destinations. .. py:function:: dump_encryption(*, inputs: list[str] = None, opened_pdfs: list[pikepdf._core.Pdf] = None, operation_args: list[str] = None, password: str = None, output: str = None, run_cli_hook: bool = False, full_result: bool = False, aliases: dict[str, typing.Any] = None, options: dict[str, typing.Any] = None) -> pdftl.core.core_types.OpResult Dumps comprehensive encryption and permission data from a PDF. .. py:function:: dump_files(*, inputs: list[str] = None, opened_pdfs: list[pikepdf._core.Pdf] = None, operation_args: list[str] = None, password: str = None, output: str = None, run_cli_hook: bool = False, full_result: bool = False, aliases: dict[str, typing.Any] = None, options: dict[str, typing.Any] = None) -> pdftl.core.core_types.OpResult List files attached to the PDF. Returns a list of dicts: {'name': str, 'size': int, 'location': str}. .. py:function:: dump_images(*, inputs: list[str] = None, opened_pdfs: list[pikepdf._core.Pdf] = None, operation_args: list[str] = None, password: str = None, output: str = None, run_cli_hook: bool = False, full_result: bool = False, aliases: dict[str, typing.Any] = None, options: dict[str, typing.Any] = None) -> pdftl.core.core_types.OpResult Dump embedded image metadata of a PDF file. .. py:function:: dump_layers(*, inputs: list[str] = None, opened_pdfs: list[pikepdf._core.Pdf] = None, operation_args: list[str] = None, password: str = None, output: str = None, run_cli_hook: bool = False, full_result: bool = False, aliases: dict[str, typing.Any] = None, options: dict[str, typing.Any] = None) -> pdftl.core.core_types.OpResult Extract OCG (Layer) data and write as JSON. .. py:function:: dump_signatures(*, inputs: list[str] = None, opened_pdfs: list[pikepdf._core.Pdf] = None, operation_args: list[str] = None, password: str = None, output: str = None, run_cli_hook: bool = False, full_result: bool = False, aliases: dict[str, typing.Any] = None, options: dict[str, typing.Any] = None) -> pdftl.core.core_types.OpResult Validate PDF signatures and returns a list of validation results. .. py:function:: dump_text(*, inputs: list[str] = None, opened_pdfs: list[pikepdf._core.Pdf] = None, operation_args: list[str] = None, password: str = None, output: str = None, run_cli_hook: bool = False, full_result: bool = False, aliases: dict[str, typing.Any] = None, options: dict[str, typing.Any] = None) -> pdftl.core.core_types.OpResult Dump text content of a PDF file. .. py:function:: fill_form(*, inputs: list[str] = None, opened_pdfs: list[pikepdf._core.Pdf] = None, operation_args: list[str] = None, password: str = None, output: str = None, run_cli_hook: bool = False, full_result: bool = False, aliases: dict[str, typing.Any] = None, options: dict[str, typing.Any] = None) -> pdftl.core.core_types.OpResult Fill in a form, treating the first argument as a filename (or similar) for data .. py:function:: filter(*, inputs: list[str] = None, opened_pdfs: list[pikepdf._core.Pdf] = None, operation_args: list[str] = None, password: str = None, output: str = None, run_cli_hook: bool = False, full_result: bool = False, aliases: dict[str, typing.Any] = None, options: dict[str, typing.Any] = None) -> pdftl.core.core_types.OpResult Return the given PDF. .. py:function:: generate_fdf(*, inputs: list[str] = None, opened_pdfs: list[pikepdf._core.Pdf] = None, operation_args: list[str] = None, password: str = None, output: str = None, run_cli_hook: bool = False, full_result: bool = False, aliases: dict[str, typing.Any] = None, options: dict[str, typing.Any] = None) -> pdftl.core.core_types.OpResult Output FDF data for the given PDF .. py:function:: highlight(*, inputs: list[str] = None, opened_pdfs: list[pikepdf._core.Pdf] = None, operation_args: list[str] = None, password: str = None, output: str = None, run_cli_hook: bool = False, full_result: bool = False, aliases: dict[str, typing.Any] = None, options: dict[str, typing.Any] = None) -> pdftl.core.core_types.OpResult Applies all parsed highlight rules to a PDF in-place. .. py:function:: inject(*, inputs: list[str] = None, opened_pdfs: list[pikepdf._core.Pdf] = None, operation_args: list[str] = None, password: str = None, output: str = None, run_cli_hook: bool = False, full_result: bool = False, aliases: dict[str, typing.Any] = None, options: dict[str, typing.Any] = None) -> pdftl.core.core_types.OpResult Injects code at the start and/or end of page content streams. .. py:function:: insert(*, inputs: list[str] = None, opened_pdfs: list[pikepdf._core.Pdf] = None, operation_args: list[str] = None, password: str = None, output: str = None, run_cli_hook: bool = False, full_result: bool = False, aliases: dict[str, typing.Any] = None, options: dict[str, typing.Any] = None) -> pdftl.core.core_types.OpResult Insert blank pages into the PDF. .. py:function:: modify_annots(*, inputs: list[str] = None, opened_pdfs: list[pikepdf._core.Pdf] = None, operation_args: list[str] = None, password: str = None, output: str = None, run_cli_hook: bool = False, full_result: bool = False, aliases: dict[str, typing.Any] = None, options: dict[str, typing.Any] = None) -> pdftl.core.core_types.OpResult Modifies properties of existing annotations in a PDF. .. py:function:: modify_layers(*, inputs: list[str] = None, opened_pdfs: list[pikepdf._core.Pdf] = None, operation_args: list[str] = None, password: str = None, output: str = None, run_cli_hook: bool = False, full_result: bool = False, aliases: dict[str, typing.Any] = None, options: dict[str, typing.Any] = None) -> pdftl.core.core_types.OpResult The `modify_layers` operation allows you to alter Optional Content Groups (layers) in a PDF. You can permanently merge/strip them, or change their default visibility and behavior. The command reads a sequence of action-target pairs. If no target is provided after an action, it defaults to affecting "all" layers. ### Available Actions **Structural (Permanent):** * `merge`: The visual content of the layer is permanently baked into the page. The layer is removed from the PDF's layer menu. * `strip`: The visual content of the layer is completely deleted from the document, and the layer is removed from the PDF's layer menu. **State & Behavior (Non-destructive):** * `show` / `hide`: Sets the default visibility when the document is opened. * `lock` / `unlock`: Prevents/allows the user from toggling the layer in viewers. * `print` / `noprint`: Overrides behavior to force layer visibility ON or OFF when printing. * `screen` / `noscreen`: Overrides behavior to force layer visibility ON or OFF on digital displays. **Utility:** * `keep`: Used primarily to exclude a specific layer when targeting "all" others. *Note on State vs. Usage: Layer visibility on screen (`show`/`hide`) is independent of its visibility when printing. Modifying a usage state (like `noprint`) without changing its base state will leave its on-screen visibility unchanged.* ### Target Specifications * `name=`: Sloppy match. Applies the action to **all** layers with this name. * `id=`: Strict match. Applies the action to the exact underlying PDF object. * `all`: Explicitly targets all layers. * ``: If no `key=` prefix is provided, it defaults to a `name=` match. .. py:function:: montage(*, inputs: list[str] = None, opened_pdfs: list[pikepdf._core.Pdf] = None, operation_args: list[str] = None, password: str = None, output: str = None, run_cli_hook: bool = False, full_result: bool = False, aliases: dict[str, typing.Any] = None, options: dict[str, typing.Any] = None) -> pdftl.core.core_types.OpResult Imposes pages onto new canvas pages based on a grid or layout strategy. .. py:function:: move(*, inputs: list[str] = None, opened_pdfs: list[pikepdf._core.Pdf] = None, operation_args: list[str] = None, password: str = None, output: str = None, run_cli_hook: bool = False, full_result: bool = False, aliases: dict[str, typing.Any] = None, options: dict[str, typing.Any] = None) -> pdftl.core.core_types.OpResult CLI Adapter for `move`: Parses string arguments into a spec, then runs logic. .. py:function:: multibackground(*, inputs: list[str] = None, opened_pdfs: list[pikepdf._core.Pdf] = None, operation_args: list[str] = None, password: str = None, output: str = None, run_cli_hook: bool = False, full_result: bool = False, aliases: dict[str, typing.Any] = None, options: dict[str, typing.Any] = None) -> pdftl.core.core_types.OpResult Apply overlay or underlay with optional OCG layering and page-range filtering. .. py:function:: multistamp(*, inputs: list[str] = None, opened_pdfs: list[pikepdf._core.Pdf] = None, operation_args: list[str] = None, password: str = None, output: str = None, run_cli_hook: bool = False, full_result: bool = False, aliases: dict[str, typing.Any] = None, options: dict[str, typing.Any] = None) -> pdftl.core.core_types.OpResult Apply overlay or underlay with optional OCG layering and page-range filtering. .. py:function:: mutate_content(*, inputs: list[str] = None, opened_pdfs: list[pikepdf._core.Pdf] = None, operation_args: list[str] = None, password: str = None, output: str = None, run_cli_hook: bool = False, full_result: bool = False, aliases: dict[str, typing.Any] = None, options: dict[str, typing.Any] = None) -> pdftl.core.core_types.OpResult The `mutate_content` operation allows you to run custom Python logic against the raw instruction streams of a PDF. You can specify your own Python script, and the function from that script to run. The default function search for if no function is specified is `mutate`. ### The Context Dictionary Your function receives a `context` dictionary with the following keys: - `pdf`: The current `pikepdf.Pdf` object. - `page_num`: The current page number (1-indexed) or `None` for XObjects. - `is_xobject`: Boolean, `True` if mutating a Form XObject. - `object`: the `pikepdf.Object` (either a page or an XObject) containing the content stream. - `args`: A list of extra arguments passed via CLI after the script name. ### Passing Arguments You can pass custom parameters to your script: `pdftl in.pdf mutate_content script.py 1.5 2.0 output out.pdf` In this case, `context['args']` would be `['1.5', '2.0']`. .. py:function:: normalize(*, inputs: list[str] = None, opened_pdfs: list[pikepdf._core.Pdf] = None, operation_args: list[str] = None, password: str = None, output: str = None, run_cli_hook: bool = False, full_result: bool = False, aliases: dict[str, typing.Any] = None, options: dict[str, typing.Any] = None) -> pdftl.core.core_types.OpResult Normalize page content streams. .. py:function:: optimize_images(*, inputs: list[str] = None, opened_pdfs: list[pikepdf._core.Pdf] = None, operation_args: list[str] = None, password: str = None, output: str = None, run_cli_hook: bool = False, full_result: bool = False, aliases: dict[str, typing.Any] = None, options: dict[str, typing.Any] = None) -> pdftl.core.core_types.OpResult Optimize images in the given PDF. .. py:function:: place(*, inputs: list[str] = None, opened_pdfs: list[pikepdf._core.Pdf] = None, operation_args: list[str] = None, password: str = None, output: str = None, run_cli_hook: bool = False, full_result: bool = False, aliases: dict[str, typing.Any] = None, options: dict[str, typing.Any] = None) -> pdftl.core.core_types.OpResult Applies geometric transformations (direct similarities) to the content of selected pages. **`` syntax:** `[](...)` **Operations:** * `shift=dx, dy` Moves content by the specified x and y distances. Supports units (pt, in, cm, mm) and percentages relative to page size. Example: `shift=1in, 50%` * `scale=factor[:anchor]` Scales content by a multiplier (e.g., 0.5 for half size). Optional anchor determines the fixed point (default: center). * `spin=angle[:anchor]` Rotates content by degrees clockwise. Optional anchor determines the pivot point (default: center). More than one operation can be given. They should be separated by semicolons, '`;`'. Operations are applied in the order they appear, from left to right. **Anchors:** Anchors define the center of scaling or rotation. * **Named:** `center` (default), `top-left`, `top`, `top-right`, `left`, `right`, `bottom-left`, `bottom`, `bottom-right`. * **Coordinate:** `x,y` (e.g., `0,0` for bottom-left corner). .. py:function:: render(*, inputs: list[str] = None, opened_pdfs: list[pikepdf._core.Pdf] = None, operation_args: list[str] = None, password: str = None, output: str = None, run_cli_hook: bool = False, full_result: bool = False, aliases: dict[str, typing.Any] = None, options: dict[str, typing.Any] = None) -> pdftl.core.core_types.OpResult The `render` operation converts PDF pages into raster images or a single PDF. It respects page rotation, cropping, and current pipeline modifications. You can specify a page range using standard page specifications (e.g., `1-5`, `even`). If no pages are specified, all pages are rendered. The `dpi=` argument sets the raster image resolution, in dots per inch (default: 150). It must be a positive number. The default `