Quick wins for a faster PC:
Scan for outdated or missing drivers - takes under a minuteDriver Scan →Clear out junk files and repair common Windows errorsFree Scan →Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Query the URLs you need from PostgreSQL, then pass the result rows to a browser automation script that visits each URL and saves an image. For a small, auditable batch, export the query as CSV and parse it with a CSV library; for an application workflow, read rows directly through your existing database driver. The example below uses Playwright with Node.js and includes per-URL results so one failed page does not stop the batch.
Choose how to get URLs from PostgreSQL
Keep database selection and screenshot capture as separate steps: first decide which rows to capture, then send those URLs and stable identifiers to the browser script.
Export a query to CSV
CSV is a straightforward handoff when you want to inspect or archive the exact input to a run. PostgreSQL 18 documents exporting a query result with COPY and CSV options; check the documentation for the PostgreSQL version deployed in your environment before relying on version-specific syntax. See the PostgreSQL 18 COPY documentation.
COPY (
SELECT id, url
FROM public.pages
WHERE url IS NOT NULL
ORDER BY id
) TO '/tmp/urls.csv' WITH (FORMAT CSV, HEADER);
The path in this server-side form is on the PostgreSQL server, and the database process must be able to write there. If you need the file on the client machine running psql, use its copy meta-command with the same query and CSV options, for example:
#1 Best Overall
- Get NVMe solid state performance with up to 1050MB/s read and 1000MB/s write speeds in a portable, high-capacity drive(1) (Based on internal testing; performance may be lower depending on host device & other factors. 1MB=1,000,000 bytes.)
- Up to 3-meter drop protection and IP65 water and dust resistance mean this tough drive can take a beating(3) (Previously rated for 2-meter drop protection and IP55 rating. Now qualified for the higher, stated specs.)
- Use the handy carabiner loop to secure it to your belt loop or backpack for extra peace of mind.
- Help keep private content private with the included password protection featuring 256‐bit AES hardware encryption.(3)
- Easily manage files and automatically free up space with the SanDisk Memory Zone app.(5). Non-Operating Temperature -20°C to 85°C
copy (SELECT id, url FROM public.pages WHERE url IS NOT NULL ORDER BY id) TO 'urls.csv' WITH (FORMAT CSV, HEADER)
Do not split CSV rows on commas yourself. A URL or other field can include commas, quote characters, or line breaks protected by CSV quoting; use a real CSV parser.
Read rows through your application
If the capture program already connects to the database, query the URL and identifier columns through the database driver used by that application and feed the returned rows into the same capture loop. The right driver and connection handling depend on your language and deployment; the workflow does not require CSV as an intermediate format.
Rank #2
- Solid state performance with up to 800MB/s read speeds in a portable drive. (Based on internal testing; performance may be lower depending on host device, interface, usage conditions and other factors. 1MB=1,000,000 bytes.)
- Back up your content and memories on a storage solution that fits seamlessly into your mobile lifestyle.
- Take it with you on your adventures—up to two-meter drop protection means this durable drive can take a beating. (Based on internal testing.)
- Secure it to your belt loop or backpack for extra peace of mind thanks to the tough rubber hook.
- From Sandisk, a brand professional photographers trust to take on assignments.
Capture the rows with Playwright
This runnable Node.js example reads id,url CSV input, visits each parseable HTTP or HTTPS URL, saves a PNG, and writes a JSON-lines result for every row. It uses Playwright’s documented navigation and screenshot operations; this is an implementation pattern, not a claim that a particular batch has been tested. Install Node.js, then install the dependencies:
npm init -y
npm install playwright csv-parse
npx playwright install chromium
Save the following as capture.mjs:
import { chromium } from 'playwright';
import { parse } from 'csv-parse/sync';
import { readFile, mkdir, appendFile } from 'node:fs/promises';
import { createHash } from 'node:crypto';
const inputPath = process.argv[2] ?? 'urls.csv';
const outputDir = process.argv[3] ?? 'shots';
const resultsPath = `${outputDir}/results.jsonl`;
const rows = parse(await readFile(inputPath), {
columns: true,
skip_empty_lines: true,
bom: true,
trim: true,
});
await mkdir(outputDir, { recursive: true });
const browser = await chromium.launch({ headless: true });
const page = await browser.newPage({ viewport: { width: 1440, height: 900 } });
function filenameFor(id, url) {
const safeId = String(id ?? 'row').replace(/[^a-zA-Z0-9_-]/g, '_').slice(0, 60) || 'row';
const hash = createHash('sha256').update(String(url)).digest('hex').slice(0, 10);
return `${safeId}-${hash}.png`;
}
try {
for (const row of rows) {
const id = row.id;
const rawUrl = row.url;
const result = { id, url: rawUrl };
try {
const parsed = new URL(rawUrl);
if (!['http:', 'https:'].includes(parsed.protocol)) {
throw new Error(`Unsupported URL protocol: ${parsed.protocol}`);
}
await page.goto(parsed.href, { waitUntil: 'load', timeout: 30000 });
const path = `${outputDir}/${filenameFor(id, parsed.href)}`;
await page.screenshot({ path, type: 'png', fullPage: false, scale: 'css' });
Object.assign(result, { status: 'ok', path });
} catch (error) {
Object.assign(result, {
status: 'error',
error: error instanceof Error ? error.message : String(error),
});
}
await appendFile(resultsPath, `${JSON.stringify(result)}n`);
}
} finally {
await browser.close();
}
Run it with the CSV file and, optionally, an output directory:
Do these 3 things before closing this tab:
1Repair Windows errors before they cause bigger problems2Scan for outdated or missing drivers - takes under a minute3Clear out junk files and repair common Windows errorsRank #3
- Capacity Display Variance: 500GB external ssd often appears as around 465GB on Windows. MacOS can show full 500 GB capacity. This is binary calculation difference and doesn’t affect SSD hard drive actual physical storage
- 1050 MB/s Speed: Instantly access to your files with blazing-fast 10Gbps external SSD read up to 1050MB/s and write up to 1000MB/s. LED Light indicates USB SSD instant activity
- Data Security: Solid state drives S.M.A.R.T. health diagnostics and adaptive TRIM optimizing data block management ensures consistent write speeds and extends the longevity of the portable SSD
- USB-C & USB-A Cable: Both cables featuring rapid USB 3.2 Gen2, this USB SSD effortlessly bridges devices, enabling seamless cross-platform file transfers and backup between computers, smartphones, tablets and iPhone
- Always Fast: No slowdowns for large file transfers. With SLC caching (25% of current available capacity allocated as high-speed cache), this external SSD delivers steady 10Gbps for transfers within the cache capacity
node capture.mjs urls.csv shots
The script expects column headers named id and url. Change the SQL aliases or the field names in the script to match your schema. Each image name includes a sanitized ID and a short URL hash, reducing collisions while keeping database values out of unsafe filename characters. The JSONL file records successful image paths and errors, making it possible to retry only failed rows.
Choose what each screenshot should contain
Viewport or full page
The example captures the visible viewport, a consistent 1440-by-900 CSS-pixel frame. Set fullPage: true in the screenshot call when you need the entire scrollable document; full-page output can vary substantially in height and storage size. See the Playwright screenshots guide.
Rank #4
- NEARLY 2X FASTER THAN OUR PREVIOUS GENERATION(8) – move 1,000 high-res photos in under 60 seconds(6) with up to 2000MB/s transfer speeds(2).
- IP65 RATING AND UP TO 3M DROP PROTECTION(3) – protects against spills and drops.
- POCKET-SIZED – fits easily in pockets and small bags.
- SPACE TO OWN YOUR AI CONTENT – speed and capacity to download your high-res clips and photo edits.
- 256-BIT AES ENCRYPTION(4) – helps keep private files secure with password protection.
Format and scale
The example explicitly saves PNG at CSS scale. Playwright’s screenshot options also support output path, image format, and scale choices; select them based on the downstream review or storage workflow. Device scale can produce more pixels than CSS scale. The exact available options depend on the Playwright language binding and version; consult the Playwright Page API.
Page readiness
waitUntil: 'load' waits for the page’s load event, but it does not guarantee that every client-rendered widget, lazy image, or animation has finished. If the target pages have a known readiness signal, wait for that selector before capturing. For pages with variable readiness, decide on a bounded wait or a site-specific condition rather than assuming one universal delay will work.
Free tools Windows power users keep installed
One-click scans. No signup required.
Best Value
- Easily store and access 2TB to content on the go with the Seagate Portable Drive, a USB external hard drive
- Designed to work with Windows or Mac computers, this external hard drive makes backup a snap just drag and drop
- To get set up, connect the portable hard drive to a computer for automatic recognition no software required
- This USB drive provides plug and play simplicity with the included 18 inch USB 3.0 cable
- The available storage capacity may vary.
Make larger runs reliable and manageable
- Keep a stable input order. An explicit
ORDER BYand row identifier make it easier to reconcile images and failures with database records. - Validate input and access scope. The example rejects non-HTTP(S) schemes. If URLs come from untrusted rows, also restrict which hosts the script may access: a browser running inside a private network can otherwise reach destinations your users should not control.
- Bound runtime and resources. The example gives each navigation a 30-second timeout and processes sequentially, which limits simultaneous browser work. Those values are starting choices, not universal recommendations; tune them to the sites, run duration, and available resources.
- Record outcomes and retry deliberately. JSONL records one outcome per row. Preserve the input and result files, then retry errors using an explicit retry policy so persistent failures do not loop indefinitely.
- Consider concurrency only after measuring. Parallel pages can increase throughput but also raise memory, CPU, and network use and may trigger rate limits on target sites. Choose a bounded concurrency level appropriate to your environment; there is no universal safe value.
- Expect rendering differences. Playwright notes that screenshots can vary with host operating system, browser version, settings, hardware, power source, and headless mode. For reproducible comparisons, keep the capture environment consistent. See Playwright’s visual comparisons guidance.
Troubleshoot failed captures
- CSV parse error or missing URL: confirm the export includes the
idandurlheaders and is valid CSV. Do not manually split rows; quoted commas and embedded line breaks require a parser. - Invalid URL or unsupported protocol: inspect the stored value for whitespace, missing scheme, or a non-web scheme. Normalize or correct the database value; only HTTP and HTTPS are accepted by this example.
- Navigation timeout: the target may be slow, unreachable, or waiting on behavior beyond the selected load event. Check the site directly, choose a readiness condition suited to it, and adjust the timeout if justified.
- Browser executable missing: run
npx playwright install chromiumin the project environment and verify the operating system dependencies required by Playwright. - Image absent but status is successful: check the output directory and its write permissions, and inspect the recorded path. Confirm that the screenshot call completed and that the process was not interrupted.
- Images differ between runs: keep the same OS, browser version, viewport, scale, and headless configuration, and account for dynamic page content such as timestamps or rotating promotions.
- Run stops partway through: the JSONL log contains completed rows. Retain it and the original CSV, identify rows without an outcome, and resume or retry those explicitly rather than discarding successful captures.
Or skip the browser setup
ScreenshotNeo accepts a URL in one GET request and returns an image or PDF. Its API can process bulk capture requests of up to 100 URLs per call; use the ScreenshotNeo API documentation for request options and authentication. For one URL, the cURL form is:
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
For URLs selected from PostgreSQL, adapt the call in your batch loop and set the output name from the row ID. ScreenshotNeo removes cookie banners, newsletter popups, and chat widgets before capture; bot checks, blank pages, and failed loads are never billed. It also provides an MCP server for AI agents, and its free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000. Visit ScreenshotNeo or sign up free.
Frequently Asked Questions
Can I capture full-page screenshots instead of only the visible viewport?
Yes. Set Playwright’s fullPage screenshot option to true.
Does PostgreSQL CSV export require a custom parser?
Use a CSV parser rather than splitting on commas, because CSV quoting can preserve commas, quotes, and line breaks inside fields.
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.

