OPEN SOURCE

YOU.PDF: A FastAPI PDF Toolkit — Extract Text, Merge, Split, Inspect

OCT 13, 2026·8 MIN

YOU.PDF: A FastAPI PDF Toolkit — Extract Text, Merge, Split, Inspect

An open-source PDF utility API: upload a PDF to read its metadata, extract per-page text, merge documents, or split out page ranges in any order. Built on pypdf, tested end-to-end with real generated PDFs, deployable via Docker or Render.

TL;DR: YOU.PDF is a five-endpoint FastAPI service for everyday PDF surgery. POST /info returns page count, file size, and document metadata. POST /extract pulls text per page, optionally limited to ranges like "1-2,3". POST /merge combines two or more PDFs into one download. POST /split extracts page ranges — including reordered ones like "3,1" — into a new PDF. Encrypted PDFs are rejected with a clear 400. The test suite generates real PDFs with reportlab and round-trips them through every endpoint.

The problem: PDF tools are either bloated or untrustworthy

Everyone needs PDF surgery sometimes — pull the text out of a report, merge three scanned contracts, extract pages 4–7 for a client. The options are usually bad: desktop apps with upsell walls, ad-covered websites that upload your documents to someone else's server, or writing a one-off pypdf script every single time.

YOU.PDF takes the middle path a developer actually wants: a small, self-hostable HTTP API for the four operations that cover ~90% of PDF chores. No accounts, no uploads to a third party, no GUI — just multipart POSTs in and PDFs or JSON out. Run it on your own machine or a $0 Render instance, and your documents never leave infrastructure you control.

How it works: five endpoints on pypdf

The whole service is one file, app.py, built on pypdf's PdfReader/PdfWriter. Every endpoint funnels through a shared _read_pdf() helper that rejects unreadable files and encrypted PDFs up front with HTTP 400 — fail fast, fail clearly:

def _read_pdf(data: bytes) -> PdfReader:
    try:
        reader = PdfReader(BytesIO(data))
    except Exception as exc:
        raise HTTPException(status_code=400, detail=f"Not a readable PDF: {exc}")
    if reader.is_encrypted:
        raise HTTPException(status_code=400, detail="Encrypted PDFs are not supported")
    return reader
EndpointInputOutput
POST /infomultipart filefilename, page count, size in bytes, metadata (title, author, creator, producer, creation date)
POST /extractmultipart file + optional form field pages ("1-2,3")JSON: text per requested page
POST /mergemultipart files (2+)Merged PDF download (merged.pdf)
POST /splitmultipart file + form field ranges ("1-2,3")PDF of the selected pages, in the given order (split.pdf)
GET /health—{"status": "ok", "service": "YOU.PDF"}

The range parser: small but strict

The _parse_ranges() function turns specs like "1-3,5" into 1-based page lists, and it's strict in the right ways: out-of-bounds pages, reversed ranges, and empty specs all return HTTP 400 with a message naming the offending chunk (e.g. "Bad range '1-9' for a 3-page PDF"). Because split preserves the requested order, ranges="3,1" genuinely reorders pages — the test suite asserts page 3's text comes first.

A few behaviors worth knowing: ranges are 1-based (page 1 is the first page, as a human would count), whitespace around commas and dashes is tolerated, and duplicate pages are allowed — ranges="2,2,2" would produce a three-page PDF with page 2 repeated three times. The same parser powers both /extract's pages field and /split's ranges field, so the syntax you learn once works in both places. Validation happens before any PDF is built, so a bad range fails fast without wasting work.

Design decisions worth stealing

Three choices in app.py are worth copying into your own FastAPI services. First, the shared _read_pdf() gate: every endpoint validates its input through one helper instead of repeating try/except blocks, which means error behavior is consistent everywhere — unreadable file or encrypted PDF, you always get a 400 with a plain-English reason. Second, merged and split outputs stream from an in-memory BytesIO buffer via StreamingResponse with a Content-Disposition: attachment header — no temp files on disk, no cleanup cron, and the browser downloads the result with a sensible filename. Third, the service is fully stateless: no database, no session, no uploaded-file storage. Each request carries its own document and the response carries the result. That makes horizontal scaling trivial and means there's nothing to leak between users.

Streaming responses, not temp files

Merge and split build the output with PdfWriter, write to an in-memory BytesIO buffer, and return it as a StreamingResponse with Content-Disposition: attachment. No temp files on disk, no cleanup jobs — the whole operation is request-scoped, which is exactly how a stateless utility service should behave.

Run it yourself

pip install -r requirements.txt   # fastapi, uvicorn, pypdf, python-multipart, pytest, httpx, reportlab
uvicorn app:app --port 8001
# inspect
curl -X POST localhost:8001/info -F "[email protected]"
# extract pages 1-2 and 5 as text
curl -X POST localhost:8001/extract -F "[email protected]" -F "pages=1-2,5"
# merge
curl -X POST localhost:8001/merge -F "[email protected]" -F "[email protected]" -o merged.pdf
# split out pages 2-3
curl -X POST localhost:8001/split -F "[email protected]" -F "ranges=2-3" -o split.pdf

A Dockerfile and render.yaml ship in the repo, plus a GitHub Actions deploy workflow — so "run it yourself" includes "host it yourself" with minimal friction.

Chaining endpoints: a real workflow

The endpoints compose into genuinely useful pipelines. Say a client sends you a 40-page scanned report and needs pages 12–18 as text plus a standalone PDF of the appendix (pages 30–40). That's two calls: POST /extract with pages="12-18" for the text, POST /split with ranges="30-40" for the appendix file. Or merge three monthly invoices with POST /merge, then POST /info on the result to confirm the page count and metadata before sending it on. Because everything is plain multipart POSTs, you can script these chains in curl, Python, or n8n without an SDK — the API surface is small enough to hold in your head.

The test suite: real PDFs, real round-trips

test_app.py doesn't mock the PDF layer — it generates real PDFs with reportlab (a 3-page document with known text and metadata) and pushes them through the actual HTTP endpoints via FastAPI's TestClient:

Run it with pytest -q. Testing a document API against real generated documents — rather than fixtures checked in years ago — means the tests stay honest as the library evolves.

Honest status and limits

Status: working. All five endpoints are implemented, the range parser validates strictly, encrypted files are rejected cleanly, and the end-to-end tests exercise real PDFs through real HTTP calls. Docker, Render, and CI deploy configs are present.

Roadmap

Who this is for

Three audiences get the most from YOU.PDF. Developers who keep writing one-off pypdf scripts get those scripts finished, tested, and behind an HTTP interface they can call from anything. Small teams that process documents — invoices, contracts, reports — get a self-hosted utility that keeps sensitive files off third-party upload sites. And automation builders get PDF primitives that slot into n8n, Zapier-style webhooks, or cron jobs: extract text from the morning's uploads, merge the week's invoices, split the client deliverable. The API is deliberately boring — multipart in, JSON or PDF out — which is exactly what makes it composable.

Frequently asked questions

What can YOU.PDF do?
Inspect PDF metadata and page counts, extract text per page (with page-range selection), merge multiple PDFs into one, and split page ranges — including reordered ranges — into a new PDF. All over a simple HTTP API you can self-host.
Do my documents get uploaded to a third party?
No. You run the service yourself (locally, on Docker, or on Render via the included config), so files never leave infrastructure you control.
Why does text extraction return empty for my scanned PDF?
Scanned-image PDFs have no text layer — there's nothing to extract. The README documents this; an OCR endpoint is on the roadmap.
What happens with password-protected PDFs?
They're rejected with HTTP 400 and a clear message: "Encrypted PDFs are not supported."

The bottom line

YOU.PDF is the kind of software the open-source ecosystem runs on: a small, sharp tool that does four jobs well, tests itself against real documents, and deploys anywhere. If you've ever written a throwaway pypdf script, this is that script — finished, tested, and given an HTTP interface.

Try it: github.com/Shivay00001/YOU.PDF — built by Shivam Kumar, VisionQuantech. Need document automation or a custom PDF pipeline for your business? [email protected]

References & further reading

  1. github.com/Shivay00001/YOU.PDF

Cite this article: Shivam Kumar (2026). YOU.PDF: A FastAPI PDF Toolkit — Extract, Merge, Split. VisionQuantech. https://visionquantech.com/blog/showcase-you-pdf.html

Want this for your business?

VisionQuantech builds AI receptionists, chatbots & automation for clinics, home services, real estate & more.

Book a Free Demo
Chat with us Email us