Do these 3 things before closing this tab:
1Scan for outdated or missing drivers - takes under a minute2Clear out junk files and repair common Windows errors3Fix the driver behind crashes, sound loss and screen glitchesUse a fixed-size worker pool and give each worker its own WebDriver session. Each task should open one URL, wait for a condition suited to that page, save to a unique path, record its result, and call driver.quit() even if capture fails. Selenium has no built-in bulk-screenshot command or universal concurrency cap; your pool size is the explicit limit you tune for available browser resources and the target sites’ policies.
Why each concurrent task needs its own browser
A WebDriver session carries mutable browser state: the current page, window, cookies, and navigation. If several tasks issue commands through one driver, their actions can interfere. Instead, treat each URL as a task and each worker as the owner of a separate browser session, created for that task and closed when it finishes.
As an Amazon Associate I earn from qualifying purchases.
A worker pool bounds how many tasks can run at once. In Python, concurrent.futures.ThreadPoolExecutor(max_workers=...) provides that limit. The number is a configuration choice, not a Selenium default: consider CPU and memory available to the browser processes, any session capacity configured for a Grid, and the destination sites’ access policies. Start conservatively and increase only while the machine or Grid remains healthy.
Runnable Python example for a URL list
This example uses Selenium’s Python bindings and Chrome. Install a current Selenium release and a compatible Chrome browser; Selenium Manager can generally handle driver setup for supported browser installations. The example uses an explicit wait for the document body, which confirms that the body element exists but does not guarantee that application data, images, animations, or lazy-loaded content are ready. Replace that condition with a page-specific one when necessary.
#1 Best Overall
- PORTABLE SCANNER FOR USE ON-THE-GO — The fastest and lightest mobile single-sheet-fed compact document scanner in its class¹
- QUICK DOCUMENT SCANNING ― This Epson ultra-fast scanner scans a single page as quickly as 5.5 seconds²; Windows and Mac compatible
- VERSATILE PAPER HANDLING ― Portable scanner scans documents up to 8.5 x 72 in; Also easily digitizes receipts and ID cards to make accounting, bookkeeping, and organizing simpler
- INTUITIVE, HIGH-SPEED SOFTWARE — Epson ScanSmart Software³ is a smart tool allowing you to easily scan, review, and save; Stay organized easily with the help of this Epson scanner
- EASY SETUP — USB-powered connect to your computer for quick and simple scanning; No batteries or external power supply required to operate portable document scanner; Standard Connectivity: USB 2.0
from concurrent.futures import ThreadPoolExecutor, as_completed
from hashlib import sha256
from pathlib import Path
from urllib.parse import urlsplit
import csv
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.support.ui import WebDriverWait
URLS = [
"https://example.com/",
"https://www.python.org/",
]
OUTPUT_DIR = Path("screenshots")
MAX_WORKERS = 3
PAGE_LOAD_TIMEOUT = 45
ELEMENT_TIMEOUT = 20
def output_path(url: str) -> Path:
parts = urlsplit(url)
host = "".join(c if c.isalnum() or c in ".-_" else "_" for c in (parts.netloc or "no-host"))
digest = sha256(url.encode("utf-8")).hexdigest()[:12]
return OUTPUT_DIR / f"{host}_{digest}.png"
def capture_one(url: str) -> dict:
path = output_path(url)
driver = None
try:
options = Options()
options.add_argument("--headless")
options.add_argument("--window-size=1440,1000")
driver = webdriver.Chrome(options=options)
driver.set_page_load_timeout(PAGE_LOAD_TIMEOUT)
driver.get(url)
WebDriverWait(driver, ELEMENT_TIMEOUT).until(
lambda d: d.find_element("tag name", "body")
)
saved = driver.save_screenshot(str(path.resolve()))
if not saved:
raise OSError(f"Selenium could not write screenshot to {path.resolve()}")
return {"url": url, "path": str(path.resolve()), "status": "success", "error": ""}
except Exception as exc:
return {"url": url, "path": str(path.resolve()), "status": "failure", "error": f"{type(exc).__name__}: {exc}"}
finally:
if driver is not None:
driver.quit()
def main() -> None:
OUTPUT_DIR.mkdir(parents=True, exist_ok=True)
results = []
with ThreadPoolExecutor(max_workers=MAX_WORKERS) as pool:
futures = [pool.submit(capture_one, url) for url in URLS]
for future in as_completed(futures):
results.append(future.result())
print(results[-1])
manifest = OUTPUT_DIR / "manifest.csv"
with manifest.open("w", newline="", encoding="utf-8") as f:
writer = csv.DictWriter(f, fieldnames=["url", "path", "status", "error"])
writer.writeheader()
writer.writerows(results)
if __name__ == "__main__":
main()
What to customize
- Input: Replace
URLSwith your list or load it from a file. Validate URLs before starting if the list is untrusted. - Concurrency: Set
MAX_WORKERSto the maximum number of simultaneous browser sessions you intend to run. The pool prevents the submitted batch from exceeding that worker count. - Readiness: Replace the body-element wait with a meaningful condition, such as a known selector appearing or a state becoming true. Set an explicit wait timeout so one slow page does not hold a worker indefinitely.
- Viewport and browser: The Chrome options set headless mode and a 1440-by-1000 window. Use the same browser, viewport, and options across tasks when consistent output matters.
- Output naming: The filename combines the sanitized host with a digest of the entire URL. This distinguishes paths and query strings on the same host and avoids relying on a potentially unsafe URL as a filename.
- Failure policy: The example records an error per URL and continues with the remaining batch. Add retries or backoff only if appropriate for your targets; Selenium does not define a retry policy.
Make readiness and capture extent explicit
Navigation is not the same as page readiness
A completed navigation does not prove every useful part of a modern page has loaded. A site may populate content after an API request, animate a component, or load images only as the page is scrolled. Selenium’s WebDriver API exposes set_page_load_timeout, but there is no universal condition meaning “all meaningful content is ready.” Choose a condition that matches what the screenshot must show and give it a bounded timeout. If a required element never appears, record that URL as a failure rather than silently saving an incomplete result.
The normal screenshot is the current window
Python WebDriver’s save_screenshot(filename) saves the current window as a PNG. It returns False if an I/O error occurs, so check the return value and use an absolute output path. The ordinary screenshot call does not promise a full-page capture across every browser and driver. Selenium’s Firefox API documents separate full-document screenshot methods; browser and driver support therefore matters if the requirement is a full-page image. See the Python WebDriver API and the Firefox WebDriver API.
Rank #2
- FAST SPEEDS - Scans color and black and white documents a blazing speed up to 16ppm (1). Color scanning won’t slow you down as the color scan speed is the same as the black and white scan speed.
- ULTRA COMPACT – At less than 1 foot in length and only about 1. 5lbs in weight you can fit this device virtually anywhere (a bag, a purse, even a pocket).
- READY WHENEVER YOU ARE – The DS-640 mobile scanner is powered via an included micro USB 3. 0 cable allowing you to use it even where there is no outlet available. Plug it into you PC or laptop and you are ready to scan.
- WORKS YOUR WAY – Use the Brother free iPrint&Scan desktop app for scanning to multiple “Scan-to” destinations like PC, Network, cloud services, Email and OCR. (2) Supports Windows, Mac and Linux and TWAIN/WIA for PC/ICA for Mac/SANE drivers. (3)
- OPTIMIZE IMAGES AND TEXT – Automatic color detection/adjustment, image rotation (PC only), bleed through prevention/background removal, text enhancement, color drop to enhance scans. Software suite includes document management and OCR software. (4)
Run the same bounded pattern on Selenium Grid
A local worker pool is enough when one machine can host the desired browser sessions. For distribution across machines or browser environments, use Remote WebDriver with a Grid command-executor URL and browser options. Each worker still needs its own remote session, and the worker limit should be coordinated with the capacity actually configured in that Grid deployment.
Recommended Free Tools
Selenium describes Grid as routing client commands to remote browser instances, supporting parallel execution across machines as well as browser-version and cross-platform testing. Grid is an optional scaling layer, not a prerequisite for a local batch. Its documentation does not set a universal maximum worker count for your deployment. See Selenium Grid and the Remote WebDriver API.
Rank #3
- FAST DOCUMENT SCANNING — Document scanner with feeder allows you to speed through stacks with a 50-sheet Auto Document Feeder (ADF); Efficient office scanner to help you scan more productively
- INTUITIVE, HIGH-SPEED SOFTWARE — Quickly scan with this desktop document scanner; Epson ScanSmart Software lets you easily preview scans, email files, upload to the cloud, and more; Plus, automatic file naming saves even more time
- SEAMLESS INTEGRATION — Easily incorporate your data into most document management software with the included TWAIN driver; Office document scanner integrates seamlessly with business workflows
- EASY SHARING — Duplex scanner allows you to scan straight to email or popular cloud storage2 services like Dropbox, Evernote, Google Drive, and OneDrive for simple storage and sharing
- SIMPLE FILE MANAGEMENT — Scanner allows the creation of searchable PDFs with Optical Character Recognition (OCR) and convert scans to editable Word or Excel files effortlessly; Designed for home and office document scanning
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
GRID_URL = "http://grid-host:4444/wd/hub"
options = Options()
options.add_argument("--headless")
driver = webdriver.Remote(command_executor=GRID_URL, options=options)
try:
driver.set_page_load_timeout(45)
driver.get("https://example.com/")
# Apply the same task-specific readiness check and output handling here.
finally:
driver.quit()
Use this initialization inside the worker function in place of webdriver.Chrome(...). Keep output writing and per-URL result collection on the client side unless the remote browser environment is deliberately configured to share the destination filesystem; a screenshot path written on a remote node may not be a path available on the client.
Common errors and practical fixes
- Driver or browser fails to start: Confirm that Chrome is installed and supported by the Selenium version in use, then check Selenium Manager or your explicit driver configuration. Reduce
MAX_WORKERSif the host cannot start that many browser processes. - Page-load timeout: The navigation exceeded
PAGE_LOAD_TIMEOUT. Decide whether the URL should fail, be retried under a bounded policy, or use a different readiness strategy. Increasing the timeout may help genuinely slow sites but also ties up a worker longer. - Wait timeout for an element: The expected selector may differ, appear only after interaction, or never load. Verify the condition for that page and capture the exception in the manifest; do not treat a timeout as proof that the page is blank.
- Screenshot returns false or file is missing: Ensure the destination directory exists and the process can write there. Pass an absolute path, as recommended by Selenium’s API, and check the boolean result from
save_screenshot. - Files overwrite one another: Do not name outputs only by a shared index that can be reused between runs or by the host alone. Include a stable unique component such as a digest of the full URL, and ensure the output directory is writable.
- Machine slows or crashes under load: Lower the worker count. Each worker can consume resources in a separate browser session; the useful concurrency is limited by the actual machine or Grid capacity, not by how many futures can be submitted.
- Grid cannot create a session: Check the command-executor URL, Grid availability, requested browser capabilities, and configured session capacity. Keep the pool limit within the capacity available to this run.
- Image omits lower-page content: The standard current-window screenshot captures the visible window, not a guaranteed full document. Use a documented browser-specific full-document method where supported, or change the capture approach to one whose full-page behavior meets the requirement.
Or skip the browser setup
ScreenshotNeo is a screenshot API and MCP server for developers. One GET request returns a PNG, JPEG, WebP, or PDF, and its documentation describes the available parameters.
Quick Recap
Best Value
- OUR MOST ADVANCED SCANSNAP. Large touchscreen, fast 45ppm double-sided scanning, 100-sheet document feeder, Wi-Fi and USB connectivity, automatic optimizations, and support for cloud services. Upgraded replacement for the discontinued iX1600
- CUSTOMIZABLE. SHARABLE. Select personalized profiles from the touchscreen. Send to PC, Mac, mobile devices, and clouds. QUICK MENU lets you quickly scan-drag-drop to your favorite computer apps
- STABLE WIRELESS OR USB CONNECTION. Built-in Wi-Fi 6 for the fastest and most secure scanning. Connect to smart devices or cloud services without a computer. USB-C connection also available
- PHOTO AND DOCUMENT ORGANIZATION MADE EFFORTLESS. Easily manage, edit, and use scanned data from documents, receipts, photos, and business cards. Automatically optimize, name, and sort files
- AVOIDS PAPER JAMS AND DAMAGE. Features a brake roller system to feed paper smoothly, a multi-feed sensor that detects pages stuck together, and skew detection to prevent paper damage and data loss
Rank #4
- Scanner type: Document
- Connectivity technology: USB
- With Auto Scan Mode, the scanner automatically detects what you're scanning
- Digitize documents and images
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://example.com -o shot.webp
ScreenshotNeo accepts cookie or consent banners before capture and removes more than 60 known consent platforms, newsletter popups, and chat widgets; each of those steps can be turned off. Bot checks or CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and responses identify the page verdict and billing status in headers. Its MCP server exposes take_screenshot, get_page_info, and capture_pdf for Claude, Cursor, and other MCP clients. The Free plan includes 1,000 shots per month with no card; paid plans start at $5 for 3,000 shots. ScreenshotNeo is another route when you want managed captures rather than operating browser sessions yourself. Sign up for 1,000 free screenshots a month with no card.
Operational notes for dependable batches
- Keep a manifest: Record the original URL, output path, status, and error for every task. The example gathers results in the main thread and writes one CSV after workers finish, avoiding concurrent writes to one shared file.
- Bound both work and waiting: A fixed pool limits active sessions, while page-load and explicit-wait timeouts limit how long individual tasks occupy workers. These controls solve different problems.
- Respect destination policies: Parallel requests can place more load on a site than a sequential run. Choose a concurrency level and pacing consistent with site terms and access rules.
- Plan disk use: PNG files can accumulate quickly across large batches. Store outputs in a predictable directory and define a retention or cleanup policy appropriate to your workflow.
- Preserve reproducibility: Record or fix browser version, viewport, options, and any relevant locale or page state when comparing screenshots across runs.
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.




