-
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Executing within Puppeteer (headless browser)
Gildas edited this page Nov 14, 2025
·
2 revisions
Minimum working example (see https://github.com/gildas-lormeau/single-file-cli/discussions/181#discussioncomment-14970620)
import puppeteer from "puppeteer";
import fs from "fs/promises";
import {
script as SINGLEFILE_SCRIPT,
hookScript as SINGLEFILE_HOOK,
zipScript as SINGLEFILE_ZIP
} from "single-file-cli/lib/single-file-bundle.js";
async function capture(url) {
const browser = await puppeteer.launch({
headless: true,
args: [
"--disable-web-security",
"--allow-running-insecure-content",
"--no-sandbox"
]
});
const page = await browser.newPage();
await page.evaluateOnNewDocument(SINGLEFILE_HOOK);
await page.evaluateOnNewDocument(`
${SINGLEFILE_SCRIPT}
window.singlefile = singlefile;
`);
await page.goto(url, { waitUntil: "networkidle2", timeout: 60000 });
await page.evaluate(async () => {
await new Promise(resolve => {
let totalScrolled = 0;
const step = 400;
const timer = setInterval(() => {
window.scrollBy(0, step);
totalScrolled += step;
if (totalScrolled >= document.body.scrollHeight - window.innerHeight) {
clearInterval(timer);
resolve();
}
}, 150);
});
});
const title = await page.evaluate(() =>
(
document.querySelector("meta[property='og:title']")?.content ||
document.title ||
"saved_page"
).trim()
);
const filename = title.replace(/[^a-z0-9\-_]+/gi, "_") + ".html";
const result = await page.evaluate(
async zip => {
return await window.singlefile.getPageData({
compressContent: false,
blockScripts: false,
blockImages: false,
blockVideos: false,
zipScript: zip
});
},
SINGLEFILE_ZIP
);
await fs.writeFile(filename, result.content);
await browser.close();
console.log("Saved:", filename);
}
const url = process.argv[2];
if (!url) {
console.error("Usage: node src/capture.js <url>");
process.exit(1);
}
capture(url).catch(error => {
console.error("Error:", error.message);
});