Old Kit, New Kit Part 8: Web Screenshotting — Gowitness vs Manual Screenshotting

This is the seventh tool-pair actually run in a series testing classic, well-documented Kali tooling against its quieter modern replacements, with a genuine look at what a lab Wazuh deployment sees from each. Same honesty note as Part 6’s vuln-scanning pair: there’s no single command for “manual screenshotting” either, so the classic baseline here is a headless browser screenshot invoked one target at a time — exactly what a pentester without a dedicated tool actually does when they need to eyeball a list of web servers. Targets: the three hosts in the lab with a web server (metasploitable2’s two HTTP ports, target-web, target-wordpress) — target-win2022 has no web server, so it’s out of scope for this pair.

How this was verified

gowitness wasn’t installed yet (3.1.1-0kali1 via apt, 13.6MB). It’s a full rewrite from v2, with a genuinely different CLI — subcommands like scan file, scan single, scan cidr, and separate --write-db/--write-csv/--write-jsonl flags for persisting results — worth checking with --help rather than assuming any v2-era tutorial syntax still applies. Chromium was already present for both sides of the comparison.

The classic baseline: one target at a time

$ time chromium --headless --disable-gpu --screenshot=manual-metasploitable2.png --window-size=1280,1024 http://10.10.10.20
27281 bytes written to file manual-metasploitable2.png
real    27.06s

$ time chromium --headless --disable-gpu --screenshot=manual-metasploitable2-8180.png --window-size=1280,1024 http://10.10.10.20:8180
194537 bytes written to file manual-metasploitable2-8180.png
real    25.85s

$ time chromium --headless --disable-gpu --screenshot=manual-target-web.png --window-size=1280,1024 http://10.10.10.30
17105 bytes written to file manual-target-web.png
real    25.67s

$ time chromium --headless --disable-gpu --screenshot=manual-target-wordpress.png --window-size=1280,1024 http://10.10.10.40
40206 bytes written to file manual-target-wordpress.png
real    26.00s

Four sites, four separate invocations, 104.58 seconds total — and every single run landed in a tight 25.67–27.06 second band regardless of which site it hit. That consistency is the tell: this is almost entirely fixed Chromium startup overhead, not actual page-load time, since these are trivial pages on a local lab network that should render in well under a second once a browser is actually running. Each invocation also logs a handful of Google Cloud Messaging registration errors to stderr — background Chromium service noise, unrelated to the screenshot itself, but a reminder that “just run headless Chrome” carries its own startup baggage. The deliverable at the end is four unrelated PNG files with no report, no metadata, and nothing tying a filename back to what was actually on the page beyond however carefully you named it yourself.

The modern tool: gowitness

$ printf 'http://10.10.10.20\nhttp://10.10.10.20:8180\nhttp://10.10.10.30\nhttp://10.10.10.40\n' > gowitness-urls.txt
$ time gowitness scan file -f gowitness-urls.txt --write-db --write-jsonl
result target=http://10.10.10.20:80   status-code=200 title="Metasploitable2 - Linux"
result target=http://10.10.10.30:80   status-code=200 title="Northbridge Freight Co. - Staff Portal"
result target=http://10.10.10.20:8180 status-code=200 title="Apache Tomcat/5.5"
result target=http://10.10.10.40:80   status-code=200 title="Target WordPress Site"
real    4.79s

All four targets, one process, 4.79 seconds — roughly a 22x speedup over the manual approach’s 104.58 seconds, because gowitness launches Chromium once and reuses it across every target instead of paying the startup cost per site. It also surfaced real structured metadata for free that the manual approach never captures at all: HTTP status codes and page titles for every target, including the first look this series has had at target-web’s actual page title — “Northbridge Freight Co. - Staff Portal,” a fictional company name that’s never come up in any earlier part’s output.

gowitness report list reads straight back from the SQLite database the scan wrote and adds even more per-target detail without a second scan:

$ gowitness report list
When              Failed  Code  Input URL                  Title                                Net  Header  Cookie
Aug 29 20:01:31   false   200   http://10.10.10.20:80      Metasploitable2 - Linux             2    7       1
Aug 29 20:01:31   false   200   http://10.10.10.30:80      Northbridge Freight Co. - Staf...   2    11      1
Aug 29 20:01:31   false   200   http://10.10.10.20:8180    Apache Tomcat/5.5                    5    4       1
Aug 29 20:01:31   false   200   http://10.10.10.40:80      Target WordPress Site               6    9       1

Network request counts, header counts, and cookie counts per target — a small operational picture of each site’s complexity that a bare screenshot can’t convey. gowitness report generate goes further and packages everything into a single, portable file:

$ gowitness report generate
report zip file generated successfully path=gowitness-report.zip
$ unzip -l gowitness-report.zip
    8459  index.html
   82194  pico.min.css
   22442  screenshots/http---10.10.10.20-80.jpeg
  116290  screenshots/http---10.10.10.20-8180.jpeg
   12369  screenshots/http---10.10.10.30-80.jpeg
   16591  screenshots/http---10.10.10.40-80.jpeg

That’s a 258KB self-contained bundle — open index.html and you get a browsable report with every screenshot, title, and status code laid out together, something you could hand to a client or a teammate as-is. The manual approach’s four loose PNGs (17KB to 195KB) have no equivalent; the report itself, not just the speed, is the actual product gowitness is selling.

What Wazuh actually saw

Both target-web and target-wordpress carry agents, so both were checked, precisely time-bounded to this test’s actual window (18:58–19:03 UTC / 19:58–20:03 BST) to avoid counting the huge historical alert floods Parts 5 and 6 already left sitting in the same alerts.log:

$ sudo grep -A5 -E '2026 Aug 29 (18:5[8-9]|19:0[0-3]):[0-9]{2} \(target-web\)' /var/ossec/logs/alerts/alerts.log | grep -oP '(?<=Rule: )\d+ ...' | sort | uniq -c | sort -rn
(no output)
$ sudo grep -A5 -E '2026 Aug 29 (18:5[8-9]|19:0[0-3]):[0-9]{2} \(target-wordpress\)' /var/ossec/logs/alerts/alerts.log | grep -oP '(?<=Rule: )\d+ ...' | sort | uniq -c | sort -rn
(no output)

Zero alerts, for either tool, on either target. This is exactly what should happen: a single plain page load is precisely the kind of traffic Wazuh’s default web ruleset has no reason to flag, since it’s built around error-code volume and attack-signature strings, not simple GETs. This pair joins Parts 2 and 4 as the series’ quiet ones — no detection angle here regardless of which screenshotting approach is used, because the underlying traffic shape is identical and entirely unremarkable either way.

Verdict

Unlike Part 7’s split decision, this one’s clean. gowitness is a straightforward, dramatic upgrade over doing this by hand: roughly 22x faster across four targets purely by amortizing browser startup cost across one process instead of paying it per site, plus status codes, page titles, and request/header/cookie counts captured automatically, plus a genuinely useful portable HTML report bundle at the end — none of which the manual approach produces at any speed. The honest caveat carried over from Part 6 stands here too: “manual screenshotting” isn’t a real competing tool, so this was never a fair fight in the way rustscan-vs-nmap or feroxbuster-vs-dirb were. What it does demonstrate cleanly is exactly the kind of workflow automation gowitness exists to replace, and on detection, this pair is a reminder that not every pair in this series needs an interesting Wazuh angle to be worth running — sometimes the finding is simply that the traffic is unremarkable, and the SIEM correctly has nothing to say about it.