unpdf
Extract text, links, images, and metadata from PDFs in Node.js, browsers, and serverless edge runtimes.
Repository Health
Technical Analysis
unpdf is a lightweight utility library built around Mozilla’s PDF.js that works consistently across every JavaScript runtime — Node.js, Deno, Bun, browsers, and edge platforms like Cloudflare Workers. Rather than requiring consumers to wrangle PDF.js’s browser-oriented API and worker-loading assumptions, unpdf ships a serverless build with the worker inlined and browser-only globals polyfilled, so getDocument and the rest of the PDF.js API work unmodified in environments that can’t load separate worker files or don’t have a DOM.
On top of that serverless PDF.js build, unpdf exposes a small set of high-level functions — extractText, extractTextItems, extractLinks, extractImages, getMeta, and renderPageAsImage — that cover the extraction and rendering tasks most PDF-processing code actually needs, particularly for AI applications that summarize or analyze uploaded documents. Consumers who need the raw PDF.js API, or want to swap in the official build instead of the bundled serverless one, can drop down via getResolvedPDFJS or definePDFJSModule without changing any call sites.
What You Get
- Serverless PDF.js build - A pre-bundled, worker-inlined build of PDF.js with browser-only globals polyfilled, so it runs in Cloudflare Workers and other edge runtimes with no separate worker file needed.
- Text extraction with and without layout - extractText for plain text (optionally merged across pages) and extractTextItems for positioned text items with coordinates, font size, and reading direction.
- Link and image extraction - extractLinks pulls every hyperlink from a document; extractImages returns raw pixel data, dimensions, and channel info per page.
- Metadata extraction - getMeta reads a PDF’s info and metadata dictionaries, with optional date parsing into Date objects.
- Page-to-image rendering - renderPageAsImage renders a page to an ArrayBuffer or data URL via @napi-rs/canvas, for thumbnailing or visual diffing.
- Drop-in swap to official PDF.js - definePDFJSModule lets you replace the bundled serverless build with pdfjs-dist or a legacy version without touching call sites.
Common Use Cases
- AI document summarization - Feed extracted PDF text into an LLM prompt to summarize uploaded reports, contracts, or research papers.
- Serverless PDF processing on the edge - Extract text or metadata from user-uploaded PDFs inside a Cloudflare Worker or other edge function with no Node-specific APIs required.
- Search indexing - Extract and normalize text from a corpus of PDFs to build a full-text search index.
- PDF link auditing - Extract all hyperlinks from a document to check for broken or outdated URLs before publishing.
- Thumbnail generation - Render the first page of an uploaded PDF as an image to show a preview in a document library UI.
Under The Hood
Architecture The entry point (src/index.ts) wraps a handful of low-level modules (text.ts, image.ts, links.ts, meta.ts) with a call to resolvePDFJSImport() before each operation, ensuring the PDF.js module is lazily resolved once via a module-level singleton before any extraction runs. utils.ts centralizes document lifecycle in withDocument(): it accepts either raw binary data or an existing PDFDocumentProxy, creates one via getDocumentProxy if needed, runs the caller’s operation, and destroys the proxy only if it created it itself, avoiding accidental double-frees on caller-supplied documents. The serverless PDF.js bundle lives under src/pdfjs-serverless/ (mocks, polyfills, Rolldown config) and is built separately via a dedicated build:pdfjs script before the main build runs, then copied into the published dist/pdfjs.mjs — so the package ships two build artifacts from one source tree: the wrapped API and the inlined PDF.js bundle. Browser-only globals are stubbed defensively before every module resolution, and DOMMatrix is polyfilled for canvas-less environments. It’s a clean, single-purpose module layout — no framework, no DI container, just pure async functions layered over one shared resolution/lifecycle utility, so a change to that utility’s caching or reload semantics affects every extraction path at once.
Tech Stack Written almost entirely in TypeScript (85% by bytes) with a small JavaScript serverless bundle, targeting any modern JS engine (Node >=22, browsers, Deno, Bun, Cloudflare Workers). It has zero declared runtime dependencies — PDF.js is bundled at build time via Rolldown rather than pulled in as a package dependency; pdfjs-dist and @napi-rs/canvas are devDependency/optional-peerDependency only, used for the official-build escape hatch and canvas-based page rendering respectively. Build tooling is tsdown (dual ESM/CJS output plus a small post-build script) and Rolldown (for the standalone serverless PDF.js bundle), with TypeScript in a fairly strict configuration (noUncheckedIndexedAccess, verbatimModuleSyntax). Package management is pnpm workspaces around a single package.
Code Quality Tests run under Vitest and are split by concern — document handling, text extraction, image extraction, link extraction, metadata, and the raw PDF.js resolution path — with fixtures and snapshot coverage. The test setup file is a notable quality signal: it spies on console.warn across every test and fails if PDF.js logs an “is not a function/defined/constructor” warning, an explicit guard against the serverless bundle silently missing an API the official build has. Error handling is explicit rather than swallowed — failed module resolution is wrapped in descriptive errors naming what failed, instead of passing through raw PDF.js exceptions. Public APIs use function overloads so return types track option values (e.g. extractText’s string vs string[] result based on mergePages) rather than forcing callers to type-guard. CI runs the full build pipeline, an “Are The Types Wrong” packaging check, type-checking of both source and built declaration files, ESLint, and the test suite on every push and pull request.
API Design The library’s core idea is repackaging PDF.js — a browser-oriented, worker-dependent rendering engine — into something that runs unmodified in environments that can’t spawn workers or don’t have a DOM, by inlining the worker into one bundle and polyfilling the handful of APIs those environments lack. That’s a genuinely useful packaging solution to a real, recurring pain point (running PDF.js on Cloudflare Workers and similar edge runtimes) rather than a new algorithm. API ergonomics are strong: six focused async functions, sensible Node-specific defaults baked into getDocumentProxy (font and CMap resolution), a clean escape hatch to the raw PDF.js API or an alternate build, and overloaded return types that remove the need for manual type narrowing. Documentation pairs every exported function with a runnable example.
Used by 9 apps in this directory
Activepieces
Automation · AI Assistants
Open-source AI automation platform that converts 280+ workflow integrations into MCP servers for LLMs, with no-code builders and TypeScript extensibility.
byterover-cli
AI Agents · AI Code Assistants
A portable memory layer for AI coding agents — curate structured project knowledge into a version-controlled context tree that syncs across tools, machines, and teammates.
LLM Gateway
AI Development · Devops
One API endpoint for 25+ LLM providers — route, track costs, enforce compliance, and switch models without changing your code.
Midday
Invoicing Finance · Productivity
All-in-one AI-powered business operations platform for freelancers and solo entrepreneurs to manage invoicing, time tracking, banking, and financial intelligence.
Next AI Draw.io
Developer Tools · AI Design Tools · Design Tools
Turn natural language into professional draw.io diagrams with AI, cloud icons, and an MCP server for your IDE.
NocoDB
No Code Platforms · Databases · Low Code Platforms
Turn any SQL database into a collaborative no-code spreadsheet with automatic REST APIs and real-time views.
Papra
Bookmarks Archiving
Self-hosted document archiving with email ingestion, OCR full-text search, and pluggable storage — store once, find anything.
Superagent
Security · AI Agents
An open-source SDK that blocks prompt injections, redacts PII and secrets, scans repositories for AI-targeted attacks, and red-teams production agents.
Valmis
AI Agents
A security-focused, self-hostable AI agent platform for production work — agents run in isolated containers that access credentials only through a host-side proxy, so the AI itself never sees API keys or plaintext credentials.