/

Professional Website Screenshot Capture with Playwright

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

playwright.dev logo

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();