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

iTechGuides is reader-supported. When you buy through links on our site, we may earn an affiliate commission. As an Amazon Associate I earn from qualifying purchases. Learn more

For a repeatable batch, put listing URLs in a file and use a browser automation script to open each one, wait for the part you need, and save a screenshot with a stable filename. Playwright supports viewport, full-page, and element screenshots. Before automating any Indian property portal, check its current terms: Magicbricks requires prior written consent for automated software used to extract or download data, and a screenshot-only workflow should not be assumed exempt.

Choose what each screenshot should preserve

  • Viewport: captures the visible screen as the page first appears. Use this when the initial view is the record you need.
  • Full page: captures content below the fold in a tall image. Choose it when the listing details you need are spread down the page.
  • Element: captures a selected page element, such as a listing card or details panel, without unrelated page chrome.

Playwright documents all three capture scopes. See its screenshot documentation and Python screenshot documentation for API details.

Check portal terms before running a batch

Terms differ by portal and can change. Magicbricks’ General Terms & Conditions state: “Use of automated software to extract or download data from the Site is prohibited without prior written consent.” Because a screenshot batch accesses and captures page content, do not assume screenshots are exempt; get written consent or use an authorized method where required.

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

Housing.com describes itself as an advertising and information platform and says it does not validate listing authenticity. Its terms direct users to independently check property and project details. A screenshot can preserve what appeared at a given time, but it does not prove that the listing is accurate, current, or true.

Check the current terms for 99acres and NoBroker directly before automating. Their automation rules are not established here; that absence is not permission.

Run a repeatable batch with Playwright

The example below uses Python and a plain-text file named urls.txt, with one URL per line. It records the input URL, capture time, output filename, and result in a CSV manifest. It takes full-page screenshots; change full_page=True to False for viewport images. Site-specific selectors and wait conditions must be verified on the portals you are authorized to capture.

Rank #2
Free Fling File Transfer Software for Windows [PC Download]
  • Intuitive interface of a conventional FTP client
  • Easy and Reliable FTP Site Maintenance.
  • FTP Automation and Synchronization

Install and prepare the URL list

python -m pip install playwright
python -m playwright install chromium

Create urls.txt:

https://example.com/listing-one
https://example.com/listing-two

Replace the example addresses with the listing URLs you are permitted to capture. The example portal URLs are placeholders, not real listings.

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

Save this script as batch_screenshots.py

import csv
import hashlib
import re
import time
from datetime import datetime, timezone
from pathlib import Path
from urllib.parse import urlparse

from playwright.sync_api import TimeoutError as PlaywrightTimeoutError
from playwright.sync_api import sync_playwright

INPUT = Path("urls.txt")
OUT = Path("screenshots")
MANIFEST = OUT / "manifest.csv"
VIEWPORT = {"width": 1440, "height": 1000}
NAVIGATION_TIMEOUT_MS = 45_000
READY_TIMEOUT_MS = 20_000
RETRIES = 1  # One additional attempt after the first failure.


def safe_label(url: str) -> str:
    host = urlparse(url).netloc or "page"
    slug = re.sub(r"[^a-zA-Z0-9]+", "-", host).strip("-").lower()
    digest = hashlib.sha256(url.encode("utf-8")).hexdigest()[:8]
    return f"{slug[:40] or 'page'}-{digest}"


urls = [line.strip() for line in INPUT.read_text(encoding="utf-8").splitlines()
        if line.strip() and not line.lstrip().startswith("#")]
OUT.mkdir(parents=True, exist_ok=True)

with MANIFEST.open("w", newline="", encoding="utf-8") as csvfile:
    writer = csv.DictWriter(csvfile, fieldnames=[
        "url", "captured_at_utc", "filename", "status", "error"
    ])
    writer.writeheader()

    with sync_playwright() as p:
        browser = p.chromium.launch(headless=True)
        for index, url in enumerate(urls, start=1):
            filename = f"{index:04d}-{safe_label(url)}.png"
            status, error = "failed", ""
            captured_at = datetime.now(timezone.utc).isoformat()

            for attempt in range(RETRIES + 1):
                page = browser.new_page(viewport=VIEWPORT, device_scale_factor=1)
                try:
                    page.goto(url, wait_until="domcontentloaded",
                              timeout=NAVIGATION_TIMEOUT_MS)
                    # Generic readiness check. Replace with a meaningful listing
                    # selector where the portal and authorized use allow it.
                    page.locator("body").wait_for(
                        state="visible", timeout=READY_TIMEOUT_MS
                    )
                    page.screenshot(path=str(OUT / filename), full_page=True)
                    status, error = "success", ""
                    captured_at = datetime.now(timezone.utc).isoformat()
                    break
                except (PlaywrightTimeoutError, Exception) as exc:
                    error = f"{type(exc).__name__}: {exc}"
                    if attempt < RETRIES:
                        time.sleep(2)
                finally:
                    page.close()

            writer.writerow({
                "url": url,
                "captured_at_utc": captured_at,
                "filename": filename if status == "success" else "",
                "status": status,
                "error": error,
            })
            csvfile.flush()
        browser.close()

Run it with python batch_screenshots.py. Images are written to screenshots/; manifest.csv records each URL’s outcome. The URL hash in each filename helps distinguish addresses that share a host, while the zero-padded row number preserves input order.

Wait for listing content, not just navigation

domcontentloaded means the initial document has been parsed; it does not guarantee that delayed listing details, images, or other dynamic content have appeared. If you know a stable element that indicates the content is ready, replace the generic body check with a locator for that element, for example:

page.locator("YOUR_LISTING_SELECTOR").wait_for(
    state="visible", timeout=READY_TIMEOUT_MS
)

Use a selector verified against the actual page and authorized capture method. If no stable element is available, choose a deliberate wait strategy and inspect sample captures before processing the full list. Waiting for an arbitrary fixed delay can be too short on a slow page and waste time on a fast one.

Keep a comparison set consistent

Use the same browser engine and version, viewport, device scale factor, headless setting, and operating environment throughout a batch. Playwright notes that screenshot rendering can vary with operating system, browser version, settings, hardware, power source, and headless mode; visual differences can therefore come from the capture setup rather than the listing page. See Playwright’s screenshot comparison guidance.

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.

For a defensible record, retain the original URLs and UTC capture timestamps in the manifest, avoid overwriting earlier runs, and keep the images with that manifest. A full-page image may be very tall; use viewport captures or a specific element when the whole page is not needed. Screenshots are visual snapshots, not a substitute for verifying property information independently.

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

Alternative: Chrome Headless for a simple individual capture

Chrome Headless documents a command-line --screenshot option and window-size settings. It can be useful for a quick single-page capture, but the Playwright loop above gives explicit per-URL logging and retry handling for a batch. Consult the Chrome Headless documentation for current command options.

Or skip the browser setup

ScreenshotNeo is a screenshot API and MCP server for developers. One GET request captures a URL; its API can return PNG, JPEG, WebP, or PDF. For a batch workflow, you can call the endpoint once per URL and retain your own input-to-output manifest.

Example with cURL, saving a WebP capture:

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

See the ScreenshotNeo API documentation for parameters and response details. ScreenshotNeo accepts cookie/consent banners before capture and removes 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 the response identifies the page verdict and billing status in headers. Its MCP server offers take_screenshot, get_page_info, and capture_pdf for AI agents and MCP clients. The Free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000, and every feature is available on every plan. ScreenshotNeo does not remove the need to check a portal’s terms or obtain consent when required.

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

Sign up for ScreenshotNeo’s free plan: 1,000 screenshots a month, no card required.

Troubleshoot common batch problems

  • Navigation timeout: the page may be slow, stuck, or still waiting on resources. The script records the failure and makes one additional attempt. Adjust the timeout only after checking sample pages; do not treat a timeout as proof the page is unavailable.
  • Screenshot misses listing details: navigation completion is not the same as dynamic content readiness. Wait for a verified listing selector or use a carefully chosen delay, then review a sample output.
  • Images differ between runs: keep browser and machine settings stable and compare capture timestamps. Rendering differences may reflect environment changes as well as page changes.
  • Duplicate or confusing filenames: retain the URL hash and row number, and do not use a listing title alone as a filename; titles may repeat or contain characters unsuitable for filenames.
  • Portal blocks or restricts automation: stop rather than attempting to bypass access controls. Check current portal terms and obtain written consent or use an authorized option where required.
  • Manifest shows a failed row: read its error field, verify the URL can be opened under the permitted workflow, then rerun only that URL after correcting the cause. Keep the failed record rather than silently dropping it.

Frequently Asked Questions

Can I use this workflow for 99acres or NoBroker?

Only after checking each portal’s current terms and confirming the automation method is permitted; their policies are not established here.

Does a screenshot prove that a property listing is genuine?

No. It records page appearance at capture time and does not validate listing claims.

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.