PDFs and webpages, as clean HTML
extract-pdf turns a PDF into structured HTML with headings, lists, footnotes and code blocks in milliseconds, with Granite Docling OCR for the pages that need it. extract-webpage pulls the main content and its citation out of any URL.
From a link or a file to readable text
Answer at once from the text layer, cite what you read, and spend OCR only on the pages that need it.
extract-pdf
A PDF (URL or ArrayBuffer) to structured HTML, with no PDF engine bundled.
Instant text layer
Headings by font size, lists, footnotes, code and quote blocks, and Table of Contents links, from the text layer in milliseconds.
OCR only where needed
A regex scan flags scanned pages, tables and figures; only those go through Granite Docling, in-process or on a remote processor.
Three parse methods
The pure-TS block algorithm everywhere, or LiteParse natively in Node or as WASM in browsers and Workers.
Runs on Workers
PDF.js comes from pdfjs-serverless at runtime. Node-only engines stay out of the bundle.
extract-webpage
Any URL to its main content and a citation, plus the text tools a research agent needs.
Main content
Readability and Mercury run side by side and the longer article wins, simplified to headings, paragraphs, images and links.
Citations
Author, date, title and publisher from meta tags and class names, with author names checked against 90,000 human names.
PDFs and DOCX too
A PDF URL goes through extract-pdf, and a DOCX buffer through JSZip.
Scraping with fallbacks
fetch first, then a Cloudflare Puppeteer scraper, then Jina Reader, with bot-detection checks and robots.txt rules.
Sentences, chunks and keyphrases
Sentence splitting that knows abbreviations, semantic chunks for LLMs, stemming, and SEEKTOPIC keyphrases.
A few lines, anywhere
The same calls in a script, a server or a Worker.
import { convertPDFToHTML } from 'extract-pdf';
const { html, title, author, ocrScan } = await convertPDFToHTML('https://arxiv.org/pdf/1706.03762', {
addPageNumbers: true,
});
console.log(title, author);
console.log(ocrScan.pagesNeedingOcr); // e.g. [3, 7]: pages with tables or figures