ScreenshotNeo

BlogHow-to

How to Save Selenium Screenshots as JPEG Instead of PNG

Selenium’s Python screenshot methods produce PNG files. Convert the screenshot bytes with Pillow to save a real JPEG, with control over quality and transparency.

By the ScreenshotNeo team4 October 20266 min read

Direct answer: In Selenium’s Python API, save_screenshot() and get_screenshot_as_file() write PNG images. Renaming the file to .jpg does not convert its contents. Get the screenshot bytes with get_screenshot_as_png(), open them with Pillow, convert to RGB, and explicitly save as JPEG:

from io import BytesIO
from PIL import Image

png_bytes = driver.get_screenshot_as_png()
with Image.open(BytesIO(png_bytes)) as image:
    image.convert("RGB").save("screenshot.jpg", format="JPEG", quality=90)

This creates a JPEG file from the captured pixels. The quality value is a choice for your use case, not a universal standard. JPEG is lossy and does not support transparency; use PNG if you need exact pixels, sharp text, or an alpha channel.

Why changing the extension does not work

A filename extension is a label, not an image encoder. Selenium’s Python screenshot-to-file methods produce PNG output, so saving those bytes as screenshot.jpg leaves PNG data inside a file with a misleading extension. Some viewers may identify the contents anyway, while other software can fail or treat it incorrectly.

To make a JPEG, decode the PNG image and encode its pixels again using a JPEG encoder. Pillow performs that conversion in the example above. Selenium documents its Python screenshot file method as saving a PNG image. Selenium Python WebDriver API.

Install Pillow

Install Pillow in the same Python environment that runs your Selenium script:

python -m pip install Pillow

Selenium itself must also be installed and configured for your browser. This guide assumes you already have a working WebDriver instance named driver.

Convert Selenium screenshot bytes to JPEG

get_screenshot_as_png() returns PNG bytes. BytesIO exposes those bytes to Pillow as a file-like object, so there is no need to write an intermediate PNG to disk.

from io import BytesIO
from PIL import Image

png_bytes = driver.get_screenshot_as_png()

with Image.open(BytesIO(png_bytes)) as image:
    jpeg = image.convert("RGB")
    jpeg.save("screenshot.jpg", format="JPEG", quality=90)

The explicit format="JPEG" makes the intended output format clear. Pillow also infers a format from the extension in many cases, but specifying it avoids ambiguity. Pillow documents opening image data from a byte stream and saving in a chosen format. Pillow tutorial.

Complete runnable Python example

This standalone example opens a page, captures the current browser window, writes a JPEG, and closes the browser even if capture or conversion fails. It uses Selenium Manager to handle the driver setup supported by your Selenium installation:

from io import BytesIO
from pathlib import Path

from PIL import Image
from selenium import webdriver

output_path = Path("screenshot.jpg")

options = webdriver.ChromeOptions()
options.add_argument("--headless=new")

with webdriver.Chrome(options=options) as driver:
    driver.get("https://example.com")
    png_bytes = driver.get_screenshot_as_png()

with Image.open(BytesIO(png_bytes)) as image:
    image.convert("RGB").save(output_path, format="JPEG", quality=90)

print(f"Saved {output_path.resolve()}")

If your Chrome version does not support --headless=new, remove that argument or use the headless option supported by your installed browser. Replace the sample page with the page you need to capture.

Choose JPEG quality and handle transparency

JPEG quality trades file size for image detail. Higher values generally preserve more detail and produce larger files; lower values produce smaller files with more visible compression. There is no single correct setting. Inspect the result at its intended display size and choose the lowest quality that remains acceptable.

Need Format and handling
Small photographic screenshots JPEG; choose and inspect a quality value for your use.
Pixel-exact output or sharp text and edges PNG avoids JPEG’s lossy compression.
Transparent background Keep PNG. JPEG has no alpha channel.
JPEG with a deliberate background Composite onto that background before saving as JPEG.

convert("RGB") removes an alpha channel, which can produce an unintended background appearance for transparent pixels. If you want a specific background, composite first:

from io import BytesIO
from PIL import Image

png_bytes = driver.get_screenshot_as_png()
with Image.open(BytesIO(png_bytes)) as image:
    rgba = image.convert("RGBA")
    background = Image.new("RGB", rgba.size, "white")
    background.paste(rgba, mask=rgba.getchannel("A"))
    background.save("screenshot.jpg", format="JPEG", quality=90)

Use a different RGB color in Image.new() if white is not the intended background. Pillow’s documented JPEG workflow converts images to RGB because JPEG does not preserve transparency. Pillow tutorial.

Save through a temporary PNG file

If your workflow is file-based, save the Selenium screenshot as PNG, then open that file with Pillow and save a separate JPEG:

from PIL import Image

if not driver.save_screenshot("screenshot.png"):
    raise RuntimeError("Selenium could not save screenshot.png")

with Image.open("screenshot.png") as image:
    image.convert("RGB").save("screenshot.jpg", format="JPEG", quality=90)

This uses extra disk space and an additional file operation compared with converting the bytes in memory. Keep the PNG if you need a lossless original; otherwise remove it after successful conversion.

Other Selenium language bindings

The Python behavior does not necessarily apply to every Selenium binding. The documented .NET screenshot API, for example, accepts a ScreenshotImageFormat value that includes JPEG. Check the API for the language you are using instead of assuming every binding has Python’s PNG-only file method. Selenium screenshot documentation.

Performance, reliability, and file size

  • Conversion cost: Pillow must decode the PNG and encode JPEG, which takes CPU time and memory proportional to the image dimensions. For ordinary screenshots, keeping the bytes in memory avoids extra disk reads and writes.
  • Output size: JPEG is often useful when reducing the size of photographic images, but the result depends on image content and quality. Measure your own pages; large flat areas and text can behave differently from photographs.
  • Reliability: Check that the browser capture returned bytes and allow exceptions from Pillow to surface. Write to a temporary destination and rename it after saving if downstream jobs must never see a partially written output.
  • Fidelity: JPEG compression can introduce artifacts around text and sharp edges. Retain the PNG source when reproducibility or pixel comparison matters.

Troubleshooting

Symptom Likely cause Fix
The JPG file is detected as PNG The PNG bytes were written directly with a .jpg name. Decode with Pillow and call save(..., format="JPEG").
cannot write mode RGBA as JPEG The image still has an alpha channel. Convert to RGB, or composite onto a chosen background as shown above.
No module named PIL Pillow is missing from the active Python environment. Run python -m pip install Pillow using the interpreter that runs the script.
The saved image looks washed out or has a dark background Converting an alpha image to RGB discarded transparency without an intentional background. Composite the RGBA image over the desired color before JPEG encoding.
The screenshot is blank or incomplete The page may not have finished rendering or the browser capture may have failed. Wait for the relevant page condition before capturing, and inspect the original PNG bytes or PNG file to distinguish capture problems from conversion problems.
Text looks blurry or has blocky edges JPEG is lossy, especially at lower quality values. Raise the quality or use PNG for text-heavy and pixel-sensitive screenshots.
Browser setup fails before capture The browser, driver, or headless option may not match the environment. Confirm Selenium can open the browser first; adjust the browser option for the installed version and environment.

Or skip the browser setup

ScreenshotNeo is a website screenshot API: one GET request can return a PNG, JPEG, WebP, or PDF. Its API accepts the URL and can return a screenshot without requiring you to set up a browser in your script. See the ScreenshotNeo API documentation for request options.

import requests

r = requests.get(
    "https://api.screenshotneo.com/v1/shot",
    params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"},
    timeout=90,
)
r.raise_for_status()
open("shot.webp", "wb").write(r.content)

To request a JPEG output, use the output-format option documented by the API. ScreenshotNeo removes cookie and consent banners, newsletter popups, and chat widgets before capture; bot checks, blank pages, failed loads, and cache hits are not billed. Its MCP server lets AI agents take screenshots. The free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000 shots.

Get 1,000 free screenshots a month with no card.

FAQ

Can I save Selenium’s Python screenshot directly as JPEG?

The documented Python file methods produce PNG. Capture the PNG bytes and re-encode with an image library such as Pillow.

Does .jpg differ from .jpeg?

Both extensions are commonly used for JPEG files. The important part is that the image data is encoded as JPEG, not just named with a JPEG extension.

Should I delete the PNG after conversion?

Keep it if you need a lossless source or may need to make a different conversion later. Otherwise, remove the temporary file after confirming the JPEG was saved successfully.