ScreenshotNeo

BlogHow-to

How to Organize Website Screenshots by URL for a Client Project

Build a reliable screenshot archive with URL-based filenames, a capture manifest, consistent viewports, review statuses, and a safe client handoff.

By the ScreenshotNeo team4 October 202610 min read

For a client project, organize website screenshots with a project folder, short URL-derived filenames, and a manifest that preserves each full original URL and its capture details. Treat the filename as a quick index and the manifest as the authoritative record. Capture small page sets individually; for larger inventories, use a URL-list or sitemap workflow, then reconcile every result against the manifest before handoff.

1. Set up a project structure

Use a client and project identifier, followed by a capture round, milestone, or date. Keep sensitive client names out of shared paths unless the client permits them.

Client-Project/
  2026-10-03-review/
    screenshots/
    manifest.csv
    README.md
  2026-10-10-approved/
    screenshots/
    manifest.csv
    README.md

Separate capture rounds so reviewers can distinguish current material from earlier or approved work. Keep original captures distinct from edited, annotated, or redacted derivatives. For example, place derivatives in an annotated/ subfolder or add a clear suffix.

2. Create a manifest before capturing

Maintain one row per requested page. A spreadsheet or CSV works for small projects; for an automated pipeline, JSON Lines or a database can hold the same fields. Keep the full original URL, including query parameters, even when it is too long or awkward for a filename.

page_label,original_url,captured_at,timezone,viewport,status,filename,final_url,http_status,notes
pricing,https://example.com/pricing,2026-10-03T14:30:00,UTC,1440x900,captured,pricing__desktop__2026-10-03__review.png,,,,
mobile-home,https://example.com/?campaign=fall,2026-10-03T14:35:00,UTC,390x844,needs-recapture,mobile-home__mobile__2026-10-03__review.png,,,,

Useful fields include:

  • Original URL: exact URL submitted for capture, including query string and fragment when relevant.
  • Page label: a stable, human-readable name such as pricing or mobile-home.
  • Capture time and timezone: timestamps without a timezone can be ambiguous across client teams.
  • Viewport: width and height, plus device preset or scale when applicable.
  • Status: for example captured, needs-recapture, review, or approved.
  • Filename: the saved asset name, including extension.
  • Final URL and HTTP status: useful when redirects or load failures matter, if the capture tool exposes them.
  • Notes: login state, consent state, interaction performed, capture options, or a reason a page needs another attempt.

A URL-list service may supply a manifest, but inspect its fields and fill any gaps. For example, url2image says its manifest includes title, final URL, HTTP status, and page size; it also describes a not-rendered.csv report for failed URLs. These are vendor descriptions, not independent validation. url2image

3. Use stable, readable filenames

A practical pattern is page-label__viewport__YYYY-MM-DD__status.png. This is a recommendation for this workflow, not an industry standard.

pricing__desktop__2026-10-03__review.png
pricing__mobile__2026-10-03__review.png
account-settings__desktop__2026-10-10__approved.png

Derive the label from the page’s purpose or a normalized URL path, then keep it stable between rounds. Do not put the entire URL in the filename: query strings, fragments, long paths, and characters unsuitable for filenames make names unwieldy. Preserve the unmodified URL in the manifest instead.

For a script that creates filenames, normalize carefully: lowercase where appropriate, replace runs of spaces and punctuation with hyphens, trim leading and trailing separators, and cap the label length. Add a short unique suffix if two URLs map to the same label. Do not discard query parameters from the manifest just because the filename omits them.

4. Keep capture conditions comparable

Record the viewport and use the same dimensions within a comparison set. If a design review covers desktop and mobile, capture both deliberately and label them separately. Website Capture describes desktop and mobile viewport selection, while WebPinch describes recording screen resolution with each feedback pin. Confirm the current options in the products before relying on a specific workflow. Website Capture · WebPinch

Also record any condition that could change the visible page: logged-in versus logged-out state, consent choice, selected tab, expanded menu, locale, or a known wait condition. A screenshot is a record of a page under particular conditions, not just a URL. Exact repeatability depends on the site and capture setup.

5. Choose a capture workflow that fits the page count

Occasional pages

For a small set, capture pages individually. Check each saved image, enter its filename and outcome in the manifest, and retry only the rows that failed or need a different state.

Larger inventories

For many pages, consider a pasted URL list, CSV/text input, or sitemap discovery. url2image describes URL-list input from pasted URLs or CSV/text. Website Capture describes sitemap discovery and a controlled batch queue. WebCapture describes URL-list capture in a browser extension. These are vendor feature descriptions; verify current behavior, export fields, and limits before choosing. url2image · Website Capture · WebCapture

After a batch, compare requested URLs with completed files and any failure report. Resolve missing outputs, redirects, duplicate labels, and pages that landed in an unexpected state before marking the round complete.

Questions to check before selecting a tool

  • Input: single URL, pasted list, CSV/text file, or sitemap?
  • Page behavior: does the page need a login, interaction, consent handling, or a session? The reviewed vendor pages do not establish uniform authenticated-page support. Test an authorized representative page first.
  • Consistency: can you use the same viewport and full-page behavior across the set?
  • Review: does the workflow support annotations, redaction, project history, failure reporting, or PDF export that your handoff needs?
  • Storage and privacy: does capture happen locally or on a vendor’s servers, and does that fit the client’s policy?
  • Failure details: can you identify which page failed and whether a redirect changed the destination?

SiteHaul notes that hosted capture renders pages on external servers and says this rules it out for some client or staging work. Treat that as a reminder to check data handling and client requirements, not as a universal assessment of hosted tools. SiteHaul

6. Review, annotate, and protect the captures

  1. Open every output and confirm it shows the intended page and state.
  2. Update the manifest with the actual filename, final URL or failure, and review status.
  3. Mark unexpected results needs-recapture and note the likely cause.
  4. Inspect for personal, account, or other sensitive details. Redact before sharing when needed.
  5. Keep source captures separate from annotated or redacted derivatives.
  6. Include the manifest and a short README that explains the round, naming pattern, and status meanings.

Some tools describe annotation and redaction features: WebCapture describes markup, redaction, export, and local history; Website Capture describes a review workspace and PDF export; WebPinch describes feedback pins tied to screenshots, URLs, and device context. Review the resulting files yourself before sharing; a tool feature does not replace that check. WebCapture · Website Capture · WebPinch

7. Automate a local URL-to-file workflow

For a simple local workflow, a browser automation script can read URLs from a CSV, save screenshots, and write a manifest. This example uses Playwright for Node.js. Install Playwright and its Chromium browser using the official Playwright setup guide; then save the script as capture.mjs beside urls.csv. The input CSV must have a header named url. This example captures one viewport per URL and uses a basic label from the URL path. Adapt login and interaction steps only for pages you are authorized to access.

import { chromium } from 'playwright';
import { createReadStream, mkdirSync, writeFileSync } from 'node:fs';
import { parse } from 'csv-parse/sync';

const rows = parse(createReadStream('urls.csv'), {
  columns: true,
  skip_empty_lines: true,
});
const date = new Date().toISOString().slice(0, 10);
const outDir = `Client-Project/${date}-review/screenshots`;
mkdirSync(outDir, { recursive: true });

const browser = await chromium.launch({ headless: true });
const results = [];
try {
  const page = await browser.newPage({ viewport: { width: 1440, height: 900 } });
  for (const row of rows) {
    const originalUrl = row.url;
    let label = 'page';
    try {
      const parsed = new URL(originalUrl);
      label = (parsed.pathname.split('/').filter(Boolean).pop() || 'home')
        .toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-|-$/g, '').slice(0, 50) || 'page';
    } catch {}
    const filename = `${label}__desktop__${date}__review.png`;
    const record = {
      page_label: label,
      original_url: originalUrl,
      captured_at: new Date().toISOString(),
      viewport: '1440x900',
      status: 'needs-recapture',
      filename,
      final_url: '',
      error: '',
    };
    try {
      const response = await page.goto(originalUrl, { waitUntil: 'networkidle', timeout: 45000 });
      await page.screenshot({ path: `${outDir}/${filename}`, fullPage: true });
      record.final_url = page.url();
      record.http_status = response?.status() ?? '';
      record.status = response && response.status() >= 400 ? 'review' : 'captured';
    } catch (error) {
      record.error = String(error);
    }
    results.push(record);
  }
} finally {
  await browser.close();
}
writeFileSync(`${outDir}/../manifest.json`, JSON.stringify(results, null, 2));

Install the two JavaScript dependencies with npm install playwright csv-parse. In production, consider writing the manifest incrementally so an interrupted run does not lose completed records. A pathname-derived filename can collide for URLs on different hosts or URLs with different query parameters; detect collisions and append a stable short suffix rather than overwriting files. The script records failures in the manifest and continues to the next URL.

8. Troubleshoot common capture problems

Symptom Likely cause What to do
No image for a requested URL Navigation timeout, blocked request, browser failure, or invalid URL. Keep the row in the manifest, record the error, check the URL manually, and retry that page. Do not silently omit failed entries.
Screenshot shows a loading state The page needed more time or a specific element to appear. Wait for a meaningful selector or a suitable page-ready condition, then capture. Record the wait condition.
Page looks different between rounds Viewport, login state, consent choice, locale, dynamic content, or interaction differed. Compare recorded conditions, use a consistent viewport, and document unavoidable dynamic content.
Two screenshots overwrite each other Different URLs normalized to the same page label. Check filename collisions before writing; add a stable suffix and preserve both full URLs in the manifest.
Redirected page is unexpected The requested URL redirected, perhaps due to locale, authentication, or a changed route. Record the final URL, investigate whether the redirect is expected, and update the manifest or retry with the required authorized session.
Content is missing below the fold Lazy-loaded content did not load before capture or the tool captured only the viewport. Use full-page capture when appropriate and test whether scrolling or waiting is needed to load below-fold content.
Sensitive details appear in the output The page exposed personal or account data during capture. Restrict access, redact the shared derivative, and confirm the client’s handling requirements before handoff.

9. Reliability, performance, and cost considerations

  • Reliability: retain one record per requested URL, including failures. Capture in manageable batches and make retries target failed or reviewed rows. Do not label a whole batch successful solely because the process exited normally.
  • Performance: browser rendering uses time and resources per page. A long wait condition such as network idle can stall on pages with ongoing requests; select a condition suited to the site. Run batches at a controlled concurrency and avoid overwhelming client staging systems.
  • Comparability: consistent viewport, state, and capture timing make review more useful. Dynamic ads, personalized content, and changing live data may still vary.
  • Cost: local browser capture avoids a per-shot hosted service charge but takes setup, compute, storage, and maintenance. Hosted tools may price by usage or plan; check current terms and pricing. No independent benchmark or cost comparison is available in the research reviewed for this guide.
  • Privacy: a hosted renderer receives the URL and may request the page from its infrastructure. Check the client’s approval and the service’s data handling before sending confidential or staging URLs.

10. Or skip the browser setup

ScreenshotNeo is a website screenshot API and MCP server for developers. For a page you are authorized to capture, one GET request returns an image or PDF. Use the same call per URL, then store each result under your project naming pattern and record the URL and capture context in your manifest. The ScreenshotNeo documentation covers the API options.

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)
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}`);
  • Cookie and consent banners are accepted like a visitor, and 60+ known consent platforms, newsletter popups, and chat widgets are removed before capture. Each step can be turned off.
  • Bot checks or CAPTCHAs, blank pages, timeouts, failed loads, and cache hits cost nothing. Response headers report the page verdict and billing status.
  • An MCP server provides take_screenshot, get_page_info, and capture_pdf tools for Claude, Cursor, and other MCP clients.
  • The Free plan includes 1,000 screenshots per month with no card. Paid plans start at $5 for 3,000 screenshots. Every feature is on every plan.

Start with 1,000 free screenshots a month, with no card.

FAQ

Should the URL itself be the filename?

No. Use a short, readable label for the filename and keep the exact URL in the manifest, where query strings and long paths remain intact.

Should each capture round get a new folder?

Yes, when the rounds represent separate review dates or milestones. This keeps older, current, and approved images easy to distinguish.

Can a sitemap replace a reviewed page list?

It can help discover URLs, but inspect the resulting set and outcomes. A sitemap does not establish that every page is in scope or renders correctly.

Is this filename format a standard?

No. It is a practical convention; consistency within the project matters more than adopting a particular pattern.

Sources and scope

Tool capabilities above are descriptions from their vendors, not results of independent hands-on testing. Verify current features, terms, pricing, browser compatibility, and data handling before selecting a tool. url2image · WebCapture · Website Capture · SiteHaul · WebPinch