Skip to content

Instantly share code, notes, and snippets.

@dpaluy
Last active August 27, 2026 16:41
Show Gist options
  • Select an option

  • Save dpaluy/74258794f7930401cc27262e0ea794dd to your computer and use it in GitHub Desktop.

Select an option

Save dpaluy/74258794f7930401cc27262e0ea794dd to your computer and use it in GitHub Desktop.
Download view only protected PDF from Google Drive

Step by step guide to downloading protected PDF from Google Drive

  1. Open the document in Google Docs
  2. Scroll to the bottom of the document, so all the pages are present
  3. Open Developer Tools on separate window and choose the Console tab
  4. Paste the code
  5. Have fun!
let jspdf = document.createElement("script");
jspdf.onload = function () {
let pdf = new jsPDF();
let elements = document.getElementsByTagName("img");
for (let i in elements) {
let img = elements[i];
console.log("add img ", img);
if (!/^blob:/.test(img.src)) {
console.log("invalid src");
continue;
}
let can = document.createElement('canvas');
let con = can.getContext("2d");
can.width = img.width;
can.height = img.height;
con.drawImage(img, 0, 0);
let imgData = can.toDataURL("image/jpeg", 1.0);
pdf.addImage(imgData, 'JPEG', 0, 0);
pdf.addPage();
}
pdf.save("download.pdf");
};
jspdf.src = 'https://cdnjs.cloudflare.com/ajax/libs/jspdf/1.5.3/jspdf.debug.js';
document.body.appendChild(jspdf);
@ChaitanyaSatkuri

ChaitanyaSatkuri commented Jul 14, 2026

Copy link
Copy Markdown

// === Google Drive PDF Downloader (Full Pages) ===
(async function() {
// Step 1: Scroll through the entire document to force all pages to render
const scrollContainer = document.querySelector('[role="main"]')
|| document.querySelector('.a-s-qi-bg-B')
|| document.querySelector('[class*="ndfHFb"]')
|| document.documentElement;

// Find the scrollable element (usually the one with overflow-y)
let scroller = null;
const allElements = document.querySelectorAll('*');
for (let el of allElements) {
    const style = getComputedStyle(el);
    if ((style.overflowY === 'scroll' || style.overflowY === 'auto') && el.scrollHeight > el.clientHeight + 100) {
        if (!scroller || el.scrollHeight > scroller.scrollHeight) {
            scroller = el;
        }
    }
}
if (!scroller) scroller = document.documentElement;

console.log("Found scroll container:", scroller.className || scroller.tagName);
console.log("Scroll height:", scroller.scrollHeight);

// Scroll to bottom incrementally to trigger lazy loading
const scrollStep = 1000;
const scrollDelay = 300; // ms between scrolls — increase if pages still missing
let currentScroll = 0;
const maxScroll = scroller.scrollHeight;

console.log("Scrolling through document to load all pages...");

while (currentScroll < maxScroll) {
    currentScroll += scrollStep;
    scroller.scrollTop = currentScroll;
    await new Promise(r => setTimeout(r, scrollDelay));
}

// Scroll back to top
scroller.scrollTop = 0;
await new Promise(r => setTimeout(r, 1000));

// Step 2: Wait a bit for final renders
console.log("Waiting for all images to finish rendering...");
await new Promise(r => setTimeout(r, 3000));

// Step 3: Collect all blob images
let images = Array.from(document.getElementsByTagName("img"))
    .filter(img => /^blob:/.test(img.src) && img.width > 100); // filter out tiny icons

console.log(`Found ${images.length} page images.`);

if (images.length === 0) {
    console.error("No blob images found. The viewer may use a different rendering method.");
    return;
}

// Sort images by their vertical position in the document
images.sort((a, b) => {
    const rectA = a.getBoundingClientRect();
    const rectB = b.getBoundingClientRect();
    // Use offsetTop of parent if available for more reliable ordering
    const topA = a.closest('[data-page-no]')?.dataset?.pageNo || a.offsetTop || rectA.top;
    const topB = b.closest('[data-page-no]')?.dataset?.pageNo || b.offsetTop || rectB.top;
    return Number(topA) - Number(topB);
});

// Step 4: Load jsPDF
let trustedURL;
if (window.trustedTypes && trustedTypes.createPolicy) {
    const policy = trustedTypes.createPolicy('myPolicy', {
        createScriptURL: (input) => input
    });
    trustedURL = policy.createScriptURL('https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.5.1/jspdf.umd.min.js');
} else {
    trustedURL = 'https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.5.1/jspdf.umd.min.js';
}

await new Promise((resolve, reject) => {
    let script = document.createElement("script");
    script.onload = resolve;
    script.onerror = reject;
    script.src = trustedURL;
    document.body.appendChild(script);
});

console.log("jsPDF loaded. Generating PDF...");

// Step 5: Generate PDF
const { jsPDF } = window.jspdf;
let pdf = null;

for (let i = 0; i < images.length; i++) {
    let img = images[i];
    let canvas = document.createElement('canvas');
    let ctx = canvas.getContext("2d");
    canvas.width = img.naturalWidth || img.width;
    canvas.height = img.naturalHeight || img.height;
    ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
    
    let imgData;
    try {
        imgData = canvas.toDataURL("image/jpeg", 0.92);
    } catch(e) {
        console.warn(`Skipping page ${i+1} due to CORS/tainted canvas`);
        continue;
    }
    
    const pageWidth = canvas.width;
    const pageHeight = canvas.height;
    
    if (i === 0) {
        pdf = new jsPDF({
            orientation: pageWidth > pageHeight ? 'landscape' : 'portrait',
            unit: 'px',
            format: [pageWidth, pageHeight]
        });
    } else {
        pdf.addPage([pageWidth, pageHeight], pageWidth > pageHeight ? 'landscape' : 'portrait');
    }
    
    pdf.addImage(imgData, 'JPEG', 0, 0, pageWidth, pageHeight);
    
    if ((i + 1) % 50 === 0) {
        console.log(`Processed ${i + 1} / ${images.length} pages...`);
    }
}

if (pdf) {
    pdf.save("download.pdf");
    console.log(`Done! Downloaded ${images.length} pages.`);
} else {
    console.error("No pages were captured.");
}

})();

// This script downloads PDF even though there are a huge number of files

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment