Turn an HTML file or web page into a PNG or JPEG using Playwright’s browser automation. This guide covers installing the dependencies on Alpine Linux, capturing a screenshot, and fixing common problems such as missing browser libraries or fonts. You’ll need Node.js and npm, a working Alpine environment, and permission to install packages.
What You’ll Need
- An Alpine Linux system or container with access to its package repositories.
- Node.js and npm, installed with Alpine’s package manager if they are not already available.
- A directory for your project, the HTML you want to render, and enough disk space for Chromium and its dependencies.
- Network access during installation if Playwright needs to download its browser.
Step-by-Step
- Install Node.js and npm. On a current Alpine release, run
apk add --no-cache nodejs npmas root, or prefix the command withdoasorsudoif configured. Confirm the tools are available withnode --versionandnpm --version. If you use a container, run these commands inside the container, not on the host. - Create a project and install Playwright. Make a working directory, enter it, and initialize npm:
mkdir html-shot && cd html-shot && npm init -y. Install the Playwright package withnpm install playwright. This package provides the browser automation API; Chromium must also be available before a screenshot can run. - Install Chromium and its Alpine runtime libraries. Playwright’s browser installation command can download a bundled Chromium build, but Alpine uses musl rather than the glibc environment used by many standard Linux builds. The bundled browser may therefore fail to launch on Alpine. A practical Alpine approach is to install the distribution’s Chromium and common runtime dependencies:
apk add --no-cache chromium nss freetype harfbuzz ca-certificates ttf-freefont. Package availability and dependency names can vary by Alpine release and enabled repositories. Ifapkcannot find Chromium, check that the appropriate community repository is enabled for your release. - Use the system Chromium executable. Create
shot.jsin the project directory. Set Playwright’sexecutablePathto the executable installed by Alpine; it is commonly/usr/bin/chromium-browseror/usr/bin/chromium. Check which one exists withwhich chromium-browser chromium. Use the matching path in the script. This avoids assuming a Playwright-downloaded browser will work on Alpine. - Write a screenshot script. Use this example, replacing the executable path if necessary and changing the input and output names as needed:
const { chromium } = require('playwright');(async () => {const browser = await chromium.launch({ headless: true, executablePath: '/usr/bin/chromium', args: ['--no-sandbox'] });const page = await browser.newPage({ viewport: { width: 1200, height: 800 }, deviceScaleFactor: 1 });await page.goto('file://' + require('path').resolve('input.html'), { waitUntil: 'load' });await page.screenshot({ path: 'output.png', fullPage: true });await browser.close();})().catch(error => { console.error(error); process.exit(1); });
Save the lines asshot.js. The--no-sandboxoption is often needed in containers or when Chromium runs as root, but it weakens Chromium’s isolation. Prefer running as a non-root user with sandboxing enabled where the environment supports it. - Render the HTML. Put
input.htmlbeside the script, then runnode shot.js. The script opens the file in headless Chromium and writesoutput.pngin the current directory. To capture a live site instead, use its URL inpage.goto; ensure the machine can reach it. - Adjust the image dimensions and format. Change the viewport width and height to control the browser’s layout.
fullPage: truecaptures the full document rather than only the visible viewport. For JPEG output, use a filename ending in.jpgand pass a quality value, for exampleawait page.screenshot({ path: 'output.jpg', type: 'jpeg', quality: 85, fullPage: true });. JPEG does not preserve transparency; PNG does. - Wait for content that loads later. If the page uses client-side rendering, images, or web fonts, wait for the relevant content before capturing. For a page that finishes rendering after load, a short targeted wait may help:
await page.waitForSelector('.ready');, replacing the selector with an element your page adds when it is ready. For fonts, useawait page.evaluate(() => document.fonts.ready);. Avoid relying on a fixed delay unless the page provides no better readiness signal.
Common Mistakes
- Using the downloaded browser without checking Alpine compatibility. A Chromium build intended for glibc-based Linux can fail on musl-based Alpine. Use Alpine’s Chromium package and its executable path, or use a compatible Playwright environment rather than guessing at missing libraries.
- Choosing the wrong executable path. The name can differ by package or release. Verify it with
whichand set that exact path inexecutablePath. - Running as root without considering the sandbox. Chromium commonly refuses to launch as root unless sandboxing is disabled. Prefer a non-root container user; use
--no-sandboxonly when appropriate for a trusted, isolated workload. - Taking the screenshot too early. The page’s initial load event does not guarantee that asynchronous content, images, or fonts are ready. Wait for a specific element or resource before capturing.
- Confusing viewport size with full-page size. The viewport controls layout, while
fullPageexpands the captured area to include the page’s full height. A narrow viewport may cause text and columns to reflow even in a full-page image.
Tips
Keep the HTML, script, and generated image in a predictable working directory; relative file paths are resolved from the process’s current directory. For repeatable output, set the viewport explicitly and use consistent fonts. Alpine’s basic font packages may not include the fonts your design expects, so install suitable fonts or bundle permitted font files with your page. If the HTML references local assets, use correct relative paths or absolute file URLs and check that Chromium can read them.
Use PNG for crisp text, diagrams, or transparency. Use JPEG for photographic pages when a smaller file is more important than lossless quality. If you need a particular crop, take a screenshot of a locator or set a specific clip instead of shrinking the viewport. For automated jobs, print browser errors to the console and close the browser in a finally block so failures do not leave a Chromium process running.
Troubleshooting
- “Executable doesn’t exist” or launch reports a missing browser: Check the result of
which chromium-browser chromium, install the Alpine package if needed, and updateexecutablePath. Do not assume Playwright’s own browser download is the executable you should use on Alpine. - “Failed to launch” or a missing shared library: Install Chromium through
apkso Alpine resolves its runtime dependencies, then review the full error output. Add the specific dependency named in the message if it is available for your release. Confirm your package repositories match the Alpine version in use. - Chromium exits immediately as root: Run the process as a non-root user if possible. In a controlled container where that is not practical, add
--no-sandboxto the launch arguments and understand the reduced isolation. - The output is blank or incomplete: Confirm the input file exists and inspect it in a browser. Log the URL and wait for a page-specific selector or font readiness before taking the screenshot. Check the terminal for page errors and verify that referenced files load.
- Text looks different or is missing: Install appropriate fonts and ensure the font files are readable. Wait for
document.fonts.readybefore capturing. If external resources are used, check network access and browser console errors. - The image has the wrong dimensions: Review the viewport settings, page CSS, and
fullPageoption. Use a fixed viewport for predictable layout, and inspect the document’s actual width and height when a full-page screenshot is unexpectedly large.
Frequently Asked Questions
Can I convert HTML to PNG without saving an HTML file?
Yes. Use page.setContent(htmlString) to load an HTML string, then call page.screenshot. Wait for any scripts, fonts, and images the content needs.
Does Playwright work on Alpine Linux?
Playwright’s Node.js API can run on Alpine, but browser compatibility depends on the Chromium build and system libraries. Using Alpine’s packaged Chromium and setting executablePath is a common approach.
How do I capture the whole page?
Set fullPage: true in the screenshot options. The viewport still affects responsive layout, so set its width to the size you want the page to render at.
Can I save the screenshot as JPEG?
Yes. Set type: 'jpeg', use a .jpg path, and optionally choose a quality from 0 to 100. JPEG does not support transparent backgrounds.
Why does my screenshot omit web fonts or images?
They may not have loaded when the capture began, or the browser may not be able to access them. Wait for fonts or a page-specific ready indicator and check network access, paths, and console errors.
Why is --no-sandbox suggested in containers?
Some container or root configurations prevent Chromium’s sandbox from starting. Running Chromium as a non-root user is preferable; disabling the sandbox is a workaround for an appropriately isolated, trusted environment.
Related
General steps for current mainstream versions; menus can differ by device and version. See the disclaimer or report an error.
More in this bed
- How to Schedule Work Profile Android Phones
- How to Enable ChatGPT Plugins and Use Them
- How to Print PowerPoint Slides With Notes
- Fix This App Was Blocked for Your Protection in Windows
- Windows Backup and Restore Stuck? What to Do
- How to Use Microsoft Copilot on Mobile