To convert HTML to an image in Express, render the markup in a headless browser such as Puppeteer, then return the screenshot bytes from an Express route. Use page.setContent() for an HTML string, page.goto() for an existing URL, set the viewport, wait for required resources, and call page.screenshot(). Puppeteer returns a binary Uint8Array by default, which Express can send directly with an image content type.
What the Express endpoint actually does
Express supplies the HTTP method, URL, request parsing, and response. It does not render HTML. Puppeteer starts or connects to Chromium, builds a page, executes HTML/CSS/JavaScript, and captures the rendered result. The basic flow is:
- Accept HTML or a URL in an HTTP request.
- Launch a browser and create a page.
- Choose viewport dimensions and, if needed, device scale.
- Load the document with
setContent()orgoto(). - Wait until the content needed for the image is ready.
- Capture a viewport, full page, or clipped region.
- Send the returned bytes with
image/png,image/jpeg, orimage/webp.
The example below accepts raw HTML, captures a PNG, and closes the browser even when rendering fails.
Build a working Express and Puppeteer route
1. Install the packages
npm install express puppeteer
This example uses ECMAScript modules. Add "type": "module" to package.json, or convert the imports to the module system used by your project.
#1 Best Overall
- 2x3" Portable Photo Printer: The upgraded PP01 photo printer uses advanced inkjet technology. This portable photo printer produces vivid, full-color prints on premium sticky-backed photo paper that is smudge-proof, water-resistant, and tear-resistant. The Nelko mini photo printer is pocket-sized and weighs only 308g, making it ultra-portable for school, travel, and field trips. Each ink cartridge prints up to 80 full-color 2x3 photos on sticky-backed paper
- Easy Printing via Bluetooth: The PP01 mini photo printer is compatible with iOS and Android phones via Bluetooth. Simply download the Nelko app from Google Play or the App Store. Load the 2x3 photo paper with the smooth side facing down. Install the ink cartridge, connect via Bluetooth, and print directly using the Nelko app. A USB charging cable is included; the adapter is not included
- High Photo Quality: This mini photo printer uses advanced inkjet technology for clear, vibrant prints. This portable photo printer produces 600 DPI high-resolution images with precise colors, capturing fine details and realistic tones. Each photo comes with adhesive backing, perfect for scrapbooks and preserving your memories. Personalize every photo for holidays, birthdays, or daily events
- Powerful App: The Nelko 2x3" PP01 photo printer app lets you edit photos and offers a variety of frame designs, making it perfect for personalizing your photos for projects like scrapbooking or journaling. Download the Nelko app to create collages and customize photos with filters, graffiti, borders, stickers, text, AI image editing, and many other features. Edit photos on your phone, then send them to the Nelko app for instant printing in under 90 seconds
- Versatile Usage Scenarios: This portable photo printer is ideal for travel journals, party favors, and family gatherings. Students use it for planners and photo printing. Crafters use it for DIY projects, custom labels, and scrapbooking. It's a practical tool for bloggers, small businesses, and event photographers to create instant giveaways. Perfect for Mother's Day surprises and heartfelt moments with loved ones using Nelko sticky-backed photo paper.
2. Create the server
import express from 'express';
import puppeteer from 'puppeteer';
const app = express();
// The client sends an HTML document as text/html.
// Keep a finite limit so an accidental or hostile request cannot be unbounded.
app.use(express.text({ type: 'text/html', limit: '1mb' }));
app.post('/image', async (req, res, next) => {
let browser;
try {
if (typeof req.body !== 'string' || req.body.trim() === '') {
return res.status(400).json({ error: 'Send an HTML document with Content-Type: text/html.' });
}
browser = await puppeteer.launch();
const page = await browser.newPage();
await page.setViewport({ width: 1200, height: 800 });
await page.setContent(req.body);
const image = await page.screenshot({
type: 'png',
fullPage: true
});
res.type('png').send(image);
} catch (error) {
next(error);
} finally {
await browser?.close();
}
});
app.use((error, req, res, next) => {
console.error(error);
if (res.headersSent) return next(error);
res.status(500).json({ error: 'Unable to render the HTML.' });
});
app.listen(3000, () => {
console.log('HTML image service listening on http://localhost:3000');
});
3. Call the endpoint
curl -X POST http://localhost:3000/image
-H 'Content-Type: text/html'
--data '<!doctype html><html><body><h1>Invoice</h1><p>Ready</p></body></html>'
-o invoice.png
The response is a PNG file. If you want the browser to show it inline, keep the image content type; if you want a download, add a suitable Content-Disposition header.
HTML strings versus existing URLs
Render an HTML string with setContent()
page.setContent(html) is appropriate when the request contains the complete document or when your server generates a template first. Include styles in the document or use a CSS framework that the browser can load. Relative URLs need a meaningful base URL; otherwise images, stylesheets, and fonts may not resolve as expected.
Render a URL with goto()
app.post('/image-from-url', express.json(), async (req, res, next) => {
let browser;
try {
if (typeof req.body?.url !== 'string') {
return res.status(400).json({ error: 'url is required' });
}
browser = await puppeteer.launch();
const page = await browser.newPage();
await page.setViewport({ width: 1200, height: 800 });
await page.goto(req.body.url, { waitUntil: 'networkidle0' });
const image = await page.screenshot({ type: 'png', fullPage: true });
res.type('png').send(image);
} catch (error) {
next(error);
} finally {
await browser?.close();
}
});
Only accept URLs you are authorized to fetch. In a public service, validate schemes and destinations and block access to private network ranges to reduce server-side request risks.
Choose the image scope and format
| Need | Puppeteer choice | Result |
|---|---|---|
| Visible browser rectangle | Omit fullPage or set it to false |
The current viewport only |
| Entire document | fullPage: true |
A screenshot extending beyond the viewport |
| One component | Measure an element and pass a clip, or use an element screenshot |
Only the selected region |
| Lossless image | type: 'png' |
PNG bytes; quality does not change PNG output |
| Smaller photographic image | type: 'jpeg', quality: 80 |
JPEG bytes with a quality setting |
| WebP output | type: 'webp', quality: 80 |
WebP bytes where supported by the installed browser |
| Transparent background | omitBackground: true |
Transparency instead of the default page background; choose a format and consumer that preserve it |
Set dimensions before loading the document:
await page.setViewport({ width: 1440, height: 900, deviceScaleFactor: 2 });
A viewport change can reload a page in some circumstances, so set it before navigation or content injection. A device scale factor increases pixel density and output dimensions; verify the resulting file size and downstream limits.
Capture a specific element
const card = await page.$('.receipt-card');
if (!card) throw new Error('receipt-card was not found');
const image = await card.screenshot({ type: 'png' });
For a manually calculated region, use page.screenshot({ clip: { x, y, width, height } }). Coordinates are in CSS pixels relative to the page viewport.
Rank #2
- User-Friendly Portable Photo Printer for iPhone, Android & PC - Get beautiful and colourful memories with Liene 4x6 photo printer! After opening the entire package, you can find one cartridge + 20 sheets of photo paper (placed inside the machine packaging), as well as an additional box containing 80 sheets of photo paper (which includes two cartridges + 80 sheets of photo paper). Full package includes smartphone photo printer, Liene 4x6 photo printer papers (100 sheets), 3 colour cartridges, and fully sealed cassette to prevent dust. Minimalist and magnetic design for compact storage.
- Superior Quality 4x6 Photo Printer - Print photos like no other thanks to the thermal-dye sublimation tech adopted by the picture printer for iphone. The dyes deeply penetrate the paper for vibrant photo printing, and the laminated surface is resistant to water, scratches, fingerprints and fading. Clean the print head promptly if smudges are observed on printed photos during operation. Get Liene photo printers now for yourself and your loved ones, print your happy moments together and keep your love forever!
- Wi-Fi Photo Printer for Smartphone - The built-in hotspot of the photo printer makes it easy to print pictures from your phone, avoiding outside interference with a fast and stable connection. No other networks required! Simply connect your device to the independent instant photo printer 4x6 hotspot.
- Multiple Device Compatibility - Liene phone printer provides instant photo printing for up to 5 simultaneous connections. Share with family and friends or print from your different devices. No additional cables or Bluetooth required when printing photos with this picture printer. Note: Ensure the ink cartridge clicks into place before printing.
- Customize your Printing with the Liene App - Customize your photos with our specialized App! You can add a Square border, insert filters, enhance the contrast and brightness, check printing status, and more. You can even print your ID and Visa photos from home with this photo printer for iphone 4x6 prints.
Wait for fonts, images, and client-side rendering
setContent() can resolve before web fonts, remote images, or application JavaScript has finished changing the DOM. Add a readiness condition that matches your page instead of relying on an arbitrary delay.
await page.setContent(html, { waitUntil: 'networkidle0' });
await page.evaluate(() => document.fonts?.ready);
await page.waitForSelector('#chart[data-ready="true"]', { timeout: 10000 });
For an application that sets a flag after data and images are complete, wait for that flag. A fixed delay can be useful for a known animation, but it is less deterministic than a selector or application-controlled signal. If you capture a URL, goto() supports navigation wait conditions; select one that reflects the page’s actual loading behavior.
Security and request controls
HTML-to-image endpoints execute markup in a browser. Treat submitted HTML and URLs as untrusted:
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
- Limit request size, navigation time, and the maximum output dimensions.
- Authenticate the route if it is not intended for anonymous users.
- For URL capture, allow only
httpandhttps, validate redirects, and deny internal or metadata addresses. - Decide whether scripts, external requests, cookies, and authorization headers are allowed for your use case.
- Do not expose browser debugging ports publicly.
- Log request identifiers and rendering errors without logging secrets embedded in HTML or URLs.
The cited documentation does not establish a universal safe launch flag set or resource limit for every hosting provider. Test Chromium launch options, sandbox requirements, memory ceilings, and concurrency in the environment where this service will run.
Browser lifecycle, performance, and reliability
The sample launches and closes Chromium per request because that makes ownership and cleanup obvious. For sustained traffic, measure your deployment before changing this design. Reusing a browser process and creating isolated pages can reduce startup work, but it also requires limits for concurrent pages, crashed browsers, stuck navigations, and cleanup. A queue is often easier to control than unlimited parallel launches.
Rank #3
- Dock Photo Printer: The KODAK Dock Plus is a home photo printer that produces high-quality 4x6” prints directly from compatible smartphones. Featuring an integrated docking station, users can place their phone on the printer for better connection while simultaneously charging the device during printing.
- Genuine 4PASS dye sublimation printing: Each photo is produced in three color layers and finished with a clear protective lamination layer. In approximately 55 seconds, you receive a smooth, detailed print designed to resist fingerprints, water, and fading for long-lasting quality.
- Easy to Use: Print photos quickly without complicated setup or technical steps. Simply power on, connect wireless bluetooth, and start printing within seconds. The Dock Plus is built for straightforward operation, making it ideal for first time users and everyday photo printing.
- Home Printing Station: Designed for stable desktop use, this dock photo printer connects to a power outlet for consistent performance and larger 4x6” prints. Ideal for home printing, photo albums, framing, family events, and everyday picture printing.
- KODAK Photo Printer APP: Featuring integrated Bluetooth connectivity, this portable printer connects to compatible iOS and Android devices through the KODAK Photo Printer app. Edit, crop, and customize your photos before printing for creative results.
- Set explicit navigation and selector timeouts so one page cannot hold a request forever.
- Close pages in a
finallyblock when you reuse a browser. - Return a clear 4xx response for invalid input and a 5xx response for rendering failures.
- Keep image responses binary; do not convert a
Uint8Arrayto a UTF-8 string. - Cache deterministic renders when the HTML, viewport, fonts, and assets are unchanged.
Puppeteer documents PNG as the default screenshot type and returns a Uint8Array unless a base64 encoding is requested. Base64 is useful for a JSON API, but it increases payload size and adds an encoding step; sending bytes is the simpler image endpoint.
Puppeteer or Playwright?
Both libraries document Node/browser screenshot workflows. Choose based on the browser engines, APIs, and deployment model your application needs rather than assuming one is universally faster or easier. The actionable comparison is capture scope and output support: both document viewport, element, and full-page screenshots, and both can produce PNG or JPEG; Playwright also documents WebP choices in its screenshot tooling. Neither the cited documentation nor this example establishes comparative speed, memory use, maintenance burden, or operational superiority for your particular Express service.
Free tools Windows power users keep installed
One-click scans. No signup required.
PDF is a different output
Do not substitute page.pdf() when the requirement is an image. PDF generation follows print-oriented behavior by default. If you intentionally need a PDF that uses screen media, call page.emulateMediaType('screen') before page.pdf(), then return a PDF content type. Convert to an image in a separate, explicit pipeline if that is your actual deliverable.
Common errors and fixes
“Cannot find module puppeteer”
Install the dependency in the same project and environment that starts Express: npm install puppeteer. Confirm that your deployment installs production dependencies and that the import style matches your module configuration.
Chromium will not launch
Check the host’s sandbox and shared-memory restrictions, available disk space, and the browser executable downloaded by your Puppeteer version. The correct launch arguments are hosting-specific; test them in the target container or VM rather than copying a blanket flag set.
Rank #4
- Instant Photo Printing: The KODAK Mini 2 Retro is a portable photo printer designed to turn smartphone pictures into high quality prints in seconds. Whether capturing family moments, travel highlights, journaling pages, or creative projects, this mini printer lets you print real photos anytime, anywhere.
- Genuine 4PASS dye sublimation printing: Each photo is produced in three color layers and finished with a clear protective lamination layer. In approximately 55 seconds, you receive a smooth, detailed print designed to resist fingerprints, water, and fading for long-lasting quality.
- Easy to Use: Print photos quickly without complicated setup or technical steps. Simply power on, connect wireless bluetooth, and start printing within seconds. The Mini 2 Retro is built for straightforward operation, making it ideal for first time users and everyday photo printing.
- Print Anytime, Anywhere: Small enough to fit in your hand, bag, or even a pocket, the Mini 2 Retro is built for on-the-go printing. Ideal for parties, trips, school projects, scrapbooks, and spontaneous moments where you want real prints without waiting.
- KODAK Photo Printer APP: Featuring integrated Bluetooth connectivity, this portable printer connects to compatible iOS and Android devices through the KODAK Photo Printer app. Edit, crop, and customize your photos before printing for creative results.
The image is blank or missing styles
Check relative asset URLs, external request failures, CSP rules, and whether the screenshot occurs before client-side rendering completes. Use absolute asset URLs or a valid document base, wait for a readiness selector, and inspect console and network errors during debugging.
Fonts or images are clipped
Set the final viewport before loading, wait for fonts and images, and choose fullPage or an element clip deliberately. Very large pages may exceed platform response or memory limits; constrain the input or split the capture.
“Cannot send headers after they are sent”
Return immediately after validation failures and keep one response path. Pass unexpected errors to the Express error middleware, as in the example.
Requests never finish
Use explicit navigation and selector timeouts, investigate third-party requests, and abort or reject pages that exceed your policy. Do not let a browser wait indefinitely for an analytics or advertising host.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Or skip the browser setup
ScreenshotNeo provides a hosted website screenshot API, so your Express application can request an image without managing Chromium. It accepts HTML-capable capture options and URL screenshots through one GET request. Cookie and consent banners, newsletter popups, and chat widgets are removed before the shot; bot checks, blank pages, timeouts, failed loads, and cache hits are not billed, and response headers identify the page verdict and billing result. It also offers an MCP server with take_screenshot, get_page_info, and capture_pdf tools for Claude, Cursor, and other MCP clients.
See the ScreenshotNeo API documentation for the current parameters. This cURL request saves a WebP screenshot:
Best Value
- STEP UP YOUR PRINTING GAME. KODAK Step Printer Connects to Any iOS or Android Device [Via Bluetooth or NFC] Turn Your Selfies, Portraits, Social Media Posts Into Physical Photos.Package Includes : KODAK STEP Instant Mobile Photo Printer, Micro USB Charging Cable, Starter Pack of KODAK ZINK Photo Paper, Quick Start Guide, Limited Warranty
- AMAZING ZERO-INK TECHNOLOGY. ZINK 2” x 3” Sticky-Back Paper with Embedded Dye Crystals Delivers High-Quality, Durable, Affordable, Beautifully Detailed Prints That are Resistant to Moisture, Rips, Tears & Smudges.
- FULL EDITING SUITE VIA APP. Download the KODAK App to Create Collages & Customize Your Snaps with Stunning Filters, Interesting Borders, Cool Stickers, Funny Text & Other Personalized Flair.
- TAKE YOUR PROJECTS TO GO. Our Palm-Sized Printer Weighs Less Than a Pound, Sets Up Fast & Delivers Gorgeous Prints You Can Peel & Stick Everywhere.
- CUTE, COMPACT & COLORFUL. Step Printer is Designed for Photo-Loving Influencers & Crafters of All Ages & Skill Levels! Portable, Lightweight Device Features Built-In Lithium-Ion Rechargeable Battery [Prints 25 Photo on a Full Charge]
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
Python:
import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
r.raise_for_status()
open("shot.webp", "wb").write(r.content)
Node.js:
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
if (!res.ok) throw new Error(`Screenshot failed: ${res.status}`);
const image = Buffer.from(await res.arrayBuffer());
await import('node:fs/promises').then(fs => fs.writeFile('shot.webp', image));
The free plan includes 1,000 screenshots per month with no card. Paid plans start at $5 for 3,000 shots; every feature is available on every plan, and yearly billing gives two months free. Create a free ScreenshotNeo account.
FAQ
Can Express return the screenshot without writing a temporary file?
Yes. Puppeteer’s default screenshot result is binary bytes, so send it directly with res.type('png').send(image). Use a file only when you need later processing or archival.
How do I make a screenshot of a dynamic chart?
Have the page signal completion with a selector or data attribute, wait for it with page.waitForSelector(), and then capture the element or full page.
Do these 3 things before closing this tab:
1Repair Windows errors before they cause bigger problems2Scan for outdated or missing drivers - takes under a minute3Clear out junk files and repair common Windows errorsCan I use this route to fetch any public URL?
Technically, page.goto() can navigate to a URL, but a public fetch endpoint needs authentication, destination allow-listing, redirect checks, and limits to prevent abuse and internal-network access.
Frequently Asked Questions
Can Express return the screenshot without writing a temporary file?
Yes. Puppeteer’s default screenshot result is binary bytes, so send it directly with res.type(‘png’).send(image).
How do I make a screenshot of a dynamic chart?
Have the page signal completion with a selector or data attribute, wait for it with page.waitForSelector(), and then capture the element or full page.
Can I use this route to fetch any public URL?
Technically, page.goto() can navigate to a URL, but a public fetch endpoint needs authentication, destination allow-listing, redirect checks, and limits to prevent abuse and internal-network access.
Quick wins for a faster PC:
Scan for outdated or missing drivers - takes under a minuteDriver Scan →Clear out junk files and repair common Windows errorsFree Scan →Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

