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.

Use one Splinter Browser session, loop through your URLs with browser.visit(url), wait for the content each page needs, and save every capture under a unique filename. If you see “Connection refused,” do not assume the website is down: identify the refused host and port first. The failure may be between Python and a local driver, between your client and a remote WebDriver service, or between the automated browser and the target site.

What you need before writing the script

  • Python and a virtual environment for the project.
  • Splinter and its Selenium-backed browser driver.
  • A supported browser, such as Chrome, plus a matching ChromeDriver.
  • A list of reachable HTTP or HTTPS URLs.
  • An output directory where the process can write image files.

Pin or record the Splinter, Selenium, browser and driver versions you install. Splinter’s screenshot argument details cited for this workflow come from its 0.18.0 documentation, while current driver setup may differ. Check the API exposed by your installed version before treating an example as production code.

Capture several pages with one Splinter browser

Creating one browser session and reusing it is simpler than starting a new browser for every URL. A context manager closes the session when the block exits, including normal completion. The example below gives each page an index, so one URL cannot overwrite another capture.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
from pathlib import Path
from splinter import Browser

urls = [
    "https://example.com/one",
    "https://example.com/two",
    "https://example.com/three",
]

output_dir = Path("screenshots")
output_dir.mkdir(parents=True, exist_ok=True)

with Browser("chrome", headless=True) as browser:
    for index, url in enumerate(urls, start=1):
        browser.visit(url)

        # Replace this diagnostic delay with a condition-based wait
        # that matches the content your page actually needs.
        # time.sleep(2)

        path = browser.screenshot(
            name=str(output_dir / f"page-{index:03d}"),
            suffix="png",
            full=True,
            unique_file=False,
        )
        print(f"{url} -> {path}")

The call to visit navigates the current browser to the destination URL. The screenshot method accepts a name and suffix, a full flag and a unique_file option in the cited Splinter documentation. Exact behavior can vary by driver and installed Splinter version; in particular, full=True is not a guarantee of a full-document image in every combination.

Use a readiness condition instead of a blind sleep

Navigation finishing does not mean that JavaScript-rendered content, images or fonts are ready. Selenium describes poor synchronization as its most common class of problem. A fixed sleep can help prove that timing is involved, but a final script should wait for something meaningful: a result container, a heading, a login state, or another selector your page promises.

Choose the wait mechanism supported by your Selenium version and driver. A typical pattern is to wait until a selector exists or becomes visible, then call screenshot. For pages with lazy-loaded images, scroll or otherwise trigger the page’s loading behavior before capture, and wait until the required images have completed. Do not use a short, arbitrary delay as proof that a page is ready.

Keep filenames deterministic and safe

Use an index, a sanitized hostname, or both. Avoid raw URLs in filenames because slashes, query strings and reserved characters can create directories or invalid names. If you intentionally want Splinter to generate distinct names, set unique_file=True; if reproducible paths matter, set it to False and ensure your own names are unique.

Free tools Windows power users keep installed

One-click scans. No signup required.

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

Capture selected URLs while preserving failures

One bad page should not necessarily discard all earlier screenshots. Catch exceptions inside the loop, record the URL and exception text, and continue when that behavior is acceptable for your job.

from pathlib import Path
from splinter import Browser

urls = [
    "https://example.com/one",
    "https://example.com/two",
]

out = Path("screenshots")
out.mkdir(parents=True, exist_ok=True)
errors = []

with Browser("chrome", headless=True) as browser:
    for index, url in enumerate(urls, 1):
        try:
            browser.visit(url)
            # Wait here for a page-specific readiness condition.
            filename = out / f"page-{index:03d}"
            saved = browser.screenshot(
                name=str(filename),
                suffix="png",
                full=True,
                unique_file=False,
            )
            print(f"saved: {saved}")
        except Exception as exc:
            errors.append({"url": url, "error": repr(exc)})
            print(f"failed: {url}: {exc}")

if errors:
    print("Failures:")
    for item in errors:
        print(item)

Whether a failed navigation leaves the session usable depends on the exception and driver. If later iterations produce invalid-session errors, stop and recreate the browser rather than repeatedly using a dead session.

Configure Chrome and ChromeDriver correctly

For Chrome, verify that the browser binary and ChromeDriver executable exist where your configuration expects them. Splinter can receive Selenium’s Service object, allowing an explicit driver executable path; it also supports configuring a custom Chrome binary. Selenium’s troubleshooting guidance recommends checking the browser version and obtaining a matching ChromeDriver.

from selenium.webdriver.chrome.service import Service
from splinter import Browser

service = Service(executable_path="/absolute/path/to/chromedriver")

with Browser("chrome", headless=True, service=service) as browser:
    browser.visit("https://example.com")
    print(browser.title)

The exact keyword accepted by Splinter can change between releases. If this raises an unexpected-argument error, consult the constructor signature for your installed version and pass the service through the documented driver options for that release.

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

Diagnose “connection refused” by locating the connection

“Connection refused” describes a TCP endpoint rejecting a connection; it does not identify the endpoint. Read the complete traceback and note the host, port, and operation that failed. Then select the matching branch below.

Python to a local WebDriver or ChromeDriver

If the refusal names a loopback address or a driver service port while the browser is starting, the driver process may not have started, may have exited immediately, or may be configured at the wrong executable path. Check that the file exists and is executable, that the browser and driver versions match, and that another process is not conflicting with the configured port. Run the driver with suitable logging to expose startup errors.

Python/Selenium to a remote WebDriver service

In a grid, container or hosted setup, confirm the remote URL, route and port. Verify that the service is running from the machine that owns it and that firewalls or security groups permit the intended client. A remote endpoint that is stopped produces a refusal even when your Python code is correct.

The automated browser to the target website

If the WebDriver session starts and only navigation fails, inspect the URL and network path from the browser environment. Test whether one site fails or all sites fail. Device settings, firewalls, antivirus software, network outages, browser extensions, cookies, memory pressure and site downtime can all affect page loading. A successful WebDriver handshake does not prove that the browser can reach every website.

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

A browser window closed before the next iteration

An invalid-session error after a tab or browser closes usually means code called close() or quit() and then attempted to reuse the session, or that the browser process crashed. Keep cleanup at the outer boundary, use the context manager, and create a new session after a terminal driver failure.

A practical troubleshooting checklist

  1. Copy the entire exception, not only its last line.
  2. Record the refused host and port.
  3. Mark the stage: browser startup, WebDriver command, or page navigation.
  4. Check browser and driver versions and executable paths.
  5. For remote execution, verify service health, route, port and firewall rules.
  6. Try a known-simple URL and then the failing URL to separate general network failure from site-specific failure.
  7. Replace a blind delay with a condition-based readiness check.
  8. Confirm the session was not closed or invalidated before the failing call.

Do not call a driver-startup refusal a target-site outage, and do not change driver configuration solely because one website is unavailable.

Security when exposing WebDriver

ChromeDriver is a powerful control interface. It allows local connections by default; if you intentionally make it reachable remotely, restrict allowed IP addresses, run it without a privileged account, place it in a protected environment, and protect the driver and related Selenium ports with firewall controls. Keep Chrome and ChromeDriver current. Never expose an unauthenticated driver endpoint to an untrusted network.

Performance and reliability choices

Reuse one session, but isolate jobs when needed

One session avoids repeated browser startup overhead and preserves cookies between pages. For untrusted sites or very long batches, periodically restart the browser to limit memory growth and cross-page state. A restart also gives you a clean recovery path after a driver crash.

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

Make readiness page-specific

Waiting for a selector that represents the final content is usually faster and more reliable than sleeping for a large fixed interval. For pages with unpredictable third-party resources, set a reasonable timeout and log the URL that exceeded it.

Control output and retries

Write captures to a dedicated directory, log the source URL beside each file, and retry only transient navigation failures. Do not blindly retry a deterministic driver configuration error. Keep the original exception so a later diagnosis can distinguish timeout, refused connection, missing selector and invalid session.

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

Or skip the browser setup

ScreenshotNeo provides a GET-based screenshot API and MCP server when you need images or PDFs without managing Splinter, Chrome or ChromeDriver. It accepts the cookie or consent banner like a visitor, then removes more than 60 known consent platforms, newsletter popups and chat widgets; each cleanup step can be disabled. Only clean shots are billed: bot checks or CAPTCHAs, blank pages, timeouts, failed loads and cache hits cost nothing, and response headers report the page verdict and billing status. Its MCP server exposes take_screenshot, get_page_info and capture_pdf to Claude, Cursor and other MCP clients.

See the parameter reference in the ScreenshotNeo documentation. The same endpoint works for a single URL or can be called repeatedly by your batch script:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
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)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
if (!res.ok) throw new Error(`HTTP ${res.status}`);
const body = Buffer.from(await res.arrayBuffer());
await Bun.write('shot.webp', body);

ScreenshotNeo includes full-page capture with lazy images, CSS-selector element capture, dark mode, device presets and custom viewports, retina scale, PDF controls, custom CSS and JavaScript, click and wait actions, request and resource blocking, headers, cookies, user agents, authorization, timezone, geolocation, transparent backgrounds, resizing, configurable-TTL caching, signed links, asynchronous jobs with signed webhooks, bulk capture for up to 100 URLs per call, a usage API and an OpenAPI specification. Common parameter names used by other screenshot APIs also work, easing migrations.

The Free plan includes 1,000 shots per month with no card. Paid plans start at $5 for 3,000 shots; every feature is available on every plan, and yearly billing gives two months free. Create a free ScreenshotNeo account to start.

FAQ

Does browser.visit wait for every JavaScript request?

No. It navigates to the URL, but your capture should wait for the specific content required by the page.

Should every page use full=True?

Only when your installed driver supports the desired full-page behavior. Validate the result because support varies by driver and version.

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

Can a refused connection be fixed by adding a longer sleep?

Only if the service is slow to start and eventually becomes available. A refusal usually requires correcting the endpoint, service, executable, network route or browser configuration.

Frequently Asked Questions

How can I tell whether ChromeDriver or the website refused the connection?

Read the host and port in the complete traceback and note whether the error occurred while creating the browser or during browser.visit. A loopback driver address points to startup or WebDriver configuration; a target domain points to browser-to-site reachability.

What should I do if the first screenshots save but later ones fail?

Check for a closed or crashed browser session, page-specific timeouts and memory growth. Log each URL, recreate the session after a terminal driver error, and keep cleanup outside the URL loop.

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.

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