Copy script
Copied
Copy script
Copied
Professional Website Screenshot Capture with Playwright
A comprehensive script that captures professional-quality screenshots of any website using Playwright. Features include full page and viewport screenshots, automatic dependency handling, accessibility testing, comprehensive error handling with fallback URLs, detailed metadata generation, and organized file management in a shareable_assets folder. Perfect for documentation, web development, QA testing, and content creation. Works seamlessly in containerized environments like GitHub Codespaces.

Created by
andrew van beek - Keyboard Team
Requirements
Script
Copy script
Copied
Copy script
Copied
const axios = require('axios'); const { chromium } = require('playwright'); const fs = require('fs'); const path = require('path'); async function captureWebsiteScreenshot() { let browser; try { const websiteUrl = `{{websiteUrl}}`; const websiteName = `{{websiteName}}`; const viewportWidth = {{viewportWidth}}; const viewportHeight = {{viewportHeight}}; const waitTime = {{waitTime}} * 1000; // Convert to milliseconds const timeout = {{timeout}} * 1000; // Convert to milliseconds const includeFullPage = {{includeFullPage}}; const includeViewport = {{includeViewport}}; const fallbackUrl = `{{fallbackUrl}}`; console.log(`š Checking accessibility of ${websiteUrl}...`); // First check if the website responds try { const testResponse = await axios.get(websiteUrl, { timeout: 10000, headers: { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36' } }); console.log(`ā ${websiteUrl} is accessible! Status: ${testResponse.status}`); } catch (accessError) { console.log(`ā ļø ${websiteUrl} may not be accessible: ${accessError.message}`); console.log('š Will attempt screenshot anyway with fallback if needed...'); } console.log('š Starting Playwright screenshot process...'); // Create the shareable_assets directory const assetsDir = './shareable_assets'; if (!fs.existsSync(assetsDir)) { fs.mkdirSync(assetsDir, { recursive: true }); console.log('š Created shareable_assets directory'); } else { console.log('š shareable_assets directory already exists'); } // Launch browser with comprehensive flags for codespace compatibility browser = await chromium.launch({ headless: true, args: [ '--no-sandbox', '--disable-setuid-sandbox', '--disable-dev-shm-usage', '--disable-accelerated-2d-canvas', '--no-first-run', '--no-zygote', '--disable-gpu', '--disable-background-timer-throttling', '--disable-backgrounding-occluded-windows', '--disable-renderer-backgrounding', '--disable-features=TranslateUI', '--disable-ipc-flooding-protection' ] }); console.log('š Playwright browser launched successfully'); // Create a new page const page = await browser.newPage(); // Set viewport size await page.setViewportSize({ width: viewportWidth, height: viewportHeight }); console.log(`š Viewport set to ${viewportWidth}x${viewportHeight}px`); // Try primary URL first, fallback if it fails const websites = [ { url: websiteUrl, name: websiteName }, { url: fallbackUrl, name: `${websiteName}-fallback` } ]; let successfulScreenshot = false; for (const site of websites) { try { console.log(`š Navigating to: ${site.url}`); await page.goto(site.url, { waitUntil: 'domcontentloaded', timeout: timeout }); console.log(`ā Page loaded successfully: ${site.url}`); // Wait for dynamic content if (waitTime > 0) { console.log(`ā³ Waiting ${waitTime/1000} seconds for dynamic content...`); await page.waitForTimeout(waitTime); } // Get page information const pageTitle = await page.title(); const currentUrl = page.url(); console.log(`š Page title: "${pageTitle}"`); console.log(`š Current URL: ${currentUrl}`); // Generate timestamp for unique filenames const timestamp = new Date().toISOString().replace(/[:.]/g, '-'); const screenshotFiles = []; // Take full page screenshot if requested if (includeFullPage) { const fullPageFilename = `${site.name}-screenshot-${timestamp}.png`; const fullPageFilepath = path.join(assetsDir, fullPageFilename); await page.screenshot({ path: fullPageFilepath, fullPage: true, type: 'png' }); console.log(`šø Full page screenshot saved: ${fullPageFilename}`); screenshotFiles.push({ type: 'fullPage', filename: fullPageFilename, filepath: fullPageFilepath }); } // Take viewport screenshot if requested if (includeViewport) { const viewportFilename = `${site.name}-viewport-${timestamp}.png`; const viewportFilepath = path.join(assetsDir, viewportFilename); await page.screenshot({ path: viewportFilepath, fullPage: false, type: 'png' }); console.log(`šø Viewport screenshot saved: ${viewportFilename}`); screenshotFiles.push({ type: 'viewport', filename: viewportFilename, filepath: viewportFilepath }); } // Verify files and collect stats const fileStats = {}; let allFilesExist = true; for (const file of screenshotFiles) { if (fs.existsSync(file.filepath)) { const stats = fs.statSync(file.filepath); fileStats[file.type] = { filename: file.filename, size: `${(stats.size / 1024).toFixed(2)} KB`, created: stats.birthtime.toLocaleString() }; console.log(`ā ${file.type} verified: ${(stats.size / 1024).toFixed(2)} KB`); } else { console.log(`ā ${file.type} file not found: ${file.filepath}`); allFilesExist = false; } } if (allFilesExist) { // Get page dimensions const pageSize = await page.evaluate(() => { return { width: document.documentElement.scrollWidth, height: document.documentElement.scrollHeight, viewportWidth: window.innerWidth, viewportHeight: window.innerHeight }; }); console.log(`š Page dimensions: ${pageSize.width}x${pageSize.height}px`); // Create comprehensive metadata const metadata = { captureInfo: { url: site.url, currentUrl: currentUrl, capturedAt: new Date().toISOString(), pageTitle: pageTitle, pageDimensions: pageSize }, settings: { viewportWidth: viewportWidth, viewportHeight: viewportHeight, waitTime: waitTime/1000, timeout: timeout/1000, includeFullPage: includeFullPage, includeViewport: includeViewport }, files: fileStats }; const metadataFilename = `${site.name}-metadata-${timestamp}.json`; const metadataFilepath = path.join(assetsDir, metadataFilename); fs.writeFileSync(metadataFilepath, JSON.stringify(metadata, null, 2), 'utf8'); console.log(`š Metadata saved: ${metadataFilename}`); successfulScreenshot = true; break; // Success - exit loop } } catch (siteError) { console.log(`ā Failed to screenshot ${site.url}: ${siteError.message}`); if (site.url === websiteUrl && fallbackUrl) { console.log('š Trying fallback URL...'); continue; } else { throw siteError; } } } if (successfulScreenshot) { // List all files in shareable_assets directory const files = fs.readdirSync(assetsDir); console.log(`\nš shareable_assets directory (${files.length} files):`); files.forEach(file => { const filePath = path.join(assetsDir, file); const fileStats = fs.statSync(filePath); console.log(` š ${file} - ${(fileStats.size / 1024).toFixed(2)} KB`); }); console.log(`\nš Screenshot capture completed successfully!`); console.log(`š Files saved to: ${path.resolve(assetsDir)}`); } else { console.log('ā All screenshot attempts failed'); } } catch (error) { console.error(`ā Error during screenshot process: ${error.message}`); if (error.message.includes('Navigation timeout')) { console.log('š” Try increasing the timeout value or check if the website is accessible'); } else if (error.message.includes('net::ERR_NAME_NOT_RESOLVED')) { console.log('š” Check if the URL is correct and the website exists'); } else if (error.message.includes('browserType.launch')) { console.log('š” Browser dependencies may be missing - ensure Playwright is properly installed'); } } finally { if (browser) { await browser.close(); console.log('š Browser closed'); } } } // Execute the screenshot function captureWebsiteScreenshot();