October DealsAmazon USOctober deal check: compare before you payAmazon US: current deals, useful picks and tech finds.Check DealsClean PCRecommendedOne scan can reveal what keeps slowing WindowsLook for cleanup and repair opportunities.Run ScanOctober DealsAmazon USDeal season is back - check today's better picksAmazon US: current deals, useful picks and tech finds.See Picks×
Skip to content
JavaScript

How to Add a PDF Viewer in React (React-PDF, PDF.js, Next.js, and Production Setup)

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

The most direct way to display an existing PDF in a React application is React-PDF: install the package, configure its PDF.js worker in the same module as your viewer components, and render Document and Page. You must also account for client-only rendering in Next.js, serve the app over HTTP rather than file://, and add loading, error, navigation and accessibility behavior.

Build a working viewer with React-PDF

The current React-PDF README documents the 11.x line. It requires React 19 or later and Node.js 22.13.0 or newer, so check the README for the exact package version your project will install before copying this example.

1. Install the dependency

npm install react-pdf

Yarn projects can use yarn add react-pdf. React-PDF uses PDF.js in the browser, including a separate worker for parsing and rendering PDF data.

2. Configure the PDF.js worker in the viewer module

Set GlobalWorkerOptions.workerSrc in the same module that imports and renders Document and Page. The project documentation warns that configuring it in a separate entry file can be overwritten by module execution order.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
import { useState } from 'react';
import { Document, Page, pdfjs } from 'react-pdf';
import 'react-pdf/dist/Page/AnnotationLayer.css';
import 'react-pdf/dist/Page/TextLayer.css';

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

export function PdfViewer({ file }) {
  const [numPages, setNumPages] = useState(null);
  const [pageNumber, setPageNumber] = useState(1);

  function handleLoadSuccess({ numPages: loadedPages }) {
    setNumPages(loadedPages);
    setPageNumber(1);
  }

  return (
    <section aria-label="PDF viewer">
      <Document
        file={file}
        onLoadSuccess={handleLoadSuccess}
        loading={<p>Loading PDF…</p>}
        error={<p role="alert">Unable to load this PDF.</p>}
      >
        <Page pageNumber={pageNumber} />
      </Document>
      {numPages && (
        <nav aria-label="PDF page navigation">
          <button
            type="button"
            onClick={() => setPageNumber((p) => Math.max(1, p - 1))}
            disabled={pageNumber <= 1}
          >
            Previous
          </button>
          <span>Page {pageNumber} of {numPages}</span>
          <button
            type="button"
            onClick={() => setPageNumber((p) => Math.min(numPages, p + 1))}
            disabled={pageNumber >= numPages}
          >
            Next
          </button>
        </nav>
      )}
    </section>
  );
}

Pass a URL, a File, a typed array or another value accepted by the installed React-PDF version as the file prop. For a public document, <PdfViewer file="/manual.pdf" /> is sufficient. For a user-selected file, pass the value from an <input type="file" /> element.

3. Render all pages only when the document is small

To show every page, create a Page for each loaded page:

{Array.from({ length: numPages ?? 0 }, (_, index) => (
  <Page key={index + 1} pageNumber={index + 1} />
))}

This is convenient for short documents but can create a large DOM and consume substantial memory for a long PDF. Use one page at a time, pagination, or virtualization for manuals and reports with many pages.

Next.js: keep the viewer on the client

React-PDF’s current guidance says the module that configures the worker and uses the components should skip server-side rendering in Next.js. With the App Router, put the viewer in a client component and dynamically import it with SSR disabled from the route that uses it:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
// app/documents/page.jsx
import dynamic from 'next/dynamic';

const PdfViewer = dynamic(() => import('../../components/PdfViewer'), {
  ssr: false,
  loading: () => <p>Preparing PDF viewer…</p>,
});

export default function DocumentsPage() {
  return <PdfViewer file="/manual.pdf" />;
}

Follow the React-PDF instructions for the router and release in your project instead of assuming this snippet applies unchanged to every Next.js version. Do not move worker setup into a server module.

Serve the application over HTTP

Mozilla’s PDF.js documentation states that its worker is not enabled for file:// URLs. Opening an HTML file directly from disk can therefore produce worker or loading failures even when the same code works in development. Start your normal development server, such as npm run dev, and test through its http://localhost address. Deployments must likewise serve the JavaScript bundle and worker from a reachable HTTP(S) origin.

Make the viewer usable in a real application

Loading and failure states

Use the loading, error and onLoadSuccess props to provide explicit status. Add an error boundary around the viewer as recommended by React-PDF’s documentation; malformed files, unavailable URLs and runtime rendering errors should not take down the surrounding page.

Page size and responsive layout

Give the viewer a defined container width and let the page scale to it. A common pattern is to measure the container with ResizeObserver and pass a calculated width to Page. Avoid hard-coding a desktop width that causes horizontal scrolling on phones. If you use scale instead, test high-density displays and narrow viewports.

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Text and annotation layers

Import the package’s text-layer and annotation-layer styles when you need selectable text, links or form annotations. Without the expected CSS, text can be offset or invisible over the canvas. Test links, keyboard focus and selection against your application’s global styles.

Navigation, zoom and download

A production viewer commonly adds page number entry, zoom controls, rotation, a download link and an “open in new tab” action. Keep controls as real buttons with accessible names, disable impossible actions, and expose the current page to assistive technology. A native download link can point at the same PDF URL:

<a href="/manual.pdf" download>Download PDF</a>

Browser and version compatibility

Compatibility is version-sensitive. React-PDF’s current documentation covers its 11.x branch, requires React 19+ and Node.js 22.13.0+, and targets current major browsers. Older supported browsers may need polyfills, bundler transpilation or a legacy worker; the examples specifically mention a URL.parse() polyfill for Chrome 125. Verify the matrix for the exact release and browsers you support.

Mozilla’s PDF.js page listed stable version 6.3.289 for modern and older browser builds on September 29, 2026; that listing is a point-in-time record, not a permanent version recommendation.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Alternatives when React-PDF is not the right fit

Route Best fit Important considerations
React-PDF A React component API with controls and layout built by your team Configure the worker, handle client-only loading where required, and add any layer CSS and navigation you need.
Mozilla PDF.js layers Lower-level control or a foundation for a custom viewer Understand the core, display and viewer layers. Mozilla asks embedders to re-skin or build on the viewer rather than embed an unmodified copy.
React PDF Kit A preassembled React structure and toolbar Its repository describes a proprietary license; commercial use requires a license. Version 2 defaults to PDF.js 5.4.530 and publishes its own browser matrix.
PDF.js Express Plus A commercial SDK with an official React integration Copy package assets to a publicly served location, mount WebViewer through a ref and initialize it in an effect. Production requires a commercial license key; its guide says no trial key is required.

Choose by required controls, customization, browser targets, deployment model and licensing. Published pricing was not established for these options here, so obtain current commercial terms from the vendor before procurement.

Troubleshooting checklist

“Setting up fake worker” or worker-load errors

  • Confirm the GlobalWorkerOptions.workerSrc assignment is in the same module as Document and Page.
  • Check that the installed pdfjs-dist worker path matches the package documentation for your React-PDF version.
  • Use the development server instead of opening the app with file://.
  • Inspect the browser network panel for a 404, blocked MIME type or content-security-policy violation.

The PDF URL returns an error

  • Open the URL directly and confirm it returns a PDF rather than an HTML login page.
  • For a different origin, configure CORS on the PDF host or proxy the file through your own server.
  • Check authentication headers or signed URL expiry; pass request data using the file-object form supported by your installed release.

Next.js crashes during build or hydration

Move the viewer into a client-only module and dynamically import it with ssr: false. Ensure worker configuration is not executed by a server component.

Large files are slow or crash mobile browsers

Render one page at a time, virtualize long lists, constrain image dimensions, and avoid mounting every page simultaneously. Measure memory on the least capable supported device rather than relying only on a desktop test.

Text or links look misaligned

Load the text and annotation layer styles supplied by React-PDF and check that global CSS is not changing the layer’s positioning, line height or pointer events.

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Performance, security and deployment notes

  • Prefer HTTPS for document URLs and avoid exposing access tokens in query strings when your server can provide short-lived authenticated URLs.
  • Set cache headers appropriate to document sensitivity. Private PDFs should not receive a publicly shareable cache policy.
  • Test PDFs with embedded fonts, scanned pages, annotations, encrypted permissions and unusually large images.
  • Keep the worker and main PDF.js code on compatible versions; upgrading one without the other can produce opaque runtime failures.
  • For accessibility, provide a visible document title, keyboard-operable controls and an alternate download route. Scanned PDFs may need OCR before their text is selectable.

Or skip the browser setup

If your goal is to capture a web page as an image or PDF rather than embed an interactive PDF inside React, ScreenshotNeo provides a single HTTP request. It accepts consent banners before capture and removes more than 60 known consent platforms, newsletter popups and chat widgets. Bot checks, CAPTCHAs, blank pages, timeouts, failed loads and cache hits are not billed, and each response reports its result through X-Page-Verdict and X-Billed headers. Its MCP server exposes take_screenshot, get_page_info and capture_pdf tools to Claude, Cursor and other MCP clients.

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp

See the ScreenshotNeo documentation for the full option set, including PDF paper size and margins, device presets, custom CSS and JavaScript, selector capture, waiting rules, headers, cookies, geolocation, signed links, asynchronous jobs and bulk capture.

In Python:

import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)

In Node.js:

const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);

The free plan includes 1,000 screenshots per month with no card. Paid plans start at $5 for 3,000 shots, and every feature is available on every plan. Create a free ScreenshotNeo account.

Frequently Asked Questions

Can I display a PDF with an HTML iframe instead of React-PDF?

Yes, a browser’s built-in PDF viewer can be embedded with an iframe, but it gives your React code little control over page navigation, rendering, annotations and consistent cross-browser behavior. React-PDF is appropriate when those controls belong in your application.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Why does the same PDF work in one browser but not another?

PDF.js support depends on the browser and the exact package release. Check the release browser matrix, required polyfills and worker choice, then test the target browser rather than inferring support from a single desktop browser.

Does React-PDF upload my document to a third-party service?

React-PDF is a client-side component using PDF.js. Whether a document leaves the browser depends on how your application obtains it; review your own URL, proxy and authentication design for sensitive files.

Should I use React PDF Kit or PDF.js Express Plus for a commercial product?

Evaluate their current license, browser matrix, required controls and deployment process. The cited project documentation states that React PDF Kit commercial use requires a license and PDF.js Express Plus production use requires a commercial key.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Leave a Reply

Your email address will not be published. Required fields are marked *

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Read next

Recommended PC Tool
Recommended PC Tool
PC Slower Than It Used to Be?Free scan - under a minute
Crashes, No Sound, or Screen Glitches?Free driver scan

Two free Windows tools

One Free Minute Could Fix That PC

Before you go - each of these free tools takes about a minute and tackles what quietly slows a Windows PC down.

Special offer. View Outbyte info, uninstall instructions, EULA, and Privacy Policy.