Skip to main content
skill CX Codex

pdf-to-docx — Claude Code skill: PDF to Word

Turns PDF files into editable Word documents with the pdf2docx library. Useful when a report or contract needs changes, not just reading.

Install into Claude Code · Skills CLI (Vercel) All methods and platforms ↓
npx skills add claude-office-skills/skills --skill pdf-to-docx -a claude-code
Open on GitHub

What pdf-to-docx does

The skill takes a PDF and produces a .docx, keeping layout, tables, images and text formatting. It runs on the Python library pdf2docx, which pulls native PDF content instead of reading pixels, so text-based files come out cleaner than with OCR.

An office-mcp server exposes a pdf_to_docx tool. You can convert the whole file, a page range, or a list of pages — indexing starts at zero. Tuning options cover line merging, border detection and page margins. The source also shows a batch example built on ThreadPoolExecutor.

Scanned files are the weak spot. With no text layer, pdf2docx has nothing to extract, and the docs suggest running pages through pytesseract or PaddleOCR first. Complex tables often need manual cleanup afterwards, and some fonts get swapped for system defaults.

What it helps with

  • turn a PDF report into an editable Word file
  • pull tables out of a PDF into a document
  • convert only selected pages instead of the whole file
  • batch-convert a folder of PDFs
  • inspect PDF structure before converting

Example prompts for the agent

  • Convert this PDF report to an editable Word document
  • Turn pages 1-5 of this PDF into Word format
  • Analyze this PDF structure, then convert it to docx

How to install pdf-to-docx

1Skills CLI (Vercel)

npx skills add claude-office-skills/skills --skill pdf-to-docx -a claude-code

2Manually: put the files in place

~/.claude/skills/pdf-to-docx/SKILL.md

Copy the whole skill folder; for one project use .claude/skills/pdf-to-docx/

Step by step, with commands for each platform: How to install skills in Claude Code: five ways

Questions about pdf-to-docx

How do I install pdf-to-docx in Claude?

Run npx skills add claude-office-skills/skills --skill pdf-to-docx -a claude-code. The skill lands in ~/.claude/skills/pdf-to-docx/SKILL.md.

What does pdf-to-docx do?

It converts a PDF into an editable .docx with pdf2docx, preserving layout, tables and images. Conversion runs through the pdf_to_docx MCP tool.

Does it work on scanned PDFs?

No. pdf2docx extracts the text layer, and scans do not have one. The docs recommend OCR with pytesseract or PaddleOCR first.

Source text

SKILL.md · MIT
---
# ═══════════════════════════════════════════════════════════════════════════════
# CLAUDE OFFICE SKILL - Enhanced Metadata v2.0
# ═══════════════════════════════════════════════════════════════════════════════

# Basic Information
name: pdf-to-docx
description: "Convert PDF files to editable Word documents using pdf2docx"
version: "1.0"
author: claude-office-skills
license: MIT

# Categorization
category: pdf
tags:
  - pdf
  - docx
  - conversion
department: All

# AI Model Compatibility
models:
  recommended:
    - claude-sonnet-4
    - claude-opus-4
  compatible:
    - claude-3-5-sonnet
    - gpt-4
    - gpt-4o

# MCP Tools Integration
mcp:
  server: office-mcp
  tools:
    - pdf_to_docx

# Skill Capabilities
capabilities:
  - format_conversion
  - editable_documents

# Language Support
languages:
  - en
  - zh
---

# PDF to Word Skill

## Overview

This skill enables conversion from PDF to editable Word documents using **pdf2docx** - a Python library that preserves layout, tables, images, and text formatting. Unlike OCR-based solutions, pdf2docx extracts native PDF content for accurate conversion.

## How to Use

1. Provide the PDF file you want to convert
2. Optionally specify pages or conversion options
3. I'll convert it to an editable Word document

**Example prompts:**
- "Convert this PDF report to an editable Word document"
- "Turn pages 1-5 of this PDF into Word format"
- "Extract this scanned document as editable text"
- "Convert this PDF contract to Word for editing"

## Domain Knowledge

### pdf2docx Fundamentals

```python
from pdf2docx import Converter

# Basic conversion
cv = Converter('input.pdf')
cv.convert('output.docx')
cv.close()

# Or using context manager
with Converter('input.pdf') as cv:
    cv.convert('output.docx')
```

### Conversion Options

```python
from pdf2docx import Converter

cv = Converter('input.pdf')

# Full document
cv.convert('output.docx')

# Specific pages (0-indexed)
cv.convert('output.docx', start=0, end=5)

# Single page
cv.convert('output.docx', pages=[0])

# Multiple specific pages
cv.convert('output.docx', pages=[0, 2, 4])

cv.close()
```

### Advanced Options

```python
from pdf2docx import Converter

cv = Converter('input.pdf')

cv.convert(
    'output.docx',
    start=0,                    # Start page (0-indexed)
    end=None,                   # End page (None = last page)
    pages=None,                 # Specific pages list
    password=None,              # PDF password if encrypted
    min_section_height=20.0,    # Minimum height for section
    connected_border_tolerance=0.5,  # Border detection tolerance
    line_overlap_threshold=0.9, # Line merging threshold
    line_break_width_ratio=0.5, # Line break detection
    line_break_free_space_ratio=0.1,
    line_separate_threshold=5,  # Vertical line separation
    new_paragraph_free_space_ratio=0.85,
    float_image_ignorable_gap=5,
    page_margin_factor_top=0.5,
    page_margin_factor_bottom=0.5,
)

cv.close()
```

### Handling Different PDF Types

#### Native PDFs (Text-based)
```python
# Works best with native PDFs
cv = Converter('native_pdf.pdf')
cv.convert('output.docx')
cv.close()
```

#### Scanned PDFs (Image-based)
```python
# For scanned PDFs, use OCR first
# pdf2docx works best with native text PDFs
# Consider using pytesseract or PaddleOCR first

import pytesseract
from pdf2image import convert_from_path

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

# OCR each page
text = ''
for img in images:
    text += pytesseract.image_to_string(img)

# Then create Word document from text
```

### Python Integration

```python
from pdf2docx import Converter
import os

def pdf_to_word(pdf_path, output_path=None, pages=None):
    """Convert PDF to Word document."""
    if output_path is None:
        output_path = pdf_path.replace('.pdf', '.docx')
    
    cv = Converter(pdf_path)
    
    if pages:
        cv.convert(output_path, pages=pages)
    else:
        cv.convert(output_path)
    
    cv.close()
    
    return output_path

# Usage
result = pdf_to_word('document.pdf')
print(f"Created: {result}")
```

### Batch Conversion

```python
from pdf2docx import Converter
from pathlib import Path
from concurrent.futures import ThreadPoolExecutor

def convert_single(pdf_path, output_dir):
    """Convert single PDF to Word."""
    output_path = output_dir / pdf_path.with_suffix('.docx').name
    
    try:
        cv = Converter(str(pdf_path))
        cv.convert(str(output_path))
        cv.close()
        return f"Success: {pdf_path.name}"
    except Exception as e:
        return f"Error: {pdf_path.name} - {e}"

def batch_convert(input_dir, output_dir, max_workers=4):
    """Convert all PDFs in directory."""
    input_path = Path(input_dir)
    output_path = Path(output_dir)
    output_path.mkdir(exist_ok=True)
    
    pdf_files = list(input_path.glob('*.pdf'))
    
    with ThreadPoolExecutor(max_workers=max_workers) as executor:
        futures = [
            executor.submit(convert_single, pdf, output_path)
            for pdf in pdf_files
        ]
        
        for future in futures:
            print(future.result())

batch_convert('./pdfs', './word_docs')
```

### Parsing PDF Structure

```python
from pdf2docx import Converter

def analyze_pdf(pdf_path):
    """Analyze PDF structure before conversion."""
    cv = Converter(pdf_path)
    
    for i, page in enumerate(cv.pages):
        print(f"Page {i+1}:")
        print(f"  Size: {page.width} x {page.height}")
        print(f"  Blocks: {len(page.blocks)}")
        
        for block in page.blocks:
            if hasattr(block, 'text'):
                print(f"    Text block: {block.text[:50]}...")
            elif hasattr(block, 'image'):
                print(f"    Image block")
    
    cv.close()

analyze_pdf('document.pdf')
```

## Best Practices

1. **Check PDF Type**: Native PDFs convert better than scanned
2. **Preview First**: Test with a few pages before full conversion
3. **Handle Tables**: Complex tables may need manual adjustment
4. **Image Quality**: Images are extracted at original resolution
5. **Font Handling**: Some fonts may substitute to system defaults

## Common Patterns

### Convert with Progress
```python
from pdf2docx import Converter

def convert_with_progress(pdf_path, output_path):
    """Convert PDF with progress tracking."""
    cv = Converter(pdf_path)
    
    total_pages = len(cv.pages)
    print(f"Converting {total_pages} pages...")
    
    for i in range(total_pages):
        cv.convert(output_path, start=i, end=i+1)
        progress = (i + 1) / total_pages * 100
        print(f"Progress: {progress:.1f}%")
    
    cv.close()
    print("Conversion complete!")
```

### Extract Tables Only
```python
from pdf2docx import Converter
from docx import Document

def extract_tables_to_word(pdf_path, output_path):
    """Extract only tables from PDF to Word."""
    cv = Converter(pdf_path)
    
    # First do full conversion
    temp_path = 'temp_full.docx'
    cv.convert(temp_path)
    cv.close()
    
    # Open and extract tables
    doc = Document(temp_path)
    new_doc = Document()
    
    for table in doc.tables:
        # Copy table to new document
        new_table = new_doc.add_table(rows=0, cols=len(table.columns))
        
        for row in table.rows:
            new_row = new_table.add_row()
            for i, cell in enumerate(row.cells):
                new_row.cells[i].text = cell.text
        
        new_doc.add_paragraph()  # Add spacing
    
    new_doc.save(output_path)
    os.remove(temp_path)
```

## Examples

### Example 1: Contract Conversion
```python
from pdf2docx import Converter
import os

def convert_contract(pdf_path):
    """Convert contract PDF to editable Word with metadata."""
    
    # Define output path
    base_name = os.path.splitext(pdf_path)[0]
    output_path = f"{base_name}_editable.docx"
    
    # Convert
    cv = Converter(pdf_path)
    
    # Check page count
    page_count = len(cv.pages)
    print(f"Processing {page_count} pages...")
    
    # Convert all pages
    cv.convert(output_path)
    cv.close()
    
    print(f"Created: {output_path}")
    print(f"File size: {os.path.getsize(output_path) / 1024:.1f} KB")
    
    return output_path

# Usage
result = convert_contract('contract.pdf')
```

### Example 2: Selective Page Conversion
```python
from pdf2docx import Converter

def convert_selected_pages(pdf_path, page_ranges, output_path):
    """Convert specific page ranges to Word.
    
    page_ranges: List of tuples like [(1, 3), (5, 7)] for pages 1-3 and 5-7
    """
    cv = Converter(pdf_path)
    
    # Convert pages (0-indexed internally)
    all_pages = []
    for start, end in page_ranges:
        all_pages.extend(range(start - 1, end))  # Convert to 0-indexed
    
    cv.convert(output_path, pages=all_pages)
    cv.close()
    
    print(f"Converted pages: {page_ranges}")
    return output_path

# Convert pages 1-5 and 10-15
convert_selected_pages(
    'long_document.pdf',
    [(1, 5), (10, 15)],
    'selected_pages.docx'
)
```

### Example 3: PDF Report to Editable Template
```python
from pdf2docx import Converter
from docx import Document

def pdf_to_template(pdf_path, output_path):
    """Convert PDF report to Word template with placeholders."""
    
    # Convert PDF to Word
    cv = Converter(pdf_path)
    cv.convert(output_path)
    cv.close()
    
    # Open and add placeholder fields
    doc = Document(output_path)
    
    # Replace common fields with placeholders
    replacements = {
        'Company Name': '[COMPANY_NAME]',
        'Date:': 'Date: [DATE]',
        'Prepared by:': 'Prepared by: [AUTHOR]',
    }
    
    for para in doc.paragraphs:
        for old, new in replacements.items():
            if old in para.text:
                para.text = para.text.replace(old, new)
    
    # Also check tables
    for table in doc.tables:
        for row in table.rows:
            for cell in row.cells:
                for old, new in replacements.items():
                    if old in cell.text:
                        cell.text = cell.text.replace(old, new)
    
    doc.save(output_path)
    print(f"Template created: {output_path}")

pdf_to_template('annual_report.pdf', 'report_template.docx')
```

### Example 4: Bulk Invoice Processing
```python
from pdf2docx import Converter
from pathlib import Path
import json

def process_invoices(input_folder, output_folder):
    """Convert PDF invoices to editable Word documents."""
    
    input_path = Path(input_folder)
    output_path = Path(output_folder)
    output_path.mkdir(exist_ok=True)
    
    results = []
    
    for pdf_file in input_path.glob('*.pdf'):
        output_file = output_path / pdf_file.with_suffix('.docx').name
        
        try:
            cv = Converter(str(pdf_file))
            cv.convert(str(output_file))
            cv.close()
            
            results.append({
                'file': pdf_file.name,
                'status': 'success',
                'output': str(output_file)
            })
            
        except Exception as e:
            results.append({
                'file': pdf_file.name,
                'status': 'error',
                'error': str(e)
            })
    
    # Save results log
    with open(output_path / 'conversion_log.json', 'w') as f:
        json.dump(results, f, indent=2)
    
    # Summary
    success = sum(1 for r in results if r['status'] == 'success')
    print(f"Converted {success}/{len(results)} files")
    
    return results

results = process_invoices('./invoices_pdf', './invoices_word')
```

## Limitations

- Scanned PDFs require OCR preprocessing
- Complex layouts may not convert perfectly
- Some fonts may not be available
- Watermarks are included in conversion
- Protected/encrypted PDFs need password

## Installation

```bash
pip install pdf2docx

# For image handling
pip install Pillow
```

## Resources

- [GitHub Repository](https://github.com/dothinking/pdf2docx)
- [Documentation](https://pdf2docx.readthedocs.io/)
- [PyPI Package](https://pypi.org/project/pdf2docx/)

© claude-office-skills · MIT · claude-office-skills/skills

Similar skills

Everything for Office documents →

From the same set109

telegram-bot A skill for building Telegram bots: chatbots, notifications, AI assistants and group automation. Useful when you need message handlers and workflows fast. CX Codex +1 6,200installs academic-search Builds academic search strategies, reviews supplied papers and abstracts, and helps synthesize findings. Use it when planning a literature review or assessing research methods. CX Codex +1 6,100installs docx-manipulation The skill builds and edits Word files through python-docx: headings, tables, images, headers. Useful when a report or contract has to come out of code. CX Codex +1 6,100installs calendar-automation Automates Google Calendar and Outlook workflows: allocates focus time blocks, sends morning Slack briefings, and prepares meeting notes with context. CX Codex +1 6,100installs proposal-writer Generates structured business proposals, quick service quotes, and partnership pitches. Useful for client negotiations and RFP responses. CX Codex +1 5,900installs PDF OCR Extraction Pulls text out of scanned and image-based PDFs with OCR. Useful when a document won't let you select anything but still needs to be searchable. CX Codex +1 5,700installs image-generation Turns a rough visual idea into a working prompt for DALL-E, Midjourney or Stable Diffusion, shaped for the tool you actually use. CX Codex +1 5,600installs social-publisher Automates multi-platform social media publishing and tailors captions for TikTok, Instagram, YouTube, and LinkedIn. Useful for scheduling content distribution. CX Codex +1 5,600installs

Project sponsors

Companies that keep this analytics open
Gold sponsor

Impressions, clicks and code copies — open statistics. We keep the numbers public for the same reason NeBlask itself is public. Become a sponsor