How to Password Protect and Encrypt PDF Files Client-Side with JavaScript

A PDF file can be encrypted, for security, in which case a password is needed to view or edit the contents. Dynamsoft Document Viewer is a JavaScript SDK for document scanning and viewing, which can encrypt and decrypt a PDF file. In this article, we are going to explore how to use it.

What you’ll build: A browser-based tool that opens, decrypts, and encrypts PDF files entirely client-side using Dynamsoft Document Viewer — no server required.

Key Takeaways

  • Dynamsoft Document Viewer can encrypt and decrypt PDF files entirely in the browser using JavaScript, with no server-side processing.
  • Use the loadSource method with a password parameter to open password-protected PDFs, and saveToPdf with a password option to create encrypted PDFs.
  • All PDF processing happens client-side via WebAssembly, keeping sensitive documents off the network.
  • This approach works for any workflow that needs to add or remove password protection from PDFs in a web application.

Common Developer Questions

  • How do I open a password-protected PDF in JavaScript without a server?
  • How can I encrypt and password protect a PDF file client-side with JavaScript?
  • How do I remove the password from a PDF using JavaScript in the browser?

Prerequisites

  • A modern browser (Chrome, Firefox, Edge, or Safari).
  • Basic knowledge of HTML and JavaScript.
  • A Dynamsoft Document Viewer license. Get a 30-day free trial license for Dynamsoft Document Viewer.

Step 1: Open a PDF File with Dynamsoft Document Viewer

  1. Create a new HTML file with the following template.

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <meta http-equiv="X-UA-Compatible" content="IE=edge">
      <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no">
      <title>Browse Viewer</title>
      <style>
      </style>
    </head>
    <body>
    </body>
    <script>
    </script>
    </html>
    
  2. Include Dynamsoft Document Viewer’s files.

    <script src="https://cdn.jsdelivr.net/npm/dynamsoft-document-viewer@2.1.0/dist/ddv.js"></script>
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/dynamsoft-document-viewer@2.1.0/dist/ddv.css">
    
  3. Initialize Dynamsoft Document Viewer with a license. You can apply for one here.

    Dynamsoft.DDV.Core.license = "LICENSE-KEY"; 
    Dynamsoft.DDV.Core.engineResourcePath = "https://cdn.jsdelivr.net/npm/dynamsoft-document-viewer@2.1.0/dist/engine";// Lead to a folder containing the distributed WASM files
    await Dynamsoft.DDV.Core.init();
    
  4. Create a new document instance.

    const docManager = Dynamsoft.DDV.documentManager;
    const doc = docManager.createDocument();
    
  5. Create an instance of browse viewer, bind it to a container and use it to view the document we just created.

    HTML:

    <div id="viewer"></div>
    

    JavaScript:

    const browseViewer = new Dynamsoft.DDV.BrowseViewer({
      container: document.getElementById("viewer"),
    });
    
    browseViewer.openDocument(doc.uid);
    

    CSS:

    #viewer {
      width: 320px;
      height: 480px;
    }
    
  6. Use input to select a PDF file and load it into the document instance so that we can use the browse viewer to view the file.

    HTML:

    <label>
      Select a PDF file to load:
      <br/>
      <input type="file" id="files" name="files" accept=".pdf" onchange="filesSelected()"/>
    </label>
    

    JavaScript:

    async function filesSelected(){
      let filesInput = document.getElementById("files");
      let files = filesInput.files;
      if (files.length>0) {
        const file = files[0];
        const blob = await readFileAsBlob(file);
        await doc.loadSource(blob); // load the PDF file
      }
    }
    
    function readFileAsBlob(file){
      return new Promise((resolve, reject) => {
        const fileReader = new FileReader();
        fileReader.onload = async function(e){
          const response = await fetch(e.target.result);
          const blob = await response.blob();
          resolve(blob);
        };
        fileReader.onerror = function () {
          reject('oops, something went wrong.');
        };
        fileReader.readAsDataURL(file); 
      })
    }
    

Step 2: Open a Password-Protected PDF

If the PDF is password-protected, it will fail to open the PDF and throw an error, which indicates that we need to enter a password to open it.

Error: Failed to read the PDF file because it's encrypted and the correct password is not provided.

We can catch the error and ask the user to enter a password.

HTML:

<div class="modal input-modal">
  <div>
    <label>
      Please input the password:
    </label>
    <br/>
    <input type="password" id="password"/>
    <br/>
    <button id="okayBtn">Okay</button>
  </div>
</div>

CSS:

.modal {
  display: flex;
  align-items: flex-start;
  position: fixed;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  min-width: 250px;
  border: 1px solid gray;
  border-radius: 5px;
  background: white;
  z-index: 9999;
  padding: 10px;
  visibility: hidden;
}

.input-modal.active {
  visibility: inherit;
}

JavaScript:

function filesSelected(){
  //...
  try {
    await doc.loadSource(blob);
  } catch (error) {
    if (error.cause.code === -80202) {
      askForPassword();
    }
  }
}

function askForPassword(){
  document.getElementById("password").value = ""; //clear previous password
  document.getElementsByClassName("input-modal")[0].classList.add("active");
}

document.getElementById("okayBtn").addEventListener("click",async function(){
  document.getElementsByClassName("input-modal")[0].classList.remove("active");
  try {
    await doc.loadSource({fileData:blob,password:document.getElementById("password").value});  
  } catch (error) {
    alert(error);
  }
})

We have to pass the password info to the loadSource method:

await doc.loadSource({fileData:blob,password:document.getElementById("password").value});  

Step 3: Save or Remove PDF Password Protection

We can save the PDF without a password to create a decrypted PDF, or set a new password to create an encrypted PDF.

<div>
  <label>Set a password:
    <input type="password" id="newPassword"/>
  </label>
</div>
<script>
let newPassword = document.getElementById("newPassword").value;
let blob;
if (newPassword) {
  blob = await doc.saveToPdf({password:newPassword});
}else{
  blob = await doc.saveToPdf();
}
</script>

Common Issues and Edge Cases

  • Wrong password gives a generic error. If the user enters an incorrect password, loadSource throws an error. Always catch it and prompt the user to re-enter the password rather than letting the error propagate silently.
  • Large PDF files may cause slow processing. Because encryption and decryption happen client-side in WebAssembly, very large PDFs (50 MB+) can take several seconds. Consider showing a loading indicator during loadSource and saveToPdf calls.
  • Some PDFs use owner-password vs. user-password. A PDF can have two passwords: one for viewing (user password) and one for editing (owner password). Dynamsoft Document Viewer’s loadSource expects the user password to open the file.

Frequently Asked Questions

How do I encrypt a PDF with a password in JavaScript without a backend?

Use Dynamsoft Document Viewer’s saveToPdf({password: "yourPassword"}) method. All encryption is handled client-side via WebAssembly, so no server round-trip is needed.

Can I decrypt and remove the password from a PDF in the browser?

Yes. Load the encrypted PDF with loadSource({fileData: blob, password: "currentPassword"}), then call saveToPdf() without a password parameter to save a decrypted copy.

What happens if the PDF password is incorrect?

Dynamsoft Document Viewer throws an error with code -80202. You should catch this error and prompt the user to enter the correct password.

Source Code

Get the source code of the demo to have a try:

https://github.com/tony-xlh/PDF-Encryption-JavaScript