unpdf

repository·main·Indexed 22 days ago

https://github.com/unjs/unpdf

A runtime-agnostic utility library for PDF extraction and rendering, designed to work across Node.js, browsers, Deno, Bun, and serverless environments like Cloudflare Workers. It provides a specialized serverless build of PDF.js and includes high-level APIs for extracting text, structured text items, images, links, and metadata, as well as rendering PDF pages as images.

Tokens
5.8K
Snippets
28
Records
33
Agent score
78%

What's inside unpdf

  1. Install unpdf

    main

    You can install unpdf using pnpm or npm. This package provides utilities for PDF extraction and rendering across Node.js, Deno, Bun, the browser, and serverless environments like Cloudflare Workers.

    # pnpm
    pnpm add unpdf
    
    # npm
    npm install unpdf
  2. Security: Processing untrusted PDFs

    main

    When processing untrusted PDFs, you must manually manage resource limits as unpdf does not apply strict defaults for all operations:

    • Image decoding: Set maxImageSize in options to prevent massive memory allocation from a single image.
    • Page fan-out: Check pdf.numPages before calling extractText, extractTextItems, or extractLinks to avoid processing too many pages at once.
    • Timeouts: When using the serverless build, parsing runs on the main event loop. Wrap extraction calls in a timeout to prevent blocking.
  3. Extract text from a PDF

    main

    To extract text from a PDF, use getDocumentProxy to create a proxy from a Uint8Array, then call extractText. You can pass an options object to extractText with mergePages: true to combine text from all pages into a single string.

    import { extractText, getDocumentProxy } from 'unpdf'
    
    // Fetch a PDF from the web or load it from the file system
    const buffer = await fetch('https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf')
      .then(res => res.arrayBuffer())
    
    const pdf = await getDocumentProxy(new Uint8Array(buffer))
    const { totalPages, text } = await extractText(pdf, { mergePages: true })
    
    console.log(`Total pages: ${totalPages}`)
    console.log(text)
  4. Extract links from a PDF with `extractLinks`

    main

    Extracts all hyperlinks and external URLs from the document.

    import { readFile } from 'node:fs/promises'
    import { extractLinks, getDocumentProxy } from 'unpdf'
    
    const buffer = await readFile('./document.pdf')
    const pdf = await getDocumentProxy(new Uint8Array(buffer))
    const { totalPages, links } = await extractLinks(pdf)
  5. Create a `PDFDocumentProxy` with `getDocumentProxy`

    main

    The getDocumentProxy method creates a PDFDocumentProxy from binary PDF data. While most extraction methods accept raw data, using a proxy is recommended when you want to reuse the same document across multiple calls (e.g., extracting text, then images, then links).

    In Node.js, it automatically applies disableFontFace: true and resolves standard font/CMap data from the local pdfjs-dist package.

    const pdf = await getDocumentProxy(new Uint8Array(buffer))
  6. Configure a custom PDF.js build with `definePDFJSModule`

    main

    By default, unpdf uses a serverless build. If you need to use the official or a legacy PDF.js build (required for certain features like renderPageAsImage), call definePDFJSModule before any other method. This method accepts a function that returns a promise resolving to the PDF.js module.

    await definePDFJSModule(() => import('pdfjs-dist'))
  7. Extract metadata from a PDF with `getMeta`

    main

    Extracts metadata and info from a PDF. You can pass either raw data or an existing PDFDocumentProxy.

    const { info, metadata } = await getMeta(pdf, { parseDates: true })
  8. Use a custom PDF.js build with definePDFJSModule

    main

    By default, unpdf uses a bundled serverless build of PDF.js optimized for edge environments. If you need to use the official pdfjs-dist build or a legacy build, you must call definePDFJSModule before calling any other unpdf methods.

    import { definePDFJSModule, extractText, getDocumentProxy } from 'unpdf'
    
    // Define the PDF.js build before using any other unpdf method
    await definePDFJSModule(() => import('pdfjs-dist'))
    
    // Now, you can use all unpdf methods with the official PDF.js build
    const pdf = await getDocumentProxy(/* … */)
    const { text } = await extractText(pdf)
  9. Access the resolved PDF.js module with `getResolvedPDFJS`

    main

    Use getResolvedPDFJS() to get the underlying PDF.js module instance. If no custom build was defined via definePDFJSModule, it returns the default serverless build. This is useful for direct interaction with the PDF.js API.

    const pdfjs = await getResolvedPDFJS()
  10. Extract text from a PDF with `extractText`

    main

    Extracts text from a PDF.

    • If mergePages: true: Returns a single string containing all text from all pages, preserving line breaks.
    • If mergePages: false (default): Returns an array of strings, where each element corresponds to a page.
    const { totalPages, text } = await extractText(pdf, { mergePages: true })
  11. Access the underlying PDF.js API via getResolvedPDFJS

    main

    If the high-level unpdf methods (like extractText or extractImages) do not provide enough control, you can access the resolved PDF.js module directly using getResolvedPDFJS. This returns the module currently in use (either the custom defined one or the default serverless build).

    import { getResolvedPDFJS } from 'unpdf'
    
    // Get the version of the current PDF.js module
    const { version } = await getResolvedPDFJS()
    
    // Example: Using PDF.js native methods like getDocument and getMetadata
    import { readFile } from 'node:fs/promises'
    const { getDocument } = await getResolvedPDFJS()
    const data = await readFile('./dummy.pdf')
    const document = await getDocument(new Uint8Array(data)).promise
    
    console.log(await document.getMetadata())
  12. Extract images from a PDF page with `extractImages`

    main

    Extracts images from a specific page number. Returns an array of objects containing the image data (Uint8ClampedArray), dimensions, and color channels.

    import { readFile } from 'node:fs/promises'
    import sharp from 'sharp'
    import { extractImages, getDocumentProxy } from 'unpdf'
    
    async function extractPdfImages() {
      const buffer = await readFile('./document.pdf')
      const pdf = await getDocumentProxy(new Uint8Array(buffer))
    
      const imagesData = await extractImages(pdf, 1)
    
      for (const imgData of imagesData) {
        await sharp(imgData.data, {
          raw: {
            width: imgData.width,
            height: imgData.height,
            channels: imgData.channels
          }
        })
          .png()
          .toFile(`image.png`)
      }
    }