DEV Community

Custodia-Admin
Custodia-Admin

Posted on • Originally published at pagebolt.dev

Selenium Alternative: How to Take Screenshots Without Managing a Browser

Selenium Alternative: How to Take Screenshots Without Managing a Browser

You need to take screenshots of web pages in production.

Your first instinct: use Selenium.

You google "Selenium screenshot tutorial." You find a guide that starts with:

"First, download the Java Development Kit (JDK)..."

Then:

"Next, download ChromeDriver..."

Then:

"Make sure ChromeDriver version matches your Chrome version..."

Then:

"If you get 'ChromeDriver is blocked by a certificate error'..."

Three hours later, you've installed JDK, ChromeDriver, configured version matching, and worked around a dozen compatibility issues.

Finally, you write 50 lines of code to take a single screenshot.

There's a better way.


The Problem: Selenium Setup Is a Nightmare

Selenium is powerful. It can automate complex browser interactions, fill forms, click buttons, wait for dynamic content.

But for screenshots, it's overkill.

Here's what you have to deal with:

1. Driver Binary Hellhole

// You need ChromeDriver
// Which version?
// Chrome 121? ChromeDriver 121.0.6167.140? 121.0.6167.160?

// Download the right version
// Extract to /usr/local/bin
// chmod +x
// Test it works
// Update Chrome
// Download new ChromeDriver
// It doesn't work
// ???
// Three hours later...
Enter fullscreen mode Exit fullscreen mode

2. Java/JDK Dependency

If you're using Selenium for Java:

# Install Java 8? 11? 17?
# Maven or Gradle?
# Which version of selenium-java?
# Dependencies resolving...
# version conflicts...
# artifact not found...
Enter fullscreen mode Exit fullscreen mode

3. Version Mismatches

Chrome: 121.0.6167.140
ChromeDriver: 121.0.6167.139
Error: "This version of ChromeDriver only supports Chrome 121.0.6167.139"

Update Chrome
ChromeDriver now out of sync
Download new version
...
Enter fullscreen mode Exit fullscreen mode

4. Deployment Nightmares

You write a screenshot script locally (works fine).

Deploy to production (fails).

  • Different Chrome version on server
  • ChromeDriver binary missing from container
  • Permission issues
  • Memory limits crash the browser

5. 50 Lines of Code for One Screenshot

System.setProperty("webdriver.chrome.driver", "/path/to/chromedriver");
WebDriver driver = new ChromeDriver();
driver.get("https://example.com");
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);

// Wait for element to load
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));
wait.until(ExpectedConditions.presenceOfElementLocated(By.id("content")));

// Take screenshot
File screenshot = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE);
FileUtils.copyFile(screenshot, new File("screenshot.png"));

driver.quit();
Enter fullscreen mode Exit fullscreen mode

The Solution: One API Call

Instead of managing Selenium:

curl -X POST https://api.pagebolt.dev/v1/screenshot \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://example.com",
    "format": "png"
  }' \
  -o screenshot.png
Enter fullscreen mode Exit fullscreen mode

That's it.

No Selenium. No ChromeDriver. No JDK. No version mismatches. One API call.


Before & After

Selenium: Screenshot Code

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

# Setup driver
driver = webdriver.Chrome()

try:
    # Navigate
    driver.get("https://example.com")

    # Wait for element
    wait = WebDriverWait(driver, 10)
    wait.until(EC.presence_of_element_located((By.ID, "content")))

    # Take screenshot
    driver.save_screenshot("screenshot.png")

finally:
    driver.quit()
Enter fullscreen mode Exit fullscreen mode

Lines of code: 18
Setup required: ChromeDriver, Selenium WebDriver, Python packages
Deployment: Fragile (Chrome versions must match)
Error handling: Missing (real code has 3x more lines for error handling)

PageBolt: Screenshot Code

import requests

response = requests.post(
    "https://api.pagebolt.dev/v1/screenshot",
    headers={"Authorization": "Bearer YOUR_API_KEY"},
    json={"url": "https://example.com", "format": "png"}
)

with open("screenshot.png", "wb") as f:
    f.write(response.content)
Enter fullscreen mode Exit fullscreen mode

Lines of code: 8
Setup required: API key only
Deployment: Works everywhere (cloud API)
Error handling: Simple (just check response status)


Real-World Comparison

Use Case: Screenshot a SaaS Dashboard Every Hour

With Selenium:

# schedule.py
import schedule
import time
from selenium import webdriver

def take_screenshot():
    driver = webdriver.Chrome()
    try:
        driver.get("https://myapp.com/dashboard")
        # Wait for dashboard to load (flaky)
        time.sleep(5)
        driver.save_screenshot("dashboard.png")
    except Exception as e:
        print(f"Screenshot failed: {e}")
    finally:
        driver.quit()

# Schedule every hour
schedule.every().hour.do(take_screenshot)

while True:
    schedule.run_pending()
    time.sleep(1)
Enter fullscreen mode Exit fullscreen mode

Issues:

  • Fixed time.sleep(5) is unreliable
  • If Chrome crashes, script exits
  • No logging/monitoring
  • Can't run on headless servers (needs X11)
  • Memory leaks over time

With PageBolt:

# schedule.py
import schedule
import requests

API_KEY = "YOUR_API_KEY"

def take_screenshot():
    try:
        response = requests.post(
            "https://api.pagebolt.dev/v1/screenshot",
            headers={"Authorization": f"Bearer {API_KEY}"},
            json={"url": "https://myapp.com/dashboard"}
        )
        response.raise_for_status()

        with open("dashboard.png", "wb") as f:
            f.write(response.content)
        print("✅ Screenshot captured")
    except requests.RequestException as e:
        print(f"❌ Screenshot failed: {e}")

# Schedule every hour
schedule.every().hour.do(take_screenshot)

while True:
    schedule.run_pending()
    time.sleep(1)
Enter fullscreen mode Exit fullscreen mode

Benefits:

  • No flaky timeouts
  • Cloud-hosted (no local browser needed)
  • Works everywhere
  • Automatic retry/monitoring
  • Same code, 10x fewer headaches

Language Examples

Node.js

Selenium:

const { Builder } = require('selenium-webdriver');
const fs = require('fs');

async function screenshot() {
  let driver = await new Builder()
    .forBrowser('chrome')
    .build();

  try {
    await driver.get('https://example.com');
    await driver.sleep(2000);
    let data = await driver.takeScreenshot();
    fs.writeFileSync('screenshot.png', data, 'base64');
  } finally {
    await driver.quit();
  }
}
Enter fullscreen mode Exit fullscreen mode

PageBolt:

const axios = require('axios');
const fs = require('fs');

async function screenshot() {
  const response = await axios.post(
    'https://api.pagebolt.dev/v1/screenshot',
    { url: 'https://example.com', format: 'png' },
    { headers: { Authorization: 'Bearer YOUR_API_KEY' }, responseType: 'arraybuffer' }
  );
  fs.writeFileSync('screenshot.png', response.data);
}
Enter fullscreen mode Exit fullscreen mode

Java

Selenium:

System.setProperty("webdriver.chrome.driver", "/path/to/chromedriver");
WebDriver driver = new ChromeDriver();
try {
  driver.get("https://example.com");
  Thread.sleep(2000);
  File screenshot = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE);
  FileUtils.copyFile(screenshot, new File("screenshot.png"));
} finally {
  driver.quit();
}
Enter fullscreen mode Exit fullscreen mode

PageBolt:

HttpClient client = HttpClient.newHttpClient();
String json = "{\"url\": \"https://example.com\", \"format\": \"png\"}";
HttpRequest request = HttpRequest.newBuilder()
  .uri(URI.create("https://api.pagebolt.dev/v1/screenshot"))
  .header("Authorization", "Bearer YOUR_API_KEY")
  .POST(HttpRequest.BodyPublishers.ofString(json))
  .build();

HttpResponse<byte[]> response = client.send(request, HttpResponse.BodyHandlers.ofByteArray());
Files.write(Paths.get("screenshot.png"), response.body());
Enter fullscreen mode Exit fullscreen mode

Python

Selenium:

from selenium import webdriver
driver = webdriver.Chrome()
driver.get("https://example.com")
driver.save_screenshot("screenshot.png")
driver.quit()
Enter fullscreen mode Exit fullscreen mode

PageBolt:

import requests
response = requests.post(
  "https://api.pagebolt.dev/v1/screenshot",
  headers={"Authorization": "Bearer YOUR_API_KEY"},
  json={"url": "https://example.com", "format": "png"}
)
open("screenshot.png", "wb").write(response.content)
Enter fullscreen mode Exit fullscreen mode

When You Still Need Selenium

PageBolt is great for screenshots and visual capture.

You still need Selenium for:

  • Complex automation — fill forms, click buttons, navigate multi-step flows
  • Real user interactions — test how users actually use your app
  • JavaScript execution — run custom JS and check results
  • Full browser testing — test cookies, local storage, console errors

But for screenshots alone, PageBolt is simpler, faster, and more reliable.


Migration Guide: Selenium → PageBolt

Step 1: Identify Screenshot Use Cases

In your Selenium code, find all calls to:

  • driver.save_screenshot()
  • driver.get_screenshot_as_*
  • driver.take_screenshot()

These are candidates for migration.

Step 2: Replace with API Calls

For each screenshot call:

Selenium:

driver.get(url)
driver.save_screenshot(path)
Enter fullscreen mode Exit fullscreen mode

PageBolt:

response = requests.post(
  "https://api.pagebolt.dev/v1/screenshot",
  headers={"Authorization": f"Bearer {API_KEY}"},
  json={"url": url, "format": "png"}
)
open(path, "wb").write(response.content)
Enter fullscreen mode Exit fullscreen mode

Step 3: Remove Selenium Dependencies

Delete from requirements.txt / pom.xml / package.json:

  • selenium
  • webdriver-manager
  • Any ChromeDriver or WebDriver packages

Step 4: Test in Production

Deploy the new code to staging. Verify screenshots work.


Cost & Performance

Metric Selenium PageBolt
Setup time 2-3 hours 5 minutes
Code lines 30-50 5-10
Deployment Fragile Reliable
Cost (self-hosted) Free (but server costs) $0-299/month (API)
Speed 2-5 sec per screenshot < 1 sec per screenshot
Reliability ~80% (driver issues) 99.9% (cloud)

The Bottom Line

Selenium is overkill for screenshots. It's designed for complex browser automation.

If you just need images, use an API.

  • ✅ No driver management
  • ✅ No version mismatches
  • ✅ No deployment headaches
  • ✅ Cloud-hosted (works everywhere)
  • ✅ 100x simpler code
  • ✅ Lightning fast

Ready to stop managing Selenium?

Migrate your screenshot code to PageBolt in 5 minutes. Free tier: 100 screenshots/month. Starter plan: 5,000/month for $29.

Get started free →

Top comments (0)