Library / SDK
wojtekmaj/react-pdf avatar
wojtekmaj/react-pdf

react-pdf: rendering PDF pages as React components with a PDF.js worker

Display PDFs in your React app as easily as if they were images.

11,185 stars1,005 forksTypeScriptMIT

At a glance

What is it?
react-pdf lets a React tree own the PDF viewer. It is a thin component layer over Mozilla's PDF.js, which means the component API is small but the worker, the browser floor and the React version are all yours to manage.
Who is it for?
Adopt react-pdf when the PDF view has to live inside your own React component tree and you can pin React 19, Node.js 22.13.0 and a modern browser baseline. Do not adopt it if you need to generate PDFs (that is @react-pdf/renderer), if you need to support browsers below Chrome 125 or Safari 18, or if you want a viewer that ships its own toolbar, thumbnails and zoom controls, since react-pdf renders pages and leaves that UI to you.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 2 days ago.
What is it written in?
Mainly TypeScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 1, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What react-pdf actually takes off your plate

Embedding a PDF in a web app usually means one of two things: an iframe pointed at the file, or a full viewer product with its own chrome. react-pdf takes a third position. It gives you React components that render PDF pages, so the document becomes part of your component tree and inherits your state, your layout and your event handlers.

The README is explicit about the boundary: this package is used to display existing PDFs. If you want to create PDFs using React, the README points at @react-pdf/renderer instead. That distinction matters because the two packages share a naming space and people conflate them constantly. react-pdf is a viewer.

The audience is a frontend engineer who already has a PDF somewhere (a URL, a base64 string, a Uint8Array) and needs it on screen inside a React app, with control over what surrounds it. If you wanted a ready-made toolbar with page navigation, zoom and download buttons, react-pdf does not hand you one. You build that, and the README's tl;dr is honest about the size of the job: import Document, wrap the viewer in Suspense and an error boundary, add Page components inside.

The Document and Page component model, and the worker it depends on

The architecture visible in the README is a component layer sitting on top of PDF.js. Document takes a file prop, which the README says can be a URL, base64 content, a Uint8Array and more. Page components go inside Document and render individual pages. That is the whole mental model: one container, many pages.

What makes this more than a wrapper is the worker. PDF.js parses and renders in a web worker, and react-pdf exposes pdfjs from its own entry point so you can set pdfjs.GlobalWorkerOptions.workerSrc. The README gives three ways to satisfy that requirement: import the worker through a URL constructed with import.meta.url, copy pdf.worker.mjs from pdfjs-dist/build into your output folder yourself, or point workerSrc at an external CDN such as unpkg.

The README carries a warning worth reading twice. workerSrc must be set in the same module where you use react-pdf components. Setting it in main.tsx and then importing react-pdf in another component may let the default value overwrite your setting because of module execution order. That is a real failure mode, and it is the kind of thing that produces a working local build and a broken production bundle.

There is also a rendering detail that the README treats as opt-in: stylesheets for annotations and for the text layer are imported separately if applicable. Pages render without them, but selection and annotation rendering depend on them.

Installing react-pdf and rendering a first document

The README gives the install command directly: npm install react-pdf, or yarn add react-pdf. Node.js 22.13.0 or newer is required, and the latest version of react-pdf needs React 19 or later in your project. Check both before you start, because neither is negotiable at runtime.

After installing, the worker has to be configured. The README's recommended approach constructs the worker URL relative to the module:

ts
import { pdfjs } from 'react-pdf';

pdfjs.GlobalWorkerOptions.workerSrc = new URL(
  'pdfjs-dist/build/pdf.worker.min.mjs',
  import.meta.url,
).toString();

Put that in the same file where you render the components, not in a shared entry point. The README warns that splitting them can cause the default value to overwrite your setting.

Then render a document. The README's tl;dr describes wrapping the viewer in React Suspense and an error boundary, then adding Document with a file prop and Page components inside it. The file prop accepts a URL, base64 content or a Uint8Array. If your PDF has annotations or you want selectable text, import the corresponding stylesheets as the README instructs. If you are on Next.js before v15, the README notes you may need swcMinify: false in next.config.js. pnpm users may need to hoist pdfjs-dist, either through public-hoist-pattern[]=pdfjs-dist in .npmrc for pnpm below 11, or publicHoistPattern in pnpm-workspace.yaml for pnpm 11 and later.

Where react-pdf stops and you start

The clearest limitation is scope. react-pdf renders pages. It does not give you a viewer. There is no toolbar, no page navigation control, no zoom widget and no download button in the component set described by the README. The related searches around react-pdf zoom and react pdf download reflect that gap: people look for those features because the package does not ship them.

The second constraint is the browser floor. The README states minimum requirements of Chrome 125 and Safari 18 (iOS 18), and it is careful to add that polyfilling a single API does not establish compatibility with browsers below those minimums. The README even shows a URL.parse polyfill for Chrome 125 while stating that this alone is not a compatibility solution. If your audience includes older Android WebViews or corporate browsers, react-pdf is the wrong tool, and the legacy worker path the README describes is described as not a complete backwards-compatibility solution either.

The third is version coupling. The README documents the 11.x branch, requires React 19 or later for the latest version, and links separate documentation for v10 through v5. Upgrading react-pdf is not a drop-in npm update if you are behind on React; you either move React forward or stay on an older react-pdf branch and read that branch's README.

react-pdf versus a batteries-included viewer

The real alternative in this space is a viewer component that packages PDF.js with its own UI layer, of the kind people search for as react-pdf-viewer/core, or an annotation-focused library such as the one searched for as react-pdf-highlighter. The difference is not quality, it is where the abstraction line sits.

A batteries-included viewer hands you a rendered toolbar, page controls and often a plugin system, at the cost of styling opinions you have to override and a second dependency to keep current. react-pdf hands you Document and Page and nothing else. You get full control over markup and styling, and you pay for it by writing the controls yourself.

There is also a lower-level option: use PDF.js directly. react-pdf is a React binding over it, and the README's worker instructions show how thin that binding is. If your app is not React, or if you need to drive the PDF.js API in ways the component props do not expose, going straight to PDF.js removes a layer. The trade-off is that you then own the React lifecycle, rendering and cleanup yourself.

One naming trap: @react-pdf/renderer is not an alternative, it solves the opposite problem. The README says so directly. Choosing between them is not a comparison, it is deciding whether you are reading PDFs or writing them.

Maintenance, licence and what an upgrade costs

The repository is not archived, and the last push was on 2026-09-21. Release history shows v11.0.0 on 2026-09-10, v10.5.0 on 2026-08-20 and v10.4.1 on 2026-02-25, so the 10.x line ran for roughly six months between v10.4.1 and v10.5.0 before the 11.0.0 major. That cadence is worth planning around: majors arrive, and the README maintains per-branch documentation going back to v6.

The licence is MIT, which permits commercial use, modification and redistribution provided the copyright notice and permission notice are included. That is a summary of the licence identifier, not legal advice; read the LICENSE file in the repository for the actual terms.

Upgrade cost is dominated by two dependencies you do not control directly. React 19 or later is required for the latest version, so a project on React 18 either upgrades React or stays on an older branch. The browser floor moves with PDF.js, so each react-pdf major can raise the minimum Chrome and Safari versions your app supports. The repository is a monorepo with packages/ and a sample/ directory containing next-app, next-pages, parcel2, vite and webpack5 examples, which is useful when a bundler-specific problem appears, though those samples are reference material rather than a guarantee about your configuration.

Editorial conclusion

Adopt react-pdf when the PDF view has to live inside your own React component tree and you can pin React 19, Node.js 22.13.0 and a modern browser baseline. Do not adopt it if you need to generate PDFs (that is @react-pdf/renderer), if you need to support browsers below Chrome 125 or Safari 18, or if you want a viewer that ships its own toolbar, thumbnails and zoom controls, since react-pdf renders pages and leaves that UI to you. Before the first commit, verify three things in your own project: that the PDF.js worker is configured in the same module that renders Document and Page, that your bundler resolves pdfjs-dist (pnpm users may need to hoist it), and which react-pdf major version your existing React version supports, because the README documents the 11.x branch against React 19 or later.

Frequently asked questions

Is react-pdf free?

Yes. The repository is licensed under MIT, which allows commercial use, modification and redistribution as long as the copyright and permission notices are kept. Read the LICENSE file for the exact terms.

How do I install react-pdf?

Run npm install react-pdf or yarn add react-pdf. Your project needs Node.js 22.13.0 or newer, and the latest version requires React 19 or later. After installing, you still have to configure the PDF.js worker.

How do I use react-pdf in Next.js?

The worker setup is the same, but the README notes that in Next.js you must skip SSR when importing the module that sets workerSrc, with links to the Pages Router and App Router guides. On Next.js before v15 you may also need swcMinify: false in next.config.js.

What is react-pdf?

react-pdf is a package for displaying existing PDFs in a React app. The README describes it as displaying PDFs as easily as if they were images, and it points readers who want to create PDFs at @react-pdf/renderer instead.

How do I use react-pdf?

Import Document from react-pdf, wrap the viewer in React Suspense and an error boundary, then add Document with a file prop and Page components inside it. The file prop accepts a URL, base64 content or a Uint8Array, and the PDF.js worker has to be configured first.

How does react-pdf compare to using pdf.js directly?

react-pdf is a React component layer over PDF.js, and the README's worker instructions show how thin that binding is: you still set pdfjs.GlobalWorkerOptions.workerSrc yourself. Using PDF.js directly removes the React layer but leaves you to manage rendering and lifecycle on your own.

Official sources

  1. License: MIT
  2. Project website
  3. README
  4. Releases
  5. wojtekmaj/react-pdf on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/wojtekmaj-react-pdf.svg)](https://hysenlabs.com/projects/wojtekmaj-react-pdf)