DEV Community

Custodia-Admin
Custodia-Admin

Posted on • Originally published at pagebolt.dev

Selenium alternative for screenshots and PDF generation: skip the WebDriver

Selenium Alternative for Screenshots and PDF Generation: Skip the WebDriver

Selenium is the standard for browser automation testing. But if what you actually need is a screenshot or a PDF — not assertions, not element interactions — Selenium is a lot of machinery for a simple output.

The setup alone: install selenium, download a WebDriver binary, match the browser version, configure the driver, handle platform differences between local and CI. Then manage the browser lifecycle in code.

Here's what the same job looks like without any of that.

Screenshot: Selenium vs API

Selenium (Python):

from selenium import webdriver
from selenium.webdriver.chrome.options import Options

options = Options()
options.add_argument('--headless')
options.add_argument('--no-sandbox')
options.add_argument('--disable-dev-shm-usage')

driver = webdriver.Chrome(options=options)
driver.set_window_size(1280, 800)
driver.get('https://example.com')
driver.save_screenshot('screenshot.png')
driver.quit()
Enter fullscreen mode Exit fullscreen mode

Requires: selenium, chromedriver, matching Chrome version, webdriver-manager in CI.

API (Python):

import requests

res = requests.post(
    'https://api.pagebolt.dev/v1/screenshot',
    headers={'x-api-key': 'YOUR_API_KEY'},
    json={'url': 'https://example.com', 'fullPage': True, 'blockBanners': True}
)
with open('screenshot.png', 'wb') as f:
    f.write(res.content)
Enter fullscreen mode Exit fullscreen mode

Requires: requests. That's it.

PDF generation

Selenium has no native PDF export for arbitrary pages. The common workaround is Chrome DevTools Protocol (execute_cdp_cmd) — which works, but adds complexity and is Chrome-specific.

import base64
from selenium import webdriver
from selenium.webdriver.chrome.options import Options

options = Options()
options.add_argument('--headless=new')
driver = webdriver.Chrome(options=options)
driver.get('https://example.com')
pdf = driver.execute_cdp_cmd('Page.printToPDF', {'printBackground': True})
with open('page.pdf', 'wb') as f:
    f.write(base64.b64decode(pdf['data']))
driver.quit()
Enter fullscreen mode Exit fullscreen mode

With an API:

res = requests.post(
    'https://api.pagebolt.dev/v1/pdf',
    headers={'x-api-key': 'YOUR_API_KEY'},
    json={'url': 'https://example.com', 'format': 'A4', 'printBackground': True}
)
with open('page.pdf', 'wb') as f:
    f.write(res.content)
Enter fullscreen mode Exit fullscreen mode

Same result. No ChromeDriver, no CDP, no base64 decode.

When to keep Selenium

Selenium is the right choice when you need:

  • Cross-browser testing (Chrome + Firefox + Safari)
  • Complex element interactions with assertions (assert element.text == 'Expected')
  • Page object models and test frameworks (pytest-selenium, etc.)
  • Fine-grained control over browser state between test steps

If your code ends with driver.save_screenshot() or a CDP PDF call and no assertions, that's the sign you're using Selenium as a file generator, not a test runner.

Batch screenshots in parallel

import asyncio, aiohttp

async def screenshot(session, url, filename):
    async with session.post(
        'https://api.pagebolt.dev/v1/screenshot',
        headers={'x-api-key': 'YOUR_API_KEY'},
        json={'url': url, 'fullPage': True, 'blockBanners': True}
    ) as resp:
        with open(filename, 'wb') as f:
            f.write(await resp.read())

async def main():
    urls = [('https://site-a.com', 'a.png'), ('https://site-b.com', 'b.png')]
    async with aiohttp.ClientSession() as session:
        await asyncio.gather(*[screenshot(session, u, f) for u, f in urls])

asyncio.run(main())
Enter fullscreen mode Exit fullscreen mode

Selenium with parallel sessions requires multiple driver instances, which multiplies memory usage. With an API, you fire concurrent requests and the browser infrastructure scales on the other end.


Free tier: 100 requests/month, no credit card. → pagebolt.dev

Top comments (0)