pdf

Use this skill whenever the user wants to do anything with PDF files. This includes reading or extracting text/tables from PDFs, combining or merging multiple PDFs into one, splitting PDFs apart, rotating pages, adding watermarks, creating new PDFs, filling PDF forms, encrypting/decrypting PDFs, extracting images, cleaning background noise from scanned PDFs, and OCR on scanned PDFs to make them searchable. If the user mentions a .pdf file or asks to produce one, use this skill.

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "pdf" with this command: npx skills add gouzhuang/agent-skills/gouzhuang-agent-skills-pdf

PDF Processing Guide

Overview

This guide covers essential PDF processing operations using Python libraries and command-line tools. For advanced features, JavaScript libraries, and detailed examples, see REFERENCE.md. If you need to fill out a PDF form, read FORMS.md and follow its instructions.

Quick Start

from pypdf import PdfReader, PdfWriter

# Read a PDF
reader = PdfReader("document.pdf")
print(f"Pages: {len(reader.pages)}")

# Extract text
text = ""
for page in reader.pages:
    text += page.extract_text()

Python Libraries

pypdf - Basic Operations

Merge PDFs

from pypdf import PdfWriter, PdfReader

writer = PdfWriter()
for pdf_file in ["doc1.pdf", "doc2.pdf", "doc3.pdf"]:
    reader = PdfReader(pdf_file)
    for page in reader.pages:
        writer.add_page(page)

with open("merged.pdf", "wb") as output:
    writer.write(output)

Split PDF

reader = PdfReader("input.pdf")
for i, page in enumerate(reader.pages):
    writer = PdfWriter()
    writer.add_page(page)
    with open(f"page_{i+1}.pdf", "wb") as output:
        writer.write(output)

Extract Metadata

reader = PdfReader("document.pdf")
meta = reader.metadata
print(f"Title: {meta.title}")
print(f"Author: {meta.author}")
print(f"Subject: {meta.subject}")
print(f"Creator: {meta.creator}")

Rotate Pages

reader = PdfReader("input.pdf")
writer = PdfWriter()

page = reader.pages[0]
page.rotate(90)  # Rotate 90 degrees clockwise
writer.add_page(page)

with open("rotated.pdf", "wb") as output:
    writer.write(output)

pdfplumber - Text and Table Extraction

Extract Text with Layout

import pdfplumber

with pdfplumber.open("document.pdf") as pdf:
    for page in pdf.pages:
        text = page.extract_text()
        print(text)

Extract Tables

with pdfplumber.open("document.pdf") as pdf:
    for i, page in enumerate(pdf.pages):
        tables = page.extract_tables()
        for j, table in enumerate(tables):
            print(f"Table {j+1} on page {i+1}:")
            for row in table:
                print(row)

Advanced Table Extraction

import pandas as pd

with pdfplumber.open("document.pdf") as pdf:
    all_tables = []
    for page in pdf.pages:
        tables = page.extract_tables()
        for table in tables:
            if table:  # Check if table is not empty
                df = pd.DataFrame(table[1:], columns=table[0])
                all_tables.append(df)

# Combine all tables
if all_tables:
    combined_df = pd.concat(all_tables, ignore_index=True)
    combined_df.to_excel("extracted_tables.xlsx", index=False)

reportlab - Create PDFs

Basic PDF Creation

from reportlab.lib.pagesizes import letter
from reportlab.pdfgen import canvas

c = canvas.Canvas("hello.pdf", pagesize=letter)
width, height = letter

# Add text
c.drawString(100, height - 100, "Hello World!")
c.drawString(100, height - 120, "This is a PDF created with reportlab")

# Add a line
c.line(100, height - 140, 400, height - 140)

# Save
c.save()

Create PDF with Multiple Pages

from reportlab.lib.pagesizes import letter
from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer, PageBreak
from reportlab.lib.styles import getSampleStyleSheet

doc = SimpleDocTemplate("report.pdf", pagesize=letter)
styles = getSampleStyleSheet()
story = []

# Add content
title = Paragraph("Report Title", styles['Title'])
story.append(title)
story.append(Spacer(1, 12))

body = Paragraph("This is the body of the report. " * 20, styles['Normal'])
story.append(body)
story.append(PageBreak())

# Page 2
story.append(Paragraph("Page 2", styles['Heading1']))
story.append(Paragraph("Content for page 2", styles['Normal']))

# Build PDF
doc.build(story)

Subscripts and Superscripts

IMPORTANT: Never use Unicode subscript/superscript characters (₀₁₂₃₄₅₆₇₈₉, ⁰¹²³⁴⁵⁶⁷⁸⁹) in ReportLab PDFs. The built-in fonts do not include these glyphs, causing them to render as solid black boxes.

Instead, use ReportLab's XML markup tags in Paragraph objects:

from reportlab.platypus import Paragraph
from reportlab.lib.styles import getSampleStyleSheet

styles = getSampleStyleSheet()

# Subscripts: use <sub> tag
chemical = Paragraph("H<sub>2</sub>O", styles['Normal'])

# Superscripts: use <super> tag
squared = Paragraph("x<super>2</super> + y<super>2</super>", styles['Normal'])

For canvas-drawn text (not Paragraph objects), manually adjust font the size and position rather than using Unicode subscripts/superscripts.

Command-Line Tools

pdftotext (poppler-utils)

# Extract text
pdftotext input.pdf output.txt

# Extract text preserving layout
pdftotext -layout input.pdf output.txt

# Extract specific pages
pdftotext -f 1 -l 5 input.pdf output.txt  # Pages 1-5

qpdf

# Merge PDFs
qpdf --empty --pages file1.pdf file2.pdf -- merged.pdf

# Split pages
qpdf input.pdf --pages . 1-5 -- pages1-5.pdf
qpdf input.pdf --pages . 6-10 -- pages6-10.pdf

# Rotate pages
qpdf input.pdf output.pdf --rotate=+90:1  # Rotate page 1 by 90 degrees

# Remove password (use environment variable for security)
qpdf --password="$PDF_PASSWORD" --decrypt encrypted.pdf decrypted.pdf

pdftk (if available)

# Merge
pdftk file1.pdf file2.pdf cat output merged.pdf

# Split
pdftk input.pdf burst

# Rotate
pdftk input.pdf rotate 1east output rotated.pdf

Ghostscript - Compress PDFs

Ghostscript is the most reliable tool for compressing PDF files by reducing image resolution and applying efficient compression.

Basic Compression Command

gs -sDEVICE=pdfwrite -dCompatibilityLevel=1.4 -dPDFSETTINGS=<setting> -dNOPAUSE -dQUIET -dBATCH -sOutputFile="compressed.pdf" "input.pdf"

Available Quality Presets

SettingQuality DescriptionImage Resolution (DPI)Typical Use Case
/screenLowest quality, highest compression72 dpiOn-screen viewing, smallest file size
/ebookMedium quality, balanced compression150 dpiE-readers and general digital use
/printerHigh quality300 dpiPrinting with good resolution
/prepressHighest quality, color preserving300 dpiProfessional printing workflows
/defaultGeneral purpose outputVaries by parameterVersatile but may result in larger files

Common Compression Examples

# Maximum compression for web/email (/screen preset)
gs -sDEVICE=pdfwrite -dCompatibilityLevel=1.4 -dPDFSETTINGS=/screen -dNOPAUSE -dQUIET -dBATCH -sOutputFile="compressed.pdf" "input.pdf"

# Balanced compression for general use (/ebook preset)
gs -sDEVICE=pdfwrite -dCompatibilityLevel=1.4 -dPDFSETTINGS=/ebook -dNOPAUSE -dQUIET -dBATCH -sOutputFile="compressed.pdf" "input.pdf"

# High quality for printing (/printer preset)
gs -sDEVICE=pdfwrite -dCompatibilityLevel=1.4 -dPDFSETTINGS=/printer -dNOPAUSE -dQUIET -dBATCH -sOutputFile="compressed.pdf" "input.pdf"

Advanced Control

For finer control, override specific parameters after the -dPDFSETTINGS flag:

# Use /ebook settings but force higher color image resolution
gs -sDEVICE=pdfwrite -dPDFSETTINGS=/ebook -dColorImageResolution=300 -dNOPAUSE -dQUIET -dBATCH -sOutputFile="output.pdf" "input.pdf"

# Disable image downsampling entirely
gs -sDEVICE=pdfwrite -dPDFSETTINGS=/default -dDownsampleColorImages=false -dDownsampleGrayImages=false -dDownsampleMonoImages=false -dNOPAUSE -dQUIET -dBATCH -sOutputFile="output.pdf" "input.pdf"

Common Tasks

Clean Background Noise from Scanned PDFs

Use scripts/clean_pdf_background.py to remove background noise and shadows from scanned PDFs while preserving color content (photos, stamps) and text clarity.

python scripts/clean_pdf_background.py input.pdf output.pdf [dpi]

Parameters:

  • input.pdf: Source PDF with background noise
  • output.pdf: Cleaned output PDF
  • dpi: Resolution for processing (default: 300, use 600 for higher quality)

Processing method:

  • Analyzes each page's background brightness (95th and 98th percentiles)
  • Skips pages with clean white backgrounds (>250 and >253 brightness)
  • Applies level adjustment (0%-92%) and white threshold (92%) to remove noise
  • Preserves color content including photos, stamps, and handwriting

Example:

# Standard quality cleaning
python scripts/clean_pdf_background.py scanned.pdf clean.pdf

# High quality cleaning
python scripts/clean_pdf_background.py scanned.pdf clean.pdf 600

Requirements:

  • ImageMagick (convert)
  • poppler-utils (pdftoppm)
  • Python: Pillow, numpy

Extract Text from Scanned PDFs

# Requires: pip install pytesseract pdf2image
import pytesseract
from pdf2image import convert_from_path

# Convert PDF to images
images = convert_from_path('scanned.pdf')

# OCR each page
text = ""
for i, image in enumerate(images):
    text += f"Page {i+1}:\n"
    text += pytesseract.image_to_string(image)
    text += "\n\n"

print(text)

Add Watermark

from pypdf import PdfReader, PdfWriter

# Create watermark (or load existing)
watermark = PdfReader("watermark.pdf").pages[0]

# Apply to all pages
reader = PdfReader("document.pdf")
writer = PdfWriter()

for page in reader.pages:
    page.merge_page(watermark)
    writer.add_page(page)

with open("watermarked.pdf", "wb") as output:
    writer.write(output)

Extract Images

# Using pdfimages (poppler-utils)
pdfimages -j input.pdf output_prefix

# This extracts all images as output_prefix-000.jpg, output_prefix-001.jpg, etc.

Password Protection

import os
from pypdf import PdfReader, PdfWriter

# Load passwords from environment variables for security
USER_PASSWORD = os.environ.get('PDF_USER_PASSWORD')
OWNER_PASSWORD = os.environ.get('PDF_OWNER_PASSWORD')

if not USER_PASSWORD or not OWNER_PASSWORD:
    raise ValueError("PDF_USER_PASSWORD and PDF_OWNER_PASSWORD environment variables must be set")

reader = PdfReader("input.pdf")
writer = PdfWriter()

for page in reader.pages:
    writer.add_page(page)

# Add password protection
writer.encrypt(USER_PASSWORD, OWNER_PASSWORD)

with open("encrypted.pdf", "wb") as output:
    writer.write(output)

Quick Reference

TaskBest ToolCommand/Code
Merge PDFspypdfwriter.add_page(page)
Split PDFspypdfOne page per file
Extract textpdfplumberpage.extract_text()
Extract tablespdfplumberpage.extract_tables()
Create PDFsreportlabCanvas or Platypus
Command line mergeqpdfqpdf --empty --pages ...
OCR scanned PDFspytesseractConvert to image first
Compress PDFGhostscriptgs -sDEVICE=pdfwrite -dPDFSETTINGS=/ebook
Clean background noisescripts/clean_pdf_background.pypython scripts/clean_pdf_background.py input.pdf output.pdf
Fill PDF formspdf-lib or pypdf (see FORMS.md)See FORMS.md

Next Steps

  • For advanced pypdfium2 usage, see REFERENCE.md
  • For JavaScript libraries (pdf-lib), see REFERENCE.md
  • If you need to fill out a PDF form, follow the instructions in FORMS.md
  • For troubleshooting guides, see REFERENCE.md

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

Automation

pdf

No summary provided by upstream source.

Repository SourceNeeds Review
Automation

pdf

No summary provided by upstream source.

Repository SourceNeeds Review
Automation

pdf

No summary provided by upstream source.

Repository SourceNeeds Review
Automation

pdf

No summary provided by upstream source.

Repository SourceNeeds Review