DEV Community

Custodia-Admin
Custodia-Admin

Posted on • Originally published at pagebolt.dev

How to Take Screenshots and Generate PDFs in Python (No Selenium Required)

How to Take Screenshots and Generate PDFs in Python (No Selenium Required)

Python developers who need to automate browser tasks have traditionally reached for Selenium or Playwright. Both work, but both come with friction: WebDriver management, dependency hell, browser binary installation, and debugging timeouts.

There's a simpler path: one HTTP call with the requests library replaces the entire Selenium stack.

This article shows you how to take screenshots, generate PDFs, and inspect web pages in Python—without managing a browser at all.

The Old Way: Selenium (Verbose & Heavy)

Here's what taking a screenshot in Selenium looks like:

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from webdriver_manager.chrome import ChromeDriverManager
from selenium.webdriver.service import Service

# Download driver, start browser, navigate
service = Service(ChromeDriverManager().install())
driver = webdriver.Chrome(service=service)

driver.get("https://example.com")
WebDriverWait(driver, 10).until(
    lambda d: d.find_element(By.TAG_NAME, "body")
)

driver.save_screenshot("screenshot.png")
driver.quit()
Enter fullscreen mode Exit fullscreen mode

What's wrong with this?

  • 15+ lines of setup code
  • Managing ChromeDriver binary
  • Polling for page load
  • Brittle selectors
  • Browser process overhead
  • On CI/CD, you need to install headless Chrome

The New Way: REST API (One HTTP Call)

Here's the same task with PageBolt:

import requests

response = requests.post(
    "https://pagebolt.dev/api/v1/screenshot",
    headers={"x-api-key": "YOUR_API_KEY"},
    json={"url": "https://example.com"}
)

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

That's it. One function. One HTTP request. One line to save the file.

No browser to manage. No CI/CD setup. Works everywhere Python runs.

Real Examples: Screenshots + PDFs

Example 1: Screenshot a Responsive Device

import requests
import json

payload = {
    "url": "https://example.com",
    "viewport_device": "iphone_14_pro",  # 25+ device presets available
    "block_banners": True,                # Hide GDPR popups
    "block_ads": True                     # Hide ads
}

response = requests.post(
    "https://pagebolt.dev/api/v1/screenshot",
    headers={"x-api-key": "YOUR_API_KEY"},
    json=payload
)

if response.status_code == 200:
    with open(f"screenshot-iphone.png", "wb") as f:
        f.write(response.content)
    print("✅ Screenshot saved")
else:
    print(f"❌ Error: {response.json()}")
Enter fullscreen mode Exit fullscreen mode

Output: A pristine iPhone 14 Pro screenshot of your website, no Chrome installation required.

Example 2: Generate a PDF Invoice

import requests

html_content = """
<html>
  <body style="font-family: Arial; padding: 20px;">
    <h1>Invoice #12345</h1>
    <p>Total: $1,200.00</p>
    <p>Date: 2026-03-28</p>
  </body>
</html>
"""

response = requests.post(
    "https://pagebolt.dev/api/v1/pdf",
    headers={"x-api-key": "YOUR_API_KEY"},
    json={"html": html_content}
)

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

Done. No wkhtmltopdf, no node-html-pdf, no Puppeteer. Just HTTP and file I/O.

Example 3: Batch Screenshot Multiple URLs

import requests
import json

urls = [
    "https://github.com",
    "https://stackoverflow.com",
    "https://python.org"
]

for url in urls:
    response = requests.post(
        "https://pagebolt.dev/api/v1/screenshot",
        headers={"x-api-key": "YOUR_API_KEY"},
        json={"url": url}
    )

    filename = url.replace("https://", "").replace("/", "_") + ".png"
    with open(filename, "wb") as f:
        f.write(response.content)

    print(f"✅ Saved {filename}")
Enter fullscreen mode Exit fullscreen mode

Three URLs, three HTTP requests, three screenshots. No browser management.

Why This Matters for Python Developers

1. Zero Infrastructure

Selenium requires Chrome + WebDriver. PageBolt's server handles all of that. Your Python environment is just pip install requests—that's it.

2. Massively Faster for Concurrent Requests

Want to screenshot 1,000 pages in parallel? With Selenium, you spawn 1,000 browser instances (memory nightmare). With PageBolt, you send 1,000 HTTP requests in concurrent threads:

import requests
from concurrent.futures import ThreadPoolExecutor

urls = ["https://example.com/page1", "https://example.com/page2", ...]

def screenshot_url(url):
    response = requests.post(
        "https://pagebolt.dev/api/v1/screenshot",
        headers={"x-api-key": "YOUR_API_KEY"},
        json={"url": url}
    )
    filename = url.split("/")[-1] + ".png"
    with open(filename, "wb") as f:
        f.write(response.content)

with ThreadPoolExecutor(max_workers=10) as executor:
    executor.map(screenshot_url, urls)
Enter fullscreen mode Exit fullscreen mode

1,000 screenshots in seconds. No browser overhead.

3. No CI/CD Headaches

GitHub Actions? Docker? Heroku? They just work. No need to install headless Chrome, manage ChromeDriver versions, or debug WebDriver timeouts.

4. Faster Development

Write the request, send it, save the file. No setup, no state management, no flaky waits.

Real-World Use Case: Automated Report Generation

import requests
from datetime import datetime

# Generate an HTML report
html = f"""
<html>
  <body style="font-family: Arial;">
    <h1>Monthly Report</h1>
    <p>Generated: {datetime.now().strftime('%Y-%m-%d')}</p>
    <p>Total requests: 50,000</p>
    <p>Uptime: 99.9%</p>
  </body>
</html>
"""

# Convert to PDF
response = requests.post(
    "https://pagebolt.dev/api/v1/pdf",
    headers={"x-api-key": "YOUR_API_KEY"},
    json={"html": html}
)

# Save and email
with open("report.pdf", "wb") as f:
    f.write(response.content)

print("✅ Report generated and saved as report.pdf")
Enter fullscreen mode Exit fullscreen mode

No Puppeteer. No wkhtmltopdf. Just Python + HTTP.

Comparing: Selenium vs REST API

Task Selenium PageBolt
Take 1 screenshot 15+ lines 5 lines
Take 100 screenshots Spawn 100 browsers OR complex queue logic 100 HTTP requests in a loop
Set up in Docker RUN apt-get install chromium Already included
Cost at scale $500–1000/mo (infrastructure) $29–79/mo (API)
Development time 2–3 hours 15 minutes
Debugging WebDriver logs, browser crashes HTTP status codes, JSON errors

API Reference (Quick Cheat Sheet)

Screenshot:

requests.post(
    "https://pagebolt.dev/api/v1/screenshot",
    headers={"x-api-key": "YOUR_API_KEY"},
    json={
        "url": "https://example.com",
        "viewport_device": "iphone_14_pro",  # optional
        "block_banners": True,                # optional
        "block_ads": True,                    # optional
        "full_page": True                     # optional: capture entire scrollable page
    }
)
Enter fullscreen mode Exit fullscreen mode

PDF:

requests.post(
    "https://pagebolt.dev/api/v1/pdf",
    headers={"x-api-key": "YOUR_API_KEY"},
    json={
        "url": "https://example.com",  # OR "html": "<html>...</html>"
        "landscape": False,              # optional
        "margin": "1cm"                 # optional
    }
)
Enter fullscreen mode Exit fullscreen mode

Page Inspection (for AI agents & web scraping):

response = requests.post(
    "https://pagebolt.dev/api/v1/inspect",
    headers={"x-api-key": "YOUR_API_KEY"},
    json={"url": "https://example.com"}
)

data = response.json()
# Returns all buttons, forms, links, headings with CSS selectors
print(data["buttons"])  # [{selector: "#submit", text: "Submit", ...}, ...]
Enter fullscreen mode Exit fullscreen mode

When Selenium Still Wins

  • Complex, long-running workflows (10+ minute interactions). REST APIs have timeouts.
  • Full browser debugging with DevTools. PageBolt doesn't expose the browser sandbox.
  • Custom JavaScript evaluation with full DOM access. The REST API limits script execution.

For everything else—screenshots, PDFs, responsive testing, batch automation—the REST API is simpler, cheaper, and faster.

Getting Started

  1. Create a free account: https://pagebolt.dev (100 requests/month, no credit card)
  2. Get your API key from the dashboard
  3. Install requests: pip install requests
  4. Run the example:
import requests

response = requests.post(
    "https://pagebolt.dev/api/v1/screenshot",
    headers={"x-api-key": "YOUR_API_KEY"},
    json={"url": "https://example.com"}
)

with open("test.png", "wb") as f:
    f.write(response.content)

print("✅ Screenshot saved as test.png")
Enter fullscreen mode Exit fullscreen mode
  1. Build something.

Final Thought

Selenium and Playwright are powerful tools for complex browser automation. But for the 80% of use cases—taking screenshots, generating PDFs, testing responsive design—they're overkill. A REST API is simpler, faster, and cheaper.

Python's strength is simplicity. Why fight with Selenium when one HTTP call does the job?

Try PageBolt free: 100 requests/month, no credit card. pagebolt.dev

Top comments (0)