Deploying URL-to-PNG
Introduction
URL-to-PNG is a simple, self-hosted service that generates screenshots of websites. Using a headless browser, it captures any webpage and returns it as a PNG image, making it perfect for generating thumbnails, preview images, and visual snapshots of web content.
Built with Node.js and Puppeteer, URL-to-PNG provides a clean REST API that accepts a URL and returns a screenshot. No complex configuration needed - just send a request with the URL you want to capture and receive an image in response.
Key highlights of URL-to-PNG:
- Simple API: Single endpoint that accepts URL and returns image
- Puppeteer Powered: Full Chrome rendering for accurate screenshots
- Customizable Output: Control viewport size, image dimensions, and format
- Fast Response: Optimized for quick screenshot generation
- Self-Hosted: Full control over your screenshot infrastructure
- Privacy Focused: URLs never sent to third-party services
- Caching Support: Optional caching for repeated requests
- Open Source: MIT licensed for full transparency
This guide walks through deploying URL-to-PNG on Klutch.sh using Docker, configuring the service, and integrating it with your applications.
Why Deploy URL-to-PNG on Klutch.sh
Deploying URL-to-PNG on Klutch.sh provides several advantages for screenshot generation:
Simplified Deployment: Klutch.sh automatically detects your Dockerfile and builds URL-to-PNG without complex configuration. Push to GitHub, and your screenshot service deploys automatically.
Persistent Storage: Attach persistent volumes for caching screenshots and reducing repeated rendering.
HTTPS by Default: Klutch.sh provides automatic SSL certificates, ensuring secure API access.
Scalable Resources: Allocate CPU and memory based on your screenshot volume. Headless Chrome benefits from adequate resources.
Always-On Service: Your screenshot API remains accessible 24/7 for your applications.
Prerequisites
Before deploying URL-to-PNG on Klutch.sh, ensure you have:
- A Klutch.sh account
- A GitHub account with a repository for your URL-to-PNG configuration
- Basic familiarity with Docker and REST APIs
- Applications that need screenshot functionality
- (Optional) A custom domain for your screenshot service
Understanding URL-to-PNG Architecture
URL-to-PNG is built on a straightforward stack:
Node.js Server: Express-based API server handling requests.
Puppeteer: Headless Chrome automation for rendering pages.
Chromium: The browser engine that renders web pages.
Sharp (optional): Image processing for optimization.
Preparing Your Repository
To deploy URL-to-PNG on Klutch.sh, create a GitHub repository containing your Dockerfile.
Repository Structure
url-to-png-deploy/├── Dockerfile└── .dockerignoreCreating the Dockerfile
Create a Dockerfile in the root of your repository:
FROM node:18-slim
# Install Chromium dependenciesRUN apt-get update && apt-get install -y \ chromium \ fonts-ipafont-gothic \ fonts-wqy-zenhei \ fonts-thai-tlwg \ fonts-kacst \ fonts-symbola \ fonts-noto \ fonts-freefont-ttf \ --no-install-recommends \ && rm -rf /var/lib/apt/lists/*
# Set Puppeteer to use installed ChromiumENV PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=trueENV PUPPETEER_EXECUTABLE_PATH=/usr/bin/chromium
# Create app directoryWORKDIR /app
# Install URL-to-PNGRUN npm init -y && npm install url-to-png
# Set environment variablesENV PORT=3000ENV API_KEY=${API_KEY}
# Create cache directoryRUN mkdir -p /app/cache
# Expose portEXPOSE 3000
# Health checkHEALTHCHECK --interval=30s --timeout=10s --start-period=30s --retries=3 \ CMD curl -f http://localhost:3000/health || exit 1
CMD ["node", "node_modules/url-to-png/index.js"]Custom Server Configuration
For more control, create a custom server.js:
const express = require('express');const puppeteer = require('puppeteer');
const app = express();const PORT = process.env.PORT || 3000;const API_KEY = process.env.API_KEY;
// API key middlewareapp.use((req, res, next) => { if (API_KEY && req.query.api_key !== API_KEY) { return res.status(401).json({ error: 'Unauthorized' }); } next();});
// Screenshot endpointapp.get('/screenshot', async (req, res) => { const { url, width = 1280, height = 800, fullPage = false } = req.query;
if (!url) { return res.status(400).json({ error: 'URL parameter required' }); }
try { const browser = await puppeteer.launch({ headless: 'new', args: ['--no-sandbox', '--disable-setuid-sandbox'] });
const page = await browser.newPage(); await page.setViewport({ width: parseInt(width), height: parseInt(height) }); await page.goto(url, { waitUntil: 'networkidle0' });
const screenshot = await page.screenshot({ type: 'png', fullPage: fullPage === 'true' });
await browser.close();
res.type('image/png').send(screenshot); } catch (error) { res.status(500).json({ error: error.message }); }});
// Health checkapp.get('/health', (req, res) => { res.json({ status: 'ok' });});
app.listen(PORT, () => { console.log(`Server running on port ${PORT}`);});Environment Variables Reference
| Variable | Required | Default | Description |
|---|---|---|---|
PORT | No | 3000 | Port for the API server |
API_KEY | No | - | Optional API key for authentication |
CACHE_DIR | No | /app/cache | Directory for cached screenshots |
CACHE_TTL | No | 3600 | Cache time-to-live in seconds |
Deploying URL-to-PNG on Klutch.sh
Once your repository is prepared, follow these steps to deploy URL-to-PNG:
- Select HTTP as the traffic type
- Set the internal port to 3000 (API server port)
- Detect your Dockerfile automatically
- Build the container image
- Attach the persistent volumes
- Start the URL-to-PNG container
- Provision an HTTPS certificate
Push Your Repository to GitHub
Initialize your repository and push to GitHub:
git initgit add Dockerfile .dockerignoregit commit -m "Initial URL-to-PNG deployment configuration"git remote add origin https://github.com/yourusername/url-to-png-deploy.gitgit push -u origin mainCreate a New Project on Klutch.sh
Navigate to the Klutch.sh dashboard and create a new project. Give it a descriptive name like “url-to-png” or “screenshot-api”.
Create a New App
Within your project, create a new app. Connect your GitHub account if you haven’t already, then select the repository containing your URL-to-PNG Dockerfile.
Configure HTTP Traffic
In the deployment settings:
Set Environment Variables
In the environment variables section, add the following:
| Variable | Value |
|---|---|
API_KEY | A secure API key (optional but recommended) |
CACHE_TTL | 3600 (1 hour cache) |
Attach Persistent Volumes
Add persistent storage for caching:
| Mount Path | Recommended Size | Purpose |
|---|---|---|
/app/cache | 5 GB | Cached screenshots |
Deploy Your Application
Click Deploy to start the build process. Klutch.sh will:
Access URL-to-PNG
Once deployment completes, access your URL-to-PNG instance at https://your-app-name.klutch.sh/health to verify it’s running.
Using the API
Basic Screenshot
Generate a simple screenshot:
GET https://your-app.klutch.sh/screenshot?url=https://example.comCustom Dimensions
Specify viewport size:
GET https://your-app.klutch.sh/screenshot?url=https://example.com&width=1920&height=1080Full Page Screenshot
Capture the entire page:
GET https://your-app.klutch.sh/screenshot?url=https://example.com&fullPage=trueWith Authentication
If API key is configured:
GET https://your-app.klutch.sh/screenshot?url=https://example.com&api_key=YOUR_KEYIntegration Examples
HTML Image Tag
Embed screenshots directly in HTML:
<img src="https://your-app.klutch.sh/screenshot?url=https://example.com&width=400&height=300" alt="Example.com Preview">JavaScript Fetch
Fetch screenshot programmatically:
const response = await fetch( `https://your-app.klutch.sh/screenshot?url=${encodeURIComponent(url)}&api_key=${apiKey}`);const blob = await response.blob();const imageUrl = URL.createObjectURL(blob);Python Integration
import requests
response = requests.get( 'https://your-app.klutch.sh/screenshot', params={'url': 'https://example.com', 'api_key': 'YOUR_KEY'})
with open('screenshot.png', 'wb') as f: f.write(response.content)Advanced Configuration
Caching
Implement caching to improve performance:
const crypto = require('crypto');const fs = require('fs');const path = require('path');
function getCacheKey(url, width, height) { return crypto.createHash('md5') .update(`${url}-${width}-${height}`) .digest('hex');}
function getCachedScreenshot(key) { const cachePath = path.join('/app/cache', `${key}.png`); if (fs.existsSync(cachePath)) { const stats = fs.statSync(cachePath); const age = (Date.now() - stats.mtimeMs) / 1000; if (age < parseInt(process.env.CACHE_TTL || 3600)) { return fs.readFileSync(cachePath); } } return null;}Wait Options
Control page loading behavior:
waitUntil: 'load'- Wait for load eventwaitUntil: 'domcontentloaded'- Wait for DOM readywaitUntil: 'networkidle0'- Wait for network quietwaitUntil: 'networkidle2'- Wait for 2 or fewer connections
Custom User Agent
Set a custom user agent:
await page.setUserAgent('URL-to-PNG Screenshot Service');Production Best Practices
Security
- API Key Protection: Always use API keys in production
- Rate Limiting: Implement rate limiting to prevent abuse
- URL Validation: Validate and sanitize input URLs
- Private Network Access: Consider blocking internal/private URLs
Performance
- Resource Allocation: Chromium needs adequate memory (2GB+ recommended)
- Caching: Cache screenshots to reduce repeated rendering
- Connection Pooling: Reuse browser instances for better performance
Monitoring
- Track request latency
- Monitor memory usage
- Alert on error rates
- Log failed URLs for debugging
Troubleshooting Common Issues
Screenshots Failing
Symptoms: API returns errors or blank images.
Solutions:
- Verify URL is accessible
- Check for JavaScript errors on target page
- Increase timeout settings
- Verify Chromium has enough memory
Slow Performance
Symptoms: Screenshots take too long to generate.
Solutions:
- Enable caching
- Increase server resources
- Reduce viewport size
- Use faster waitUntil options
Memory Issues
Symptoms: Container crashes or restarts.
Solutions:
- Increase memory allocation
- Close browser instances properly
- Limit concurrent screenshots
- Monitor memory usage
Additional Resources
- URL-to-PNG GitHub Repository
- Puppeteer Documentation
- Chrome for Testing
- Klutch.sh Persistent Volumes
- Klutch.sh Deployments
Conclusion
Deploying URL-to-PNG on Klutch.sh gives you a reliable, self-hosted screenshot service accessible from anywhere. The combination of URL-to-PNG’s simple API and Klutch.sh’s deployment automation means you can generate website previews without relying on third-party services.
With customizable output, caching support, and full control over your infrastructure, URL-to-PNG provides everything you need for programmatic screenshot generation. Your URLs and images remain private, processed on your own secure infrastructure.