pdf-processor · git:20261005.032b435 · 2026-10-05 · sha256 8f365d3796607a86
pdf-processor git:20261005.032b435A
Immutable. This exact content never changes and is served at /api/v1/blob/8f365d3796607a86.
---
name: pdf-processor
description: "Use whenever a PDF is mentioned or is the input/output: read or extract text/tables/images, OCR scans, create/export, merge, split, reorder, rotate, watermark, fill forms, redact, compress, encrypt, or inspect PDF metadata. Inspect the PDF structure and distinguish searchable text from scanned pages. Do not treat a raster image of text as editable source or promise that redaction is secure unless underlying content was removed and verified."
license: MIT
compatibility: Python 3.8+; pypdf for structural operations; pdfplumber for layout/table extraction; reportlab for basic generation; Poppler or MuPDF tools for rendering/OCR workflows. The inspection script uses Python standard library only.
---
# PDF Processor
PDF workflows must preserve page order, geometry, text, and security expectations. First identify whether each page contains text, vectors, raster scans, or a mixture. Choose a method based on the task; verify the saved PDF, not only the intermediate objects.
## Shared research and assets
When external facts, images, tables or a website's visual style are needed, read
[`references/shared-scraping.md`](references/shared-scraping.md), which connects
this skill to `ultimate-scrape-skill`. Skip scraping for local-only PDF operations.
## Workflow
1. **Protect source material.** Never overwrite the only input. Treat PDFs and embedded links/attachments as untrusted. Do not execute scripts, open embedded files, submit forms, or follow links unless explicitly authorized.
2. **Inspect.** Run `python scripts/inspect_pdf.py file.pdf --json` to check ZIP-independent PDF header/trailer, page count, encryption flag when readable, and metadata basics. If tools are available, inspect text with `pdftotext -layout`, metadata with `pdfinfo`, and representative rendered pages. A scan with little/no text needs OCR.
3. **Clarify consequential choices.** Preserve original page order unless asked to change it. For form filling, identify fields and flattening expectations. For redaction, distinguish a visible black box (not redaction) from irreversible removal. For encryption, determine password/permissions and handle secrets without logging them.
4. **Choose an appropriate tool.** Use pypdf for page-level changes, pdfplumber for layout-aware extraction and tables, ReportLab for authored PDFs, and OCR/rendering tools for image-only pages. Preserve vector/text quality when feasible.
5. **Perform the task.** Write to a new output file. Keep page rotation, boxes, bookmarks, metadata, tags, links and encryption consistent with requirements. Be cautious with digitally signed PDFs: modification invalidates signatures. A redacted area must be removed from underlying content and, when needed, sanitized from metadata, OCR layers, attachments, annotations, and incremental revisions.
6. **Verify output.** Reopen it with an independent parser. Confirm page count/order, page dimensions/rotation, expected text/fields, metadata, encryption, and attachments as relevant. Render all pages or a representative full-page contact sheet for visual review. Search the output for supposedly removed text before claiming redaction. Check that OCR text is accurate against the image.
7. **Deliver.** State output path, operations, page count only when measured, and exact structural/visual/security checks performed. Do not claim a PDF is accessible/searchable, redacted, password-protected, or print-ready without validating that property.
## Common operations
### Extract text and page count
```python
from pypdf import PdfReader
reader = PdfReader("input.pdf")
print("pages", len(reader.pages))
for number, page in enumerate(reader.pages, 1):
print(f"--- PAGE {number} ---")
print(page.extract_text() or "[No extractable text; may require OCR]")
```
For reading order/tables, use `pdfplumber` and compare with rendered pages; PDF extraction order can differ from visual order.
### Merge and split
```python
from pypdf import PdfReader, PdfWriter
writer = PdfWriter()
for source in ["a.pdf", "b.pdf"]:
for page in PdfReader(source).pages:
writer.add_page(page)
with open("merged.pdf", "wb") as stream:
writer.write(stream)
```
For splitting, create one writer per requested range and verify each output's page count. Preserve bookmarks only if the chosen library path supports them; otherwise report loss.
### Rotate and metadata
Use `page.rotate(90)` on selected pages and preserve the rest. Check page dimensions and orientation afterwards. Set document metadata only with accurate title/author/subject values; metadata changes can invalidate signatures.
### Generate
Use ReportLab for authored PDFs. For long reports, use Platypus flowables and real page templates rather than manually positioning every line. Embed an appropriate font for non-ASCII text. Avoid Unicode subscript/superscript glyphs with built-in ReportLab fonts; use Paragraph `<sub>`/`<super>` tags or a font with glyph support. For accessible PDFs, a visual PDF alone is not a guarantee of tagged reading order: use an authoring source/tool that supports tagging and validate with an accessibility checker.
### OCR scanned pages
Render pages at appropriate resolution and OCR with a verified local tool. Keep the original scan available. If creating a searchable PDF, place the OCR layer accurately over each page; verify page orientation, language, diacritics, tables, and representative extracted text. OCR is an estimate and must not be silently presented as authoritative transcription.
### Redaction and security
Do not overlay black rectangles and call it redaction. Use a true redaction implementation that removes text/graphics from page content, then sanitize metadata, attachments, annotations, hidden OCR layers and prior revisions where the threat model requires. Reopen and text-search the final file, render it, and inspect page content. Encryption tools and permission flags vary; test opening behavior without putting passwords in shell history or logs.
## Supporting files
- `python scripts/inspect_pdf.py file.pdf [--json]`: dependency-free PDF container sanity check. It is not a full parser or content safety scan.
- `python tests/test_inspect_pdf.py`: basic parser-inventory regression tests.
- Use `pypdf` for simple page operations; `pdfplumber` for layout extraction; `pdftotext -layout`, `pdfinfo`, `pdftoppm`, `qpdf`, or equivalent only when installed.
- See `references/operations-and-qa.md` for validation checklists.