Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Some links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.

You can render pages in headless Selenium, save screenshots or PDFs, inspect the resulting DOM, and even open a live DevTools view of a running headless Chrome session. For visual debugging, start with a reproducible viewport and a screenshot; use an explicit wait when the page fills in asynchronously. To watch the running browser, expose Chrome’s remote debugging endpoint and connect to it from a visible Chrome window at chrome://inspect.

What headless means in Selenium

Headless Chrome creates and uses a browser page without displaying the usual platform windows. It still parses and renders the page and runs its scripts; what is absent is the normal visible browser window. Selenium can control this mode by adding --headless=new to Chrome’s options.

Headless mode is not itself a screenshot, recording, or debugging view. Choose an output that fits the question: a PNG captures pixels, a PDF captures print output, serialized DOM shows the document after scripts have run, and DevTools provides an interactive view while the session is active.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Render a page and save a screenshot with Python

This minimal Selenium script opens a page in headless Chrome, sets a consistent viewport, saves a screenshot, and prints the serialized DOM exposed by WebDriver. Install Selenium and ensure Chrome is available in the environment before running it.

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

options = Options()
options.add_argument("--headless=new")
options.add_argument("--window-size=1440,1000")
driver = webdriver.Chrome(options=options)
try:
    driver.get("https://example.com")
    driver.save_screenshot("render.png")
    print(driver.page_source)  # serialized DOM exposed by WebDriver
finally:
    driver.quit()

The try/finally ensures the browser is closed even if navigation or capture raises an exception. save_screenshot writes the visible viewport, not necessarily the entire length of a long page. For consistent comparisons, keep the viewport fixed and use the same capture point in the page’s loading lifecycle.

Wait for dynamic content before capture

driver.get() returning does not guarantee that every lazy image, animation, or API-driven update has finished. If the screenshot is taken too early, it may faithfully capture an incomplete state. Wait for the condition that matters to your page, such as a result element becoming visible:

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

# After driver.get(...):
WebDriverWait(driver, 20).until(
    EC.visibility_of_element_located((By.CSS_SELECTOR, "main .results"))
)
driver.save_screenshot("results.png")

Replace the selector and timeout with conditions appropriate to the page. A condition-based wait is usually more meaningful than assuming every page is ready after the same fixed delay. For command-line captures, Chrome supports --timeout=<milliseconds> to delay capture and --virtual-time-budget=<milliseconds> to advance time-dependent script execution from the browser’s perspective. Virtual time is not a substitute for checking that the particular content you need exists.

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Watch a running headless session with DevTools

A headless session can be inspected interactively. Start Chrome with a remote debugging port, read the browser’s WebSocket endpoint, then connect from a separate, visible Chrome window. Chrome’s guidance describes the Inspect action as opening DevTools for the remote Headless target, including a live page view.

  1. Enable remote debugging. Add --remote-debugging-port=0 to Chrome’s arguments. Port zero asks Chrome to use an available ephemeral port.
  2. Capture the endpoint. Read Chrome’s output for a WebSocket address similar to ws://127.0.0.1:<port>/devtools/browser/.... The actual port and path are generated for the running browser; do not copy the example as a fixed endpoint.
  3. Open the inspector in visible Chrome. Visit chrome://inspect, select Configure…, and enter the host and port from the debugging endpoint.
  4. Inspect the target. Select Inspect on the remote target. DevTools opens with a live view and tools for inspecting DOM, styles, console output, network activity, and runtime state.

The Selenium code above shows the basic browser setup; to use this workflow, add options.add_argument("--remote-debugging-port=0") before creating the driver, then make Chrome’s endpoint output available to the operator who will connect. How that output is surfaced depends on how Chrome is launched and hosted.

Keep the debugging endpoint controlled

A remote debugging endpoint permits inspection of the browser, so treat access to it as privileged. Keep it on a protected interface, avoid exposing it to untrusted networks, and use an ephemeral port when practical. These are operational precautions based on what the endpoint allows; they are not a quoted Chrome security policy.

Choose the right rendered output

Need Use What it gives you
Check layout, colors, or visible defects PNG screenshot A stable image of the rendered viewport. Selenium offers driver.save_screenshot(...) and get_screenshot_as_file(...); Chrome’s command line also supports --screenshot.
Review print-oriented output PDF A saved print rendering. Chrome Headless supports --print-to-pdf; --no-pdf-header-footer removes generated date, URL, and page-number decorations where supported.
See what scripts produced in the document Serialized DOM The post-script document structure. Chrome’s --dump-dom parses the page and runs scripts before serialization, so its output differs from downloading the raw HTML.
Investigate a live runtime problem DevTools inspection An interactive view of the active target, with DOM, styles, console, network, and runtime inspection. It is not a saved artifact.

A screenshot answers “what pixels did the browser show?” DOM output answers “what structure was present after scripts ran?” A PDF answers “what did the page produce for printing?” For a visual bug, save an image; if it is unclear why the image looks wrong, inspect the live target and its console or network activity.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Use Chrome directly for a one-off capture

Selenium is useful when you need WebDriver control, explicit conditions, or repeatable browser automation. For a quick command-line artifact, Chrome Headless can capture without a Selenium script. The supported switches include:

  • --screenshot to write a screenshot (Chrome documents the output as screenshot.png).
  • --window-size=1440,1000 to set the viewport dimensions for a reproducible capture.
  • --print-to-pdf to produce a PDF, optionally paired with --no-pdf-header-footer where supported.
  • --dump-dom to emit the serialized post-script DOM.
  • --timeout=<milliseconds> to delay a command-line capture, or --virtual-time-budget=<milliseconds> for time-dependent scripts.

Use Chrome’s current command-line syntax for your installed build and consult its Headless documentation for exact invocation details. Do not assume that a fixed delay guarantees a page’s application data has loaded.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Handle version and remote-browser setup

Check that Chrome and ChromeDriver have matching major versions. Selenium’s Chrome documentation covers the supported setup and version relationship. If the browser runs remotely, WebDriver can control a browser on another machine through a remote server; the machine hosting Chrome must have the browser and driver configured, and the screenshot or diagnostic output must be made accessible to your workflow.

Local Chrome is typically the simplest arrangement for initial debugging. Remote WebDriver and a DevTools endpoint are useful when a browser runs in CI or a container and you need to inspect that remote target. A visible Chrome window on your workstation does not mean the remote browser is local: connect the inspector to the host and port where the target endpoint is reachable, with suitable network controls.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Troubleshoot blank or incorrect captures

The screenshot is blank

  • Confirm navigation reached the intended URL rather than a redirect, error, or access-check page.
  • Wait for the page’s actual readiness condition before capturing; a successful get() alone may be too early for asynchronous content.
  • Save the serialized DOM at the failure point. If the expected elements are absent, investigate page loading or script execution; if the elements exist but pixels are missing, inspect rendering and styles.
  • Open the live target in DevTools, when available, and check console and network activity for runtime errors or failed resources.

The layout differs between runs

  • Set an explicit --window-size so viewport-dependent layout is repeatable.
  • Wait for a relevant element or state rather than capturing immediately or relying on an arbitrary delay.
  • Capture the screenshot and DOM at the same failure point; the image and structure together help distinguish timing from styling issues.

Chrome or WebDriver will not start

  • Verify Chrome and ChromeDriver major versions match.
  • Confirm the Chrome installation and driver are available in the environment where Selenium is running, especially for remote or containerized sessions.
  • If using DevTools, make sure Chrome was launched with the remote-debugging argument and use the generated host and port rather than guessing them.

The live inspector cannot find the target

  • Check that the remote endpoint is reachable from the visible Chrome instance and that Configure… contains the endpoint’s host and port.
  • Use the current session’s endpoint; an ephemeral port can change on the next launch.
  • Do not make the debugging endpoint broadly reachable just to simplify discovery. Arrange a protected path between the inspector and browser host.

Or skip the browser setup

If you only need a screenshot artifact and do not need to inspect Selenium’s live runtime, ScreenshotNeo accepts a URL in one GET request and returns an image or PDF. Here is the cURL form, adapted to the example page:

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://example.com -o shot.webp

See the ScreenshotNeo API documentation for the request options and response details. Cookie banners, newsletter popups, and chat widgets are removed before capture; bot checks, blank pages, and failed loads are not billed. An MCP server offers screenshot tools for AI agents, and the free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000 shots. This is an alternative for generating captures, not a replacement for live Selenium or DevTools debugging. Create a free ScreenshotNeo account to try it.

Sources for the browser behavior

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.