OpenPdf
Free open-source PDF toolkit with 30+ tools : merge, split, compress, convert, OCR, encrypt & more. Self-hosted iLovePDF alternative built with Next.js 15 & FastAPI. No signup, no limits, privacy-first.
Install / Use
/learn @aymenhmaidiwastaken/OpenPdfREADME
<p align="center"> <img src="scripts/screenshots/hero.png" alt="OpenPdf Hero" width="100%" /> </p>
Why OpenPdf?
Most online PDF tools are closed-source, riddled with ads, and upload your files to unknown servers. OpenPdf is different:
- 100% Open Source — MIT licensed. Inspect, modify, and deploy it yourself.
- Privacy First — All processing happens on your server. Files are auto-deleted after 15 minutes.
- No Limits — No file size caps, no watermarks, no account required.
- 30 Professional Tools — Everything from merging to OCR in one clean interface.
- Self-Hosted — One
docker-compose upand you're running.
Demo
<p align="center"> <img src="scripts/screenshots/openpdf_demo.gif" alt="OpenPdf Tools Demo" width="100%" /> </p> <details> <summary>Dark Mode</summary> <p align="center"> <img src="scripts/screenshots/openpdf_demo_dark.gif" alt="OpenPdf Dark Mode Demo" width="100%" /> </p> </details> <details> <summary>Full Homepage</summary> <p align="center"> <img src="scripts/screenshots/homepage.png" alt="OpenPdf Homepage" width="100%" /> </p> </details>Features
Core Manipulation
| Tool | Description | |------|-------------| | Merge PDF | Combine multiple PDFs into one with drag-and-drop reordering | | Split PDF | Split by page ranges, every N pages, or extract specific pages | | Rotate PDF | Rotate pages 90/180/270 degrees | | Delete Pages | Remove specific pages from a PDF | | Reorder Pages | Rearrange page order with drag-and-drop |
Conversion
| Tool | Description | |------|-------------| | PDF to Word | Convert PDF to editable .docx with formatting preserved | | PDF to Excel | Extract tables from PDF into .xlsx spreadsheets | | PDF to PowerPoint | Convert PDF pages to .pptx slides | | PDF to Images | Export pages as PNG or JPG with configurable DPI | | Images to PDF | Combine multiple images into a single PDF | | HTML to PDF | Convert HTML files to PDF documents | | Word to PDF | Convert .docx documents to PDF |
Optimization
| Tool | Description | |------|-------------| | Compress PDF | Reduce file size with low/medium/high quality presets | | Linearize PDF | Optimize for fast web viewing (progressive loading) | | Flatten PDF | Flatten form fields and annotations |
Security
| Tool | Description | |------|-------------| | Encrypt PDF | AES-256 password protection with owner/user passwords | | Decrypt PDF | Remove password protection | | Redact PDF | Permanently black out sensitive text by keyword search | | Add Watermark | Text watermarks with custom opacity, position, and rotation | | Sign PDF | Place a signature image on any page |
Content & Forms
| Tool | Description | |------|-------------| | OCR PDF | Make scanned PDFs searchable using Tesseract OCR | | Add Page Numbers | Insert page numbers with configurable position and format | | Edit Metadata | View and edit title, author, subject, keywords | | Add Bookmarks | Create table of contents / bookmarks | | Repair PDF | Fix corrupted or damaged PDF files |
Analysis
| Tool | Description | |------|-------------| | Compare PDFs | Side-by-side visual diff highlighting differences | | Extract Text | Pull all text with per-page view and copy button | | Extract Images | Extract all embedded images with individual/bulk download | | PDF Info | Detailed file info, metadata, and per-page stats | | Count Pages | Count pages across one or multiple PDFs |
Quick Start
Docker (Recommended)
git clone https://github.com/aymenhmaidiwastaken/OpenPdf.git
cd OpenPdf
cp .env.example .env
docker compose up --build -d
docker compose ps
Open http://localhost:3000 in your browser.
Optional health checks:
curl http://localhost:3000/api/v1/health
curl http://localhost:8000/api/v1/health
Manual Setup
Prerequisites: Python 3.11+, Node.js 18+, Redis
Backend:
cd backend
pip install -r requirements.txt
uvicorn main:app --host 0.0.0.0 --port 8000
Frontend:
cd frontend
npm install
npm run dev
Open http://localhost:3000. The frontend proxies API requests to the backend at port 8000.
Tech Stack
Frontend
- Next.js 15 — App Router, Turbopack, server components
- Tailwind CSS v4 — Custom neumorphic design system
- Framer Motion — Page transitions and component animations
- PDF.js — Client-side PDF preview with zoom and navigation
- TypeScript — End-to-end type safety
Backend
- FastAPI — Async Python web framework
- PyMuPDF — PDF rendering, text extraction, OCR, comparison
- pypdf — Merge, split, rotate, page manipulation
- pikepdf — Encryption, metadata, linearization, repair
- Celery + Redis — Async job queue for heavy operations
- ReportLab — Watermarks, page numbers, PDF generation
Architecture
Browser (Next.js) ──> Next.js API Routes (BFF Proxy) ──> FastAPI Backend
│
Celery Worker
│
Redis
Docker Compose runtime:
Browser -> frontend (Next.js, :3000) -> backend (FastAPI, :8000) -> redis + celery
- Next.js API routes proxy to FastAPI — no CORS, backend stays private
- Fast operations run synchronously, heavy ops (OCR, batch) go through Celery
- Temp files stored in
{UPLOAD_DIR}/{job_id}/, auto-cleaned every 15 minutes - Tool plugin architecture — add a new tool by creating one Python file
API Endpoints
POST /api/v1/tools/{tool_name} Upload files + process
GET /api/v1/jobs/{job_id}/status Poll job progress
GET /api/v1/jobs/{job_id}/download Download result file
GET /api/v1/jobs/{job_id}/files List all output files
GET /api/v1/jobs/{job_id}/content/* Get file content inline
DELETE /api/v1/jobs/{job_id} Clean up job
GET /api/v1/health Health check
Project Structure
OpenPdf/
├── frontend/
│ └── src/
│ ├── app/ # Next.js App Router pages
│ │ ├── page.tsx # Homepage
│ │ └── tools/[tool]/ # Dynamic tool pages
│ ├── components/ # React components
│ │ ├── home/ # Hero, FeatureGrid, FeatureCard
│ │ ├── tools/ # FileUploader, PdfViewer, OptionPanel
│ │ │ └── results/ # Inline result displays
│ │ ├── layout/ # Navbar, Footer, ThemeProvider
│ │ └── shared/ # Button, Modal, Toast
│ ├── hooks/ # useFileUpload, useJobPolling
│ ├── lib/ # tools-config, api-client, utils
│ └── types/ # TypeScript interfaces
├── backend/
│ ├── main.py # FastAPI application
│ ├── config.py # Settings (pydantic-settings)
│ ├── routers/ # API route handlers
│ ├── services/ # Tool registry, file/job management
│ ├── tools/ # 30 tool implementations
│ │ ├── base.py # Abstract base tool class
│ │ ├── merge.py
│ │ ├── compress.py
│ │ └── ... # One file per tool
│ └── tasks/ # Celery app + workers
├── scripts/
│ ├── generate_demo_pdf.py # Create demo PDF for testing
│ ├── take_screenshots.py # Automated screenshot capture
│ └── create_gif.py # Generate demo GIF
├── docker-compose.yml
├── .env.example
└── README.md
Docker Files
frontend/Dockerfilebuilds the production Next.js container.frontend/.dockerignoreexcludes local artifacts from image build context.docs/contributions/docker-full-stack-startup-fix.mddocuments the Docker startup fix contribution.
Adding a New Tool
- Create a new file in
backend/tools/:
from pathlib import Path
from tools.base import BaseTool
class MyNewTool(BaseTool):
name = "my-new-tool"
description = "What this tool does"
category = "manipulation" # or conversion, optimization, security, content, analysis
is_async = False
def execute(self, input_files: list[Path], options: dict, output_dir: Path) -> list[Path]:
# Your logic here
output_path = output_dir / "result.pdf"
# ... process files ...
return [output_path]
- Add the tool config in
frontend/src/lib/tools-config.ts - That's it — the backend auto-discovers tools, and the frontend uses the dynamic
[tool]route.
Environment Variables
| Variable | Default | Description |
|----------|---------|-------------|
| REDIS_URL
