Recommended Free Tools
Use Playwright’s Python API to visit each URL in a list and save a screenshot with a unique filename. The workflow is the same for Python users in India as elsewhere: the official documentation describes screenshot calls, not a country-specific service or setup. The examples below use the documented Playwright primitives and show a practical way to organize a batch; queueing, retries and concurrency are choices you make in your script.
Choose a capture mode before you start
- Viewport screenshot: captures the visible browser area. Use it when you want comparable first-screen snapshots.
- Full-page screenshot: captures the scrollable page. It can produce a very tall image, so consider how you will review, store or process it.
- Element screenshot: captures one selected component, such as a product card or chart, rather than the page as a whole.
Playwright’s Python documentation states: “Screenshots API accepts many parameters for image format, clip area, quality, etc.” See the Playwright screenshot guide for the documented options and examples.
As an Amazon Associate I earn from qualifying purchases.
Install Playwright and prepare the URL list
Install the Python package, then install the browser binaries Playwright uses:
python -m pip install playwright
python -m playwright install chromium
Save the pages you want to capture in a text file named urls.txt, with one complete URL per line:
#1 Best Overall
https://example.com/
https://www.python.org/
https://playwright.dev/
Use explicit URLs, including https:// where supported. The script below skips blank lines and gives each URL a numbered output filename so repeated or similar URL paths do not overwrite one another.
Capture a list of URLs with synchronous Python
This implementation pattern opens one browser, creates a fresh page for each URL, saves a viewport screenshot, records failures, and closes the browser. It is not a built-in Playwright bulk service; it is orchestration around the documented navigation and screenshot calls.
from pathlib import Path
from playwright.sync_api import sync_playwright
URL_FILE = Path("urls.txt")
OUTPUT_DIR = Path("screenshots")
FAILURES_FILE = OUTPUT_DIR / "failures.txt"
OUTPUT_DIR.mkdir(parents=True, exist_ok=True)
urls = [line.strip() for line in URL_FILE.read_text(encoding="utf-8").splitlines()
if line.strip()]
failures = []
with sync_playwright() as playwright:
browser = playwright.chromium.launch()
for index, url in enumerate(urls, start=1):
page = browser.new_page()
try:
response = page.goto(url, wait_until="load", timeout=30_000)
if response is not None and response.status >= 400:
failures.append(f"{url}tHTTP {response.status}")
continue
page.screenshot(path=str(OUTPUT_DIR / f"{index:04d}.png"))
except Exception as error:
failures.append(f"{url}t{type(error).__name__}: {error}")
finally:
page.close()
browser.close()
FAILURES_FILE.write_text("n".join(failures), encoding="utf-8")
print(f"Processed {len(urls)} URLs; failures: {len(failures)}")
The script treats an HTTP response status of 400 or higher as a failed capture and skips saving that page. Redirects and pages that return lower statuses proceed to the screenshot call. Navigation can also fail by raising an exception, which is recorded with its URL; inspect screenshots/failures.txt after the run.
Quick wins for a faster PC:
Scan for outdated or missing drivers - takes under a minuteDriver Scan →Repair Windows errors before they cause bigger problemsFix Now →Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Rank #2
Save the full scrollable page
For a full-page image, change the screenshot call to:
page.screenshot(path=str(OUTPUT_DIR / f"{index:04d}.png"), full_page=True)
Choose another image format
The file extension and screenshot type should match. For JPEG, for example:
page.screenshot(path=str(OUTPUT_DIR / f"{index:04d}.jpg"), type="jpeg", quality=80)
Quality applies to JPEG output. Use PNG when you need lossless output or transparency; select the format based on the downstream use and file-size needs.
Use async Python as an alternative
Playwright documents both synchronous and asynchronous APIs. Async can fit naturally into an application that already uses asyncio; it does not by itself guarantee a faster batch. This sequential version follows the same capture pattern and keeps failures associated with their URLs.
The Tool Desk
Outbyte Driver Updater FREEScan for outdated or missing drivers - takes under a minuteDriver Scan →Outbyte PC Repair FREEClear out junk files and repair common Windows errorsFree Scan →import asyncio
from pathlib import Path
from playwright.async_api import async_playwright
URL_FILE = Path("urls.txt")
OUTPUT_DIR = Path("screenshots")
async def main():
OUTPUT_DIR.mkdir(parents=True, exist_ok=True)
urls = [line.strip() for line in URL_FILE.read_text(encoding="utf-8").splitlines()
if line.strip()]
failures = []
async with async_playwright() as playwright:
browser = await playwright.chromium.launch()
for index, url in enumerate(urls, start=1):
page = await browser.new_page()
try:
response = await page.goto(url, wait_until="load", timeout=30_000)
if response is not None and response.status >= 400:
failures.append(f"{url}tHTTP {response.status}")
continue
await page.screenshot(path=str(OUTPUT_DIR / f"{index:04d}.png"))
except Exception as error:
failures.append(f"{url}t{type(error).__name__}: {error}")
finally:
await page.close()
await browser.close()
(OUTPUT_DIR / "failures.txt").write_text("n".join(failures), encoding="utf-8")
print(f"Processed {len(urls)} URLs; failures: {len(failures)}")
asyncio.run(main())
For larger batches, concurrency, throttling, retry policy and timeout values need to be chosen for your workload and target sites. The Playwright screenshot documentation does not establish universal limits or a throughput guarantee. Start with controlled, sequential captures, then add bounded concurrency only if your environment and destination sites can handle it.
Capture one element instead of the whole page
Use a locator screenshot when the output should contain a particular component. Replace the page screenshot call with a locator call, using a selector that identifies the target:
card = page.locator(".product-card").first
card.screenshot(path=str(OUTPUT_DIR / f"{index:04d}-card.png"))
Locator screenshots provide options including animation handling and output settings. An element covered by another element may not appear visibly in the captured image; check the page layout and overlays if the result is obscured. See the Locator screenshot API for the available arguments.
Save screenshots to files or keep them in memory
Passing path writes the image directly to disk, which is convenient for a batch archive. To pass the image to another processing step without first writing it to a file, omit path; the screenshot call returns image bytes:
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
image_bytes = page.screenshot(full_page=True)
# Pass image_bytes to your image-processing or upload step.
The asynchronous equivalent is image_bytes = await page.screenshot(full_page=True). A screenshot can also be configured with options such as output type, JPEG quality and scale; use the API reference for exact parameters and applicable formats.
Best Value
Make repeatable captures and diagnose failures
Keep visual baselines comparable
Screenshot rendering can vary with operating system, browser version, settings, hardware, power source and headless mode. For visual regression baselines, keep the browser and host environment consistent, and avoid comparing captures made under different rendering conditions as if they were identical.
Common failures and practical fixes
- Browser executable is missing: run
python -m playwright install chromiumafter installing the package. - Navigation times out: the site may be slow or may not reach the selected load condition in time. Check the URL and network access, and choose a timeout appropriate to the job rather than assuming every site loads equally quickly.
- Screenshot is blank or incomplete: confirm that navigation reached the intended page and that the chosen wait condition matches the page. Pages that render content after load may need an additional wait for a known selector or other application-specific readiness signal.
- Output files are overwritten: ensure each capture receives a unique path. The examples use list position in the filename.
- Element is absent or hidden: verify the locator matches the intended element and inspect whether another page element covers it.
- Batch stops at one bad URL: keep navigation and capture inside a per-URL exception handler, as in the examples, and review the recorded failures before retrying only affected URLs.
Before running a large list, consider the destination sites’ terms and access expectations. The documentation does not establish site-specific permission rules or a universal request rate.
Or skip the browser setup
ScreenshotNeo is a website screenshot API and MCP server for developers. One GET request can return an image or PDF; its capture flow accepts cookie/consent banners and removes more than 60 known consent platforms, newsletter popups and chat widgets, with each step optional. Bot checks, blank pages, timeouts, failed loads and cache hits are not billed, and responses identify the page verdict and billing status. Its MCP server offers take_screenshot, get_page_info and capture_pdf for AI agents and MCP clients.
Example using cURL (see the ScreenshotNeo documentation):
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
ScreenshotNeo includes 1,000 screenshots per month on its free plan with no card; paid plans start at $5 for 3,000 screenshots. Sign up for the free plan and try 1,000 screenshots a month without a card.
Quick Recap
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.




