DEV Community

Erik for Allscreenshots

Posted on

Debugging Chromium Crashes When Taking Full-Page Screenshots with Playwright

We recently ran into a frustrating issue with our screenshot API: Chromium was crashing with a segmentation fault when capturing full-page screenshots of large websites. Here's how we diagnosed and fixed it.

The Problem

Our API uses Playwright with headless Chromium to capture screenshots. For most sites, everything worked fine. But for very tall pages, we'd get this crash:

[pid=422][err] Received signal 11 SEGV_MAPERR 000000000000
Enter fullscreen mode Exit fullscreen mode

Followed by a stack trace and ultimately a RENDER_FAILED error returned to the user. The SEGV_MAPERR with address 000000000000 is a null pointer dereference—Chromium was running out of memory during the screenshot compositing process.

Our Setup

We're running a Spring Boot + Kotlin application with Playwright inside Docker on a Linux VPS. The container was already configured with generous shared memory:

$ docker exec allscreenshots-api df -h /dev/shm
Filesystem      Size  Used Avail Use% Mounted on
shm             2.0G     0  2.0G   0% /dev/shm
Enter fullscreen mode Exit fullscreen mode

So that wasn't the issue. We also checked if the container had a memory limit:

$ docker exec allscreenshots-api cat /sys/fs/cgroup/memory.max
max
Enter fullscreen mode Exit fullscreen mode

No container limit either—it could use all available host memory.

Finding the Root Cause

The real problem became obvious when we checked the host's actual memory:

$ free -h
               total        used        free      shared  buff/cache   available
Mem:           1.9Gi       1.3Gi       178Mi        26Mi       628Mi       629Mi
Swap:             0B          0B          0B
Enter fullscreen mode Exit fullscreen mode

Only ~630MB available and no swap space. Our 2GB VPS was running Postgres, Caddy, and our application, leaving very little headroom.

To understand why this matters, consider what happens when Chromium takes a full-page screenshot. For a page that's 1920×50,000 pixels at 32-bit color:

1920 × 50,000 × 4 bytes = ~384MB for the raw bitmap alone
Enter fullscreen mode Exit fullscreen mode

Add Chromium's compositing overhead, and you can easily spike to 1GB+ for a single large screenshot. With only 630MB available and no swap, the kernel's OOM killer terminates the process.

The Fix

We added 2GB of swap space:

sudo fallocate -l 2G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile

# Make it permanent across reboots
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab
Enter fullscreen mode Exit fullscreen mode

After enabling swap:

$ free -h
               total        used        free      shared  buff/cache   available
Mem:           1.9Gi       1.3Gi       183Mi        26Mi       631Mi       638Mi
Swap:          2.0Gi          0B       2.0Gi
Enter fullscreen mode Exit fullscreen mode

The large screenshot that was crashing now completes successfully.

Other Things We Considered

Before identifying the root cause, we investigated several other potential fixes:

Increasing Docker's shared memory — Docker defaults to only 64MB for /dev/shm, which is often too small for Chromium. You can increase it in your docker-compose.yml:

services:
  your-app:
    shm_size: '1gb'
Enter fullscreen mode Exit fullscreen mode

This wasn't our issue since we already had 2GB, but it's a common culprit.

Chrome flags for memory reduction — Playwright already adds many memory-saving flags, but you can add more:

chromium.launch(BrowserType.LaunchOptions().apply {
    setArgs(listOf(
        "--disable-dev-shm-usage",
        "--disable-gpu",
        "--disable-software-rasterizer",
        "--single-process",
        "--memory-pressure-off"
    ))
})
Enter fullscreen mode Exit fullscreen mode

Reducing screenshot quality — Using JPEG instead of PNG with reduced quality uses less memory during encoding:

page.screenshot(Page.ScreenshotOptions().apply {
    setType(ScreenshotType.JPEG)
    setQuality(80)
})
Enter fullscreen mode Exit fullscreen mode

Capping maximum height — If you can live with a height limit, this prevents the problem entirely:

val maxHeight = 16384
val actualHeight = (page.evaluate("document.documentElement.scrollHeight") as Number).toInt()

if (actualHeight > maxHeight) {
    logger.warn("Page height $actualHeight exceeds max, capping to $maxHeight")
    // Return error or take partial screenshot
}
Enter fullscreen mode Exit fullscreen mode

For a screenshot API where full-page capture is a core feature, this wasn't an option for us.

Lessons Learned

  1. Always configure swap on VPS instances running Chromium — Even if you think you have enough RAM, screenshot operations can spike memory usage unpredictably. Swap provides a safety net.

  2. Check actual available memory, not just limits — Container memory limits and shared memory size don't matter if the host itself is constrained.

  3. 2GB is tight for a Playwright-based service — If you're running a screenshot API alongside a database and web server, 4GB gives you much more breathing room.

  4. The SEGV_MAPERR 000000000000 error is usually OOM — When you see Chromium crash with a null pointer dereference during screenshot operations, think memory first.

Monitoring Going Forward

We're now keeping an eye on swap usage to know when it's time to upgrade:

free -h | grep Swap
Enter fullscreen mode Exit fullscreen mode

If swap is constantly in use, that's a signal the VPS needs more RAM.


Have you run into similar issues with Playwright or Puppeteer? We'd love to hear about your experience in the comments.

Top comments (0)