How to Print PDFs with PDF.js
Learn how to print PDFs in the PDF.js viewer, embed the workflow, handle loading and browser limits, and troubleshoot failed print jobs.
To print a PDF in the standard PDF.js viewer, open the document, select the Print button in the viewer toolbar, or press Ctrl+P ( Cmd+P on macOS). PDF.js prepares the document for printing, then your browser opens its normal print dialog. The browser, operating system, and printer provide the final paper or PDF output.
The official PDF.js FAQ documents Ctrl+P as the print shortcut. The viewer may first show “Preparing document for printing…” with progress and a Cancel action. It can also warn when printing is not fully supported by the browser or when the PDF is not fully loaded for printing.
1. Print a PDF in the standard PDF.js viewer
- Open the PDF in the PDF.js viewer.
- Wait until the document has loaded enough for the viewer to enable its controls.
- Click the printer icon, or press Ctrl+P. On macOS, use Cmd+P.
- Wait while PDF.js prepares the pages. A long document can take time because the viewer renders pages for the print pipeline.
- Choose the destination, paper size, orientation, margins, page range, color options, and other settings in the browser print dialog.
- Click Print, or choose a PDF destination if you want another PDF file instead of paper.
Do not close the tab during the preparation phase. If the viewer reports that the PDF is not fully loaded, let loading finish and try again.
2. Use the ready-made PDF.js viewer on a website
PDF.js provides a prebuilt generic viewer, an npm distribution named pdfjs-dist, and a source build. The project describes the viewer as a user interface built on the display layer; it is also a starting point when you need a custom viewer. See the official PDF.js setup guide.
Open a document with the viewer URL
The generic viewer accepts a file parameter. URL-encode the PDF URL before placing it in the query string:
<a href="/pdfjs/web/viewer.html?file=https%3A%2F%2Fcdn.example.com%2Fmanual.pdf">
Open the PDF
</a>
In JavaScript, use encodeURIComponent so query characters in the document URL do not become viewer parameters:
const pdfUrl = "https://cdn.example.com/manual.pdf";
const viewerUrl = `/pdfjs/web/viewer.html?file=${encodeURIComponent(pdfUrl)}`;
window.location.assign(viewerUrl);
The PDF server must allow the browser request. PDF.js restricts cross-origin loading by default, so configure suitable CORS headers or proxy the document through your own origin. The PDF.js FAQ covers the file parameter, URL encoding, CORS, and server-side proxy options.
Open a document from viewer code
When you control the viewer page, the application can open a document through PDFViewerApplication.open. The exact integration depends on the PDF.js version and whether you use the generic viewer or build your own interface, so keep your viewer and display-layer versions aligned.
const pdfUrl = "https://cdn.example.com/manual.pdf";
// Run this after the PDF.js generic viewer has initialized.
PDFViewerApplication.open({ url: pdfUrl });
3. Prebuilt viewer or custom viewer?
| Choice | What you get | Choose it when |
|---|---|---|
| Prebuilt generic viewer | A ready-made document interface, including the standard toolbar and print workflow. | You want PDF viewing and printing with limited UI work. |
pdfjs-dist npm package |
The distributed PDF.js code for integrating the display layer and related components into your application. | You want to integrate PDF.js into an existing application or supply your own interface. |
| Source build | The project source and the ability to build a more deeply customized viewer. | You need control over the viewer’s structure, branding, or behavior and can own the build work. |
The prebuilt viewer supplies more of the interface immediately. A custom viewer gives you more control over branding and interaction, but your application must take responsibility for integration and build configuration. The official project materials document these setup routes without claiming identical implementation effort or browser behavior for each one.
4. What happens during printing?
- PDF loading: PDF.js downloads and parses the document. A document that is still loading may not be printable yet.
- Print preparation: The viewer renders the pages needed by the print path and displays progress. The English localization includes “Preparing document for printing…” and a Cancel action.
- Browser print dialog: The browser takes over. Its dialog controls the destination, paper settings, page range, and printer access.
- Output: The browser sends the prepared pages to a physical printer or creates a PDF using the selected virtual destination.
PDF.js is the document viewer and preparation layer. It does not require a physical printer; a printer is only needed when the selected output is paper.
5. Complete minimal embed example
Place the PDF.js distribution in a directory such as /pdfjs, then link to the generic viewer:
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>PDF manual</title>
</head>
<body>
<iframe
title="PDF manual"
src="/pdfjs/web/viewer.html?file=https%3A%2F%2Fcdn.example.com%2Fmanual.pdf"
style="width:100%;height:80vh;border:0"
></iframe>
</body>
</html>
Serve this page over HTTP rather than opening it directly with a file: URL. A real web server makes relative assets resolve correctly and lets you configure the headers needed for the PDF request.
6. Troubleshooting PDF.js printing
| Symptom | Likely cause | Fix |
|---|---|---|
| No print button or shortcut appears to do anything | The generic viewer is not fully initialized, the document has not loaded, or a custom viewer omitted the print UI. | Wait for initialization and document loading. Confirm that you are using the standard viewer or implement a print control in your custom UI. |
| “Preparing document for printing…” never completes | A large or complex document is still being rendered, or loading has stalled. | Wait for loading to finish, check the browser network panel for failed PDF requests, then retry. Cancel and start again if the viewer exposes Cancel. |
| “Warning: The PDF is not fully loaded for printing.” | The viewer started printing before all required document data arrived. | Let the PDF finish loading and invoke Print again. |
| “Warning: Printing is not fully supported by this browser.” | The browser or version lacks a feature required by the viewer’s print path. | Validate the browser versions you support and try a current supported browser. Do not assume identical behavior across browsers. |
| The viewer shows a blank page or fails to open the file | The file value is not URL-encoded, the URL is wrong, or the PDF server blocks the cross-origin request. |
Wrap the URL with encodeURIComponent, verify the response URL, and configure CORS or use a same-origin proxy. |
| The PDF opens but printing fails on only some documents | Document complexity, loading state, or browser-specific support can affect preparation. | Compare with a small PDF, wait for full loading, inspect browser console errors, and test the intended browser and PDF set. |
| The browser dialog opens but paper output is wrong | Print settings such as scale, orientation, margins, paper size, or page range belong to the browser and printer. | Review those settings in the browser dialog and check the printer’s own paper configuration. |
7. Reliability and performance considerations
- Load before printing: Start printing only after the viewer indicates that the document is available. Partially loaded documents can trigger the not-fully-loaded warning.
- Document size matters: More pages and more complex page content generally require more preparation work. Keep the tab open until preparation completes.
- Browser coverage: Support varies by browser and version. Test the exact browsers used by your readers instead of promising one identical workflow everywhere.
- Network path: A slow or blocked PDF request delays both viewing and printing. Check CORS, authentication, redirects, and response errors before debugging the print button.
- Custom viewers: The more of the generic viewer you replace, the more loading, readiness, and print behavior your application must integrate and maintain.
8. Or skip the browser setup
If your goal is to produce a clean image or PDF of a web page rather than expose an interactive PDF.js viewer, ScreenshotNeo provides a website screenshot API and MCP server. It accepts one GET request and returns a PNG, JPEG, WebP, or PDF.
See the ScreenshotNeo API documentation for the available options.
cURL
curl -G "https://api.screenshotneo.com/v1/shot" \
-d access_key=YOUR_API_KEY \
--data-urlencode url=https://example.com/document.pdf \
-o shot.webp
Python
import requests
r = requests.get(
"https://api.screenshotneo.com/v1/shot",
params={
"access_key": "YOUR_API_KEY",
"url": "https://example.com/document.pdf",
},
timeout=90,
)
r.raise_for_status()
open("shot.webp", "wb").write(r.content)
Node.js
const q = new URLSearchParams({
access_key: 'YOUR_API_KEY',
url: 'https://example.com/document.pdf'
});
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
if (!res.ok) throw new Error(`ScreenshotNeo request failed: ${res.status}`);
const bytes = await res.arrayBuffer();
await Bun.write('shot.webp', bytes);
ScreenshotNeo removes cookie and consent banners, newsletter popups, and chat widgets before capture; bot checks, blank pages, failed loads, timeouts, and cache hits are not billed. Each response identifies the result with X-Page-Verdict and X-Billed headers. Its MCP server includes take_screenshot, get_page_info, and capture_pdf for Claude, Cursor, and other MCP clients. The free plan includes 1,000 screenshots per month with no card, and paid plans start at $5 for 3,000. Create a free ScreenshotNeo account.
9. FAQ
Can I print without a physical printer?
Yes. In the browser print dialog, select a PDF destination when your operating system provides one. A physical printer is only required for paper output.
Why does PDF.js need to prepare pages?
The viewer prepares the document for its print path before handing the job to the browser. That is why you may see progress and a Cancel action.
Is Ctrl+P the same as clicking Print?
In the standard viewer, both invoke the viewer’s print workflow. On macOS, use Cmd+P.
Should I build a custom print implementation?
Use the generic viewer when its supplied controls meet your needs. Choose a custom integration when your application needs its own interface and you are prepared to own the associated loading, browser support, and build work.
What should I check first when a remote PDF will not open?
Check that the URL is encoded, the server returns the PDF, and cross-origin requests are allowed by CORS or handled through a server-side proxy.


