How to download view only protected PDF from Google Drive

cover

Use this script to download a view-only PDF file from Google Drive.

It captures all visible PDF pages as images with high resolution and merges them into a single PDF.

If only some part of the document appears, try zooming out before running the script.

Instructions:

  1. Open the PDF on Google Drive
  2. Click Preview
  3. Scroll to the bottom of the document (ensure all pages are visible)
  4. Open Developer Tools in a separate window → Console tab
  5. Paste and run the script (remove “allow pasting” warning if needed)

Highly Recommended: Use Script 1


Script 1

// Check if policy exists, otherwise create it
if (!window.scriptPolicy) {
  window.scriptPolicy = window.trustedTypes.createPolicy(
    "jspdf-loader-unique",
    {
      createScriptURL: (url) => url,
    },
  );
}

let jspdfScript = document.createElement("script");
// Use the window-scoped policy
jspdfScript.src = window.scriptPolicy.createScriptURL(
  "https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.5.1/jspdf.umd.min.js",
);

jspdfScript.onload = function () {
  const { jsPDF } = window.jspdf;
  const pdf = new jsPDF();
  const images = document.getElementsByTagName("img");
  let imagesProcessed = 0;

  for (let i = 0; i < images.length; i++) {
    const img = images[i];
    if (!img.src.startsWith("blob:")) continue;

    const canvas = document.createElement("canvas");
    const ctx = canvas.getContext("2d");
    canvas.width = img.naturalWidth || img.width;
    canvas.height = img.naturalHeight || img.height;
    ctx.drawImage(img, 0, 0);

    const imgData = canvas.toDataURL("image/jpeg", 1.0);
    if (imagesProcessed > 0) pdf.addPage();

    const pageWidth = pdf.internal.pageSize.getWidth();
    const pageHeight = pdf.internal.pageSize.getHeight();
    const ratio = Math.min(
      (pageWidth - 20) / canvas.width,
      (pageHeight - 20) / canvas.height,
    );
    const imgWidth = canvas.width * ratio;
    const imgHeight = canvas.height * ratio;

    pdf.addImage(
      imgData,
      "JPEG",
      (pageWidth - imgWidth) / 2,
      (pageHeight - imgHeight) / 2,
      imgWidth,
      imgHeight,
    );
    imagesProcessed++;
  }

  if (imagesProcessed > 0) {
    pdf.save("Exported_File.pdf");
    console.log(`Success! Exported ${imagesProcessed} images.`);
  } else {
    console.warn("No blob images found.");
  }
};

document.body.appendChild(jspdfScript);
js

Script 2

(function () {
  console.log("Loading script ...");

  let script = document.createElement("script");
  script.onload = function () {
    const { jsPDF } = window.jspdf;
    let pdf = null;
    let imgElements = document.getElementsByTagName("img");
    let validImgs = [];
    let initPDF = true;

    console.log("Scanning content ...");
    for (let i = 0; i < imgElements.length; i++) {
      let img = imgElements[i];
      let checkURLString = "blob:https://drive.google.com/";
      if (img.src.substring(0, checkURLString.length) !== checkURLString) {
        continue;
      }
      validImgs.push(img);
    }
    console.log(`${validImgs.length} content found!`);
    console.log("Generating PDF file ...");
    for (let i = 0; i < validImgs.length; i++) {
      let img = validImgs[i];
      let canvasElement = document.createElement("canvas");
      let con = canvasElement.getContext("2d");
      canvasElement.width = img.naturalWidth;
      canvasElement.height = img.naturalHeight;
      con.drawImage(img, 0, 0, img.naturalWidth, img.naturalHeight);
      let imgData = canvasElement.toDataURL();

      let orientation = img.naturalWidth > img.naturalHeight ? "l" : "p";
      let pageWidth = img.naturalWidth;
      let pageHeight = img.naturalHeight;

      if (initPDF) {
        pdf = new jsPDF({
          orientation: orientation,
          unit: "px",
          format: [pageWidth, pageHeight],
        });
        initPDF = false;
      }
      if (!initPDF) {
        pdf.addImage(imgData, "PNG", 0, 0, pageWidth, pageHeight, "", "SLOW");
        if (i !== validImgs.length - 1) {
          pdf.addPage();
        }
      }
      const percentages = Math.floor(((i + 1) / validImgs.length) * 100);
      console.log(`Processing content ${percentages}%`);
    }
    let title = document.querySelector('meta[itemprop="name"]').content;
    if (title.split(".").pop() !== "pdf") {
      title = title + ".pdf";
    }
    console.log("Downloading PDF file ...");
    pdf.save(title, { returnPromise: true }).then(() => {
      document.body.removeChild(script);
      console.log("PDF downloaded!");
    });
  };
  let scriptURL = "https://unpkg.com/jspdf@latest/dist/jspdf.umd.min.js";
  let trustedURL;
  if (window.trustedTypes && trustedTypes.createPolicy) {
    const policy = trustedTypes.createPolicy("myPolicy", {
      createScriptURL: (input) => input,
    });
    trustedURL = policy.createScriptURL(scriptURL);
  } else {
    trustedURL = scriptURL;
  }
  script.src = trustedURL;
  document.body.appendChild(script);
})();
js

Script 3

const pdfDocumentName = "Document";
let docDataUrls = "";
function generatePDFDataFile() {
  const imgTags = document.getElementsByTagName("img");
  const checkURLString = "blob:https://drive.google.com/";
  Array.from(imgTags).forEach((img) => {
    if (img.src.startsWith(checkURLString)) {
      const canvas = document.createElement("canvas");
      const context = canvas.getContext("2d");
      canvas.width = img.naturalWidth;
      canvas.height = img.naturalHeight;
      context.drawImage(img, 0, 0, img.naturalWidth, img.naturalHeight);
      const imgDataURL = canvas.toDataURL();
      docDataUrls += `${docDataUrls ? "\\n" : ""}${imgDataURL}`;
    }
  });
  const file = new Blob([docDataUrls], { type: "Tutorial" });
  const url = URL.createObjectURL(file);
  const anchorElement = document.createElement("a");
  anchorElement.href = url;
  anchorElement.download = `${pdfDocumentName}.PDF_DataFile`;
  document.body.appendChild(anchorElement);
  anchorElement.click();
}
function autoScrollAndGeneratePDF() {
  const allElements = document.querySelectorAll("*");
  let chosenElement = null;
  let heightOfScrollableElement = 0;
  allElements.forEach((element) => {
    if (element.scrollHeight > element.clientHeight) {
      if (heightOfScrollableElement < element.scrollHeight) {
        chosenElement = element;
        heightOfScrollableElement = element.scrollHeight;
      }
    }
  });
  if (
    chosenElement &&
    chosenElement.scrollHeight > chosenElement.clientHeight
  ) {
    console.log("Auto Scroll");
    const scrollDistance = Math.round(chosenElement.clientHeight / 2);
    let remainingHeightToScroll = chosenElement.scrollHeight;
    let scrollToLocation = 0;
    function myLoop(remainingHeight, scrollTo) {
      setTimeout(() => {
        scrollTo += scrollDistance;
        chosenElement.scrollTo(0, scrollTo);
        remainingHeight -= scrollDistance;
        if (remainingHeight > 0) {
          myLoop(remainingHeight, scrollTo);
        } else {
          setTimeout(generatePDFDataFile, 1500);
        }
      }, 400);
    }
    myLoop(remainingHeightToScroll, scrollToLocation);
  } else {
    console.log("No Scroll Needed");
    setTimeout(generatePDFDataFile, 1500);
  }
}
autoScrollAndGeneratePDF();
js

Script 4

function loadJsPDF(callback) {
  let script = document.createElement("script");
  script.onload = callback;
  script.src =
    "https://cdnjs.cloudflare.com/ajax/libs/jspdf/1.5.3/jspdf.debug.js";
  document.body.appendChild(script);
}
function processAndGeneratePDF() {
  const pdfDocumentName = "Document.pdf";
  let doc = null;
  function addImageToPDF(img) {
    const canvas = document.createElement("canvas");
    const ctx = canvas.getContext("2d");
    canvas.width = img.naturalWidth;
    canvas.height = img.naturalHeight;
    ctx.drawImage(img, 0, 0);
    const imgData = canvas.toDataURL();
    const orientation = img.naturalWidth > img.naturalHeight ? "l" : "p";
    const scaleFactor = 1.335;
    const pageWidth = img.naturalWidth * scaleFactor;
    const pageHeight = img.naturalHeight * scaleFactor;
    if (!doc) {
      doc = new jsPDF({
        orientation,
        unit: "px",
        format: [pageWidth, pageHeight],
      });
    } else {
      doc.addPage([pageWidth, pageHeight], orientation);
    }
    doc.addImage(imgData, "PNG", 0, 0, img.naturalWidth, img.naturalHeight);
  }
  function processValidImages() {
    const imgTags = document.getElementsByTagName("img");
    const checkURLString = "blob:https://drive.google.com/";
    Array.from(imgTags).forEach((img) => {
      if (img.src.startsWith(checkURLString)) {
        addImageToPDF(img);
      }
    });
    if (doc) {
      doc.save(pdfDocumentName);
    }
  }
  function handleAutoScrollAndGeneratePDF() {
    const elementsWithScroll = Array.from(
      document.querySelectorAll("*"),
    ).filter((el) => el.scrollHeight > el.clientHeight);
    const chosenElement = elementsWithScroll.reduce(
      (maxEl, currentEl) =>
        currentEl.scrollHeight > (maxEl.scrollHeight || 0) ? currentEl : maxEl,
      {},
    );
    if (chosenElement.scrollHeight > chosenElement.clientHeight) {
      console.log("Auto Scroll");
      let remainingHeight = chosenElement.scrollHeight;
      const scrollDistance = Math.round(chosenElement.clientHeight / 2);
      function scrollAndGenerate() {
        if (remainingHeight > 0) {
          chosenElement.scrollBy(0, scrollDistance);
          remainingHeight -= scrollDistance;
          setTimeout(scrollAndGenerate, 500);
        } else {
          setTimeout(processValidImages, 1500);
        }
      }
      scrollAndGenerate();
    } else {
      console.log("No Scroll");
      setTimeout(processValidImages, 1500);
    }
  }
  handleAutoScrollAndGeneratePDF();
}
loadJsPDF(processAndGeneratePDF);
js

Final Steps

  1. Wait for the script to process and download the PDF
  2. The speed of processing depends on the number and size of pages
  3. Enjoy!
share your thoughts