๐Ÿ“„ vue-pdf-embed

June 21, 2026 ยท View on GitHub

PDF embed component for Vue 3 (see Compatibility for Vue 2 support)

Awesome List npm Version npm Downloads GitHub Stars License

Features

  • Controlled rendering of PDF documents in Vue apps
  • Handling password-protected documents
  • Includes text layer (searchable and selectable documents)
  • Includes annotation layer (annotations and links)
  • No peer dependencies or additional configuration required
  • Can be used directly in the browser (see Examples)

Compatibility

This package is only compatible with Vue 3. For Vue 2 support, install vue-pdf-embed@1 and refer to the v1 docs.

Installation

Depending on the environment, the package can be installed in one of the following ways:

npm install vue-pdf-embed
yarn add vue-pdf-embed
<script src="https://unpkg.com/vue-pdf-embed"></script>

Usage

<script setup>
import VuePdfEmbed from 'vue-pdf-embed'

// Optional styles
import 'vue-pdf-embed/dist/styles/annotationLayer.css'
import 'vue-pdf-embed/dist/styles/textLayer.css'

// Either URL, Base64, binary, or document proxy
const pdfSource = '<PDF_URL>'
</script>

<template>
  <VuePdfEmbed annotation-layer text-layer :source="pdfSource" />
</template>

Props

NameTypeAccepted valuesDescription
annotationLayerbooleanwhether the annotation layer should be enabled
findControllerPDFFindControllerfind controller for highlighting text matches (requires textLayer)
formsbooleanwhether interactive form fields should be rendered (requires annotationLayer)
heightnumbernatural numbersdesired page height in pixels (ignored if the width property is specified)
imageResourcesPathstringURL or path with trailing slashpath for icons used in the annotation layer
linkServicePDFLinkServicedocument navigation service (replaces the default one that emits internal-link-clicked)
pagenumber
number[]
1 to the last page numberpage number(s) to display (displaying all pages if not specified)
rotationnumber0, 90, 180, 270 (multiples of 90)desired page rotation angle in degrees
scalenumberrational numbersrendering resolution multiplier (controls sharpness)
sourcestring
object
PDFDocumentProxy
document URL or Base64 or typed array or document proxysource of the document to display
textLayerbooleanwhether the text layer should be enabled
widthnumbernatural numbersdesired page width in pixels

Events

NameValueDescription
internal-link-clickeddestination page numberan internal link was clicked
loadedPDF document proxyfinished loading the document
loading-failederror objectfailed to load the document
password-requestedobject with callback function and isWrongPassword flaga password is required to display the document
progressobject with loaded and total byte countstracks the document's loading progress
renderedโ€“finished rendering the document
rendering-failederror objectfailed to render the document

Slots

NamePropsDescription
after-pagepage (page number)content to be added after each page
before-pagepage (page number)content to be added before each page

Public Methods

NameArgumentsDescription
downloadfilename (string)download the document
printprint resolution (number), filename (string), all pages flag (boolean)print the document via the browser interface

Note: Public methods can be accessed through a template ref.

Common Issues and Caveats

Server-Side Rendering

This is a client-side library that relies on browser APIs and cannot be server-rendered. Wrap it in a client-only boundary (Nuxt's <ClientOnly> or equivalent); if that doesn't keep it out of the server bundle, also lazy-load it with defineAsyncComponent.

Web Worker Loading

By default, the PDF.js web worker is bundled as a blob URL. This works out of the box, but it may be blocked by certain CSP (content security policy) configurations. In such cases, use the essential build and configure the worker manually:

import VuePdfEmbed, {
  GlobalWorkerOptions,
} from 'vue-pdf-embed/dist/index.essential.mjs'

// Option 1: use a bundler URL import
import PdfWorker from 'pdfjs-dist/build/pdf.worker.min.mjs?url'
GlobalWorkerOptions.workerSrc = PdfWorker

// Option 2: serve the worker from your public directory,
// copied from pdfjs-dist/build/pdf.worker.min.mjs
GlobalWorkerOptions.workerSrc = '/pdf.worker.min.mjs'

Document Loading

Typically, document loading is internally handled within the component. However, for optimization purposes, the document can be loaded with the usePdfDocument composable and then passed to the component via the source prop (e.g., when sharing the source between multiple instances of the component).

<script setup>
import VuePdfEmbed, { usePdfDocument } from 'vue-pdf-embed'

const { doc } = usePdfDocument({ source: '<PDF_URL>' })
</script>

<template>
  <VuePdfEmbed :source="doc" />
</template>

Full-text search over a loaded document is available through the usePdfSearch composable. Pass its findController to the :find-controller prop (with the text layer enabled) to highlight matches in place:

<script setup>
import VuePdfEmbed, { usePdfDocument, usePdfSearch } from 'vue-pdf-embed'

const { doc } = usePdfDocument({ source: '<PDF_URL>' })
const { find, findController } = usePdfSearch(doc)
</script>

<template>
  <input @keydown.enter="find($event.target.value)" />
  <VuePdfEmbed :find-controller="findController" text-layer :source="doc" />
</template>

Resources

The path to predefined CMaps should be provided to ensure correct rendering of documents with non-Latin characters and to avoid CMap-related errors:

<VuePdfEmbed
  :source="{
    cMapUrl: 'https://unpkg.com/pdfjs-dist/cmaps/',
    url: '<PDF_URL>',
  }"
/>

The image resource path must be specified for annotations to display correctly:

<VuePdfEmbed
  image-resources-path="https://unpkg.com/pdfjs-dist/web/images/"
  source="<PDF_URL>"
/>

For documents containing JPEG 2000 or JBIG2 images, the path to WebAssembly decoders must be specified:

<VuePdfEmbed
  :source="{
    url: '<PDF_URL>',
    wasmUrl: 'https://unpkg.com/pdfjs-dist/wasm/',
  }"
/>

Note: The examples above use a CDN to load resources, however these resources can also be included in the build by installing the pdfjs-dist package as a dependency and further configuring the bundler.

Examples

Basic Usage Demo (JSFiddle)

Advanced Usage Demo (JSFiddle)

Lazy Loading Demo (JSFiddle)

License

MIT License. Please see LICENSE file for more information.