The Playwright --with-deps Flag: When It Helps and When It Breaks Production

When deploying PixelPerfect Screenshot API to Render.com, I learned a critical lesson about Playwright's --with-deps flag: conventional wisdom doesn't always apply to managed hosting platforms.

Most tutorials and documentation suggest that Linux servers need --with-deps to install system dependencies for Chromium. Following this advice, I added the flag to my deployment configuration. The result? Complete build failure.

The fix was counterintuitive: remove --with-deps entirely. The moment I did, the deployment succeeded, Chromium launched perfectly, and screenshots worked flawlessly.

This article explains what actually happened, why managed platforms like Render.com behave differently than bare Linux servers, and how to determine the right approach for your specific hosting environment.

The Failed Deployment: What Went Wrong

Here's what the Render.com build logs showed with --with-deps:

Feb 6 12:04:02 AM  ==> Building with command: pip install -r requirements.txt && python -m playwright install --with-deps chromium
Feb 6 12:04:02 AM  
Feb 6 12:04:02 AM  Switching to root user to install dependencies...
Feb 6 12:04:03 AM  Password: su: Authentication failure
Feb 6 12:04:03 AM  Failed to install browsers
Feb 6 12:04:03 AM  Error: Build failed

The --with-deps flag was attempting to run sudo apt-get install to add system packages. However, Render.com blocks root access during builds for security reasons. This authentication failure caused the entire deployment to crash.

The Problem: The --with-deps flag assumes it can use sudo to install system packages. On managed platforms that restrict root access (like Render.com, Heroku, or Railway.app), this assumption breaks the deployment.

The Solution: Remove --with-deps

After removing the flag, the build logs showed:

Feb 6 12:12:57 AM  ==> Building with command: pip install -r requirements.txt && python -m playwright install chromium
Feb 6 12:12:57 AM  
Feb 6 12:12:57 AM  Playwright browsers installed successfully
Feb 6 12:12:58 AM  ✅ Database tables created successfully
Feb 6 12:12:59 AM  ==> Your service is live 🎉

Success. The service deployed, health checks passed, and screenshot generation worked perfectly.

Why This Worked: Render.com's Ubuntu environment already includes all necessary Chromium dependencies. The --with-deps flag was trying to install packages that were already present, and failing because it lacked permission to do so.

PixelPerfect Deployment: Before vs. After
❌ With --with-deps (FAILED)
python -m playwright install --with-deps chromium
What Happened:
  • Attempted sudo apt-get
  • Required root access
  • Render blocked authentication
  • Build failed immediately
  • Service never started
Authentication Failure
✅ Without --with-deps (SUCCESS)
python -m playwright install chromium
What Happened:
  • Downloaded Chromium binary
  • Used existing system libs
  • No root access needed
  • Build completed successfully
  • Service went live
Service Live 🎉

The Lesson: What works for bare Linux servers doesn't always apply to managed hosting platforms. Render.com pre-installs Chromium dependencies, making --with-deps unnecessary—and problematic.

Understanding What --with-deps Actually Does

The --with-deps flag tells Playwright to install not just the browser binary, but also all system-level libraries that Chromium depends on. On a bare Linux installation, these might include:

  • libnss3 – Network Security Services (SSL/TLS)
  • libnspr4 – Netscape Portable Runtime
  • libatk1.0-0 – Accessibility Toolkit
  • libgbm1 – Generic Buffer Management
  • libxcomposite1 – X Composite extension
  • fonts-liberation – Font libraries
  • Many others...

To install these packages, Playwright runs commands equivalent to:

sudo apt-get update
sudo apt-get install -y libnss3 libnspr4 libatk1.0-0 ...

This requires root privileges, which managed hosting platforms explicitly deny.

Why Managed Platforms Block Root Access

Platforms like Render.com, Heroku, and Railway.app run applications in containerized environments where:

  • Security: Preventing root access limits what malicious code can do
  • Consistency: Pre-installing dependencies ensures every deployment has the same environment
  • Performance: Dependencies are already cached, speeding up builds

These platforms pre-install common dependencies—including everything Chromium needs—so --with-deps becomes redundant.

When DO You Need --with-deps?

The --with-deps flag is essential in these scenarios:

1. Bare Linux Servers (VPS, EC2, DigitalOcean)

If you're deploying to a minimal Ubuntu or Debian installation without a managed platform, you absolutely need --with-deps. These servers start with almost nothing installed.

# On a bare Ubuntu 22.04 server
python -m playwright install --with-deps chromium  # Required!

2. Docker Containers with Minimal Base Images

If your Dockerfile uses a slim Python image without system dependencies:

FROM python:3.11-slim

# Need --with-deps because slim images are minimal
RUN pip install playwright
RUN python -m playwright install --with-deps chromium

3. CI/CD Pipelines on Basic Runners

GitHub Actions, GitLab CI, or Jenkins runners often use minimal images:

- name: Install Playwright
  run: |
    pip install playwright
    python -m playwright install --with-deps chromium

When DON'T You Need --with-deps?

1. Render.com (Confirmed)

As demonstrated with PixelPerfect, Render's Ubuntu environment includes all dependencies:

# Build Command on Render
pip install -r requirements.txt && python -m playwright install chromium

2. Heroku

Heroku's stack includes necessary libraries. Use the official buildpack:

heroku buildpacks:add heroku/python
heroku buildpacks:add https://github.com/mxschmitt/heroku-playwright-buildpack

3. Railway.app

Railway's Nixpacks builder automatically handles dependencies:

# Railway auto-detects and installs
python -m playwright install chromium

4. Vercel/Netlify (Serverless)

These platforms use pre-built layers with dependencies included. Follow their specific Playwright integration guides.

Platform-Specific --with-deps Requirements
Platform Use --with-deps? Reason
Render.com ✗ NO Dependencies pre-installed, root access blocked
Heroku ✗ NO Use official Playwright buildpack instead
Railway.app ✗ NO Nixpacks handles dependencies automatically
AWS EC2 (bare) ✓ YES Minimal OS, no dependencies pre-installed
DigitalOcean Droplet ✓ YES Bare Ubuntu, requires system packages
Docker (slim base) ✓ YES Minimal images lack Chromium dependencies
GitHub Actions ✓ YES Standard runners need explicit installation
Vercel/Netlify ✗ NO Use platform-specific integrations

Rule of Thumb: Managed platforms usually have dependencies pre-installed. Bare servers and minimal containers need --with-deps. When in doubt, try without it first—it's easier to add than to troubleshoot authentication failures.

The Correct PixelPerfect Implementation

Here's the final, working configuration for deploying to Render.com:

requirements.txt

fastapi>=0.104.0
uvicorn[standard]>=0.24.0
playwright>=1.40.0
Pillow>=10.0.0

# IMPORTANT: On Render.com, do NOT use --with-deps
# 
# Render's Ubuntu environment includes all Chromium dependencies.
# Using --with-deps causes authentication failures because it
# attempts to run sudo apt-get, which Render blocks.
#
# Build command: pip install -r requirements.txt && python -m playwright install chromium
#
# For bare Linux servers (EC2, DigitalOcean), you WOULD need --with-deps

Render Build Command

pip install -r requirements.txt && python -m playwright install chromium

Testing the Deployment

After deployment, verify Chromium is working:

# Health check endpoint response
{
  "status": "healthy",
  "screenshot_service": "ready",
  "chromium_installed": true
}

Production Result: With this configuration, PixelPerfect deployed successfully on the first try. The screenshot endpoint handled hundreds of requests without a single browser launch failure. The service runs stable and reliable on Render.com.

Common Pitfalls and How to Avoid Them

1. Assuming Tutorials Apply to All Platforms

Many Playwright tutorials were written for bare Linux servers or Docker containers. They correctly recommend --with-deps for those environments. However, copying these instructions to managed platforms causes the exact failure we experienced.

Fix: Check your platform's documentation specifically. Render, Heroku, and Railway all have different requirements than bare servers.

2. Not Testing Locally with Docker

If you develop on Windows or macOS, you might never encounter dependency issues because those operating systems handle Chromium differently.

Fix: Test your deployment configuration in a Docker container that matches your production environment before pushing to production.

3. Adding --with-deps as a "Just in Case"

It's tempting to add --with-deps thinking "it can't hurt." But on platforms that block root access, it actively breaks the deployment.

Fix: Only add --with-deps if you've confirmed your platform requires it. Start without it and add if needed.

Troubleshooting Decision Tree

Use this decision tree to determine the right approach for your deployment:

Are you deploying to a managed platform?
├─ YES (Render, Heroku, Railway)
│  └─ Try WITHOUT --with-deps first
│     ├─ Build succeeds? ✓ Done!
│     └─ Build fails?
│        └─ Check platform documentation
│           for Playwright-specific setup
│
└─ NO (VPS, EC2, bare Docker)
   └─ Use WITH --with-deps
      ├─ Build succeeds? ✓ Done!
      └─ Build fails?
         ├─ Check you have root/sudo access
         └─ Verify Ubuntu/Debian base (not Alpine)

Conclusion: Platform Matters More Than Assumptions

The --with-deps flag is not universally required or universally harmful—its necessity depends entirely on your deployment platform. The key lesson from deploying PixelPerfect is that conventional wisdom must be tested against your specific environment.

For managed platforms like Render.com, --with-deps was the problem, not the solution. The platform had already solved the dependency problem by pre-installing everything Chromium needs. Our job was simply to avoid interfering with that setup by trying to install packages we didn't have permission to touch.

This experience reinforces an important principle in production deployments: understand your platform's architecture before following generic tutorials. What works on a bare Ubuntu server won't work the same way on Render, Heroku, or Railway. Read the platform-specific documentation, test your assumptions, and be prepared to adjust your approach based on what actually works—not what theoretically should work.

Final Recommendation: For Render.com deployments, use python -m playwright install chromium without --with-deps. Document this decision clearly in your requirements.txt so future developers understand the platform-specific requirement. Test thoroughly before assuming any tutorial applies to your exact hosting environment.


If you found this production troubleshooting deep-dive helpful, explore more real-world deployment insights and platform-specific guides at OneTechly. We share honest lessons from actual production deployments—including the failures that led to success.

About OneTechly: We write about real development challenges and the solutions that actually worked in production. From platform-specific deployment issues to architecture decisions, our articles provide battle-tested insights for building reliable applications. Follow us for more technical deep-dives that go beyond theory to show what really happens when code meets production.

Comments

Popular posts from this blog