Self-hosted service
sensepost/gowitness avatar
sensepost/gowitness

gowitness: Chrome Headless Screenshots for URL, CIDR and Nmap Lists

🔍 gowitness - a golang, web screenshot utility using Chrome Headless

4,523 stars458 forksGoGPL-3.0

At a glance

What is it?
gowitness is a Go utility that drives Chrome Headless to screenshot web interfaces and, optionally, record what it saw. It is aimed at people who need to look at many hosts at once, and its SQLite output feeds a bundled report viewer.
Who is it for?
Adopt gowitness if you already have a list of hosts, from Nmap, Nessus or a CIDR range, and you want screenshots plus a browsable SQLite report without writing a browser harness yourself. Do not adopt it if you need a fully supported Windows pipeline: the README says Windows support is mostly working, which is not the same as supported.
Can I use it commercially?
Yes, with conditions. GPL-3.0 is a copyleft licence: if you distribute software that includes it, you must release that software's source code under the same licence. Running it internally without distributing it does not trigger that obligation.
Is it still maintained?
Yes. The repository last received commits 14 days ago.
What is it written in?
Mainly Go, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 30, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What gowitness solves, and who is on the other end of it

A penetration test or an attack-surface review usually starts with a list of hosts. Turning that list into something a human can look at means opening a browser against every address, waiting for render, and saving an image. Doing that by hand does not scale past a few dozen entries, and writing a Selenium or Puppeteer harness means owning browser lifecycle, timeouts and storage.

gowitness exists to remove that work. The README states the main goal plainly: take website screenshots, and do that well, while optionally saving any information it gathered along the way. The inputs it accepts are the interesting part for this audience. According to the feature list, it scans a list of URLs, CIDRs, Nmap results, Nessus results and more. That means the output of a port scan can be fed straight in, which is the workflow most people arrive with.

It is a command line tool first. There is a report viewer, a web-based results viewer that the README describes as available when data was saved to SQLite, and an API behind it. The intended user is a security practitioner or an operator who wants a visual index of a set of web interfaces, not an application developer embedding screenshots in a product.

How gowitness drives Chrome Headless and where the data goes

The mechanism is a Go binary that talks to Chrome Headless. The go.mod file lists both github.com/chromedp/chromedp and github.com/go-rod/rod, two Go libraries for driving Chrome over the DevTools protocol, alongside github.com/chromedp/cdproto, the protocol bindings. So the browser is not bundled into the Go program; the program is a client that controls a Chrome or headless-shell process.

That distinction matters operationally. The Dockerfile builds the Go binary in a golang image, then copies it into docker.io/chromedp/headless-shell:stable and creates symlinks so that /headless-shell/headless-shell is also reachable as /usr/bin/google-chrome, /usr/bin/chromium and /usr/bin/chromium-browser. The container therefore ships a browser, but only because the base image does. If you run the release binary directly on a host, you supply the browser.

Alongside the screenshot, gowitness can persist what it observed. The README lists a request log, console logs, headers and cookies among the data it can grab and save, and states it can write to many formats including a sqlite database, jsonlines and csv. Technology detection is present too: go.mod depends on github.com/projectdiscovery/wappalyzergo. The reporting layer is a chi router (github.com/go-chi/chi/v5) with CORS middleware and Swagger documentation (github.com/swaggo/swag, github.com/swaggo/http-swagger), served on port 7171 as declared by EXPOSE in the Dockerfile.

Installing gowitness and taking a first screenshot

The README gives go install as the simplest route, assuming $GOBIN is on your shell $PATH. This places the gowitness binary in your Go bin directory.

bash
go install github.com/sensepost/gowitness@latest

The README also points at platform specific release binaries and compiling from source as alternatives, and refers to the wiki for advanced installation information. If you prefer containers, the repository ships a docker-compose.yml that runs the published image ghcr.io/sensepost/gowitness:latest. Note what that compose file actually starts: the report server, not a scan.

yaml
services:
  gowitness:
    image: ghcr.io/sensepost/gowitness:latest
    command: gowitness report server --host 0.0.0.0 --screenshot-path /data/screenshots --db-uri sqlite:///data/gowitness.sqlite3
    volumes:
      - ./gowitness.sqlite3:/data/gowitness.sqlite3
      - ./screenshots:/data/screenshots

The first real use from the README is a single-target scan that writes to a SQLite database and saves the screenshot under ./screenshots. The --write-db flag is what turns on persistence; without it you get the image and no database to browse later.

bash
gowitness scan single --url "https://sensepost.com" --write-db

Expect the command to launch a browser, render the page and drop a file in the screenshots directory. The README notes there are many flags and scan types, and that adding -h anywhere prints them, which is the practical way to discover the Nmap and Nessus input options rather than guessing at flag names.

The report viewer and its API are the reason to keep a database

Screenshots on disk are hard to review in bulk. gowitness addresses that with a web-based results viewer, which the README describes as available if data was saved to SQLite, and which it calls fully featured with an API. The compose file shows the exact invocation: gowitness report server with --host, --screenshot-path and --db-uri. The db-uri in that example is sqlite:///data/gowitness.sqlite3, and the screenshot path is /data/screenshots.

The Dockerfile exposes port 7171 and declares a /data volume with WORKDIR /data, so the container's default working directory is where relative paths resolve. The compose file mounts both the database file and the screenshots directory from the host, which means the report server reads state produced by earlier scan runs rather than collecting it itself.

Two constraints are visible in the compose file. First, the example protects the UI with Traefik basic auth, and the comment warns that you need to escape $ with another $ in the htpasswd hash, which is a real trap when substituting your own credentials. Second, the example credentials are literally gowitness:gowitness. If you copy that file onto a reachable host and do not change them, the report viewer is effectively open. The README does not describe an authentication mechanism inside gowitness itself, so access control is a reverse proxy concern in this deployment shape.

Where gowitness is the wrong tool

The README is candid about one boundary: both Linux and macOS are supported, with Windows support mostly working. That phrasing is a warning, not a feature. If your workflow depends on Windows, treat the platform as unverified and plan a fallback.

The second limitation is structural. gowitness needs a Chrome or headless-shell process it can drive. The Docker image solves this by inheriting one, but a bare binary install does not, and the README does not document browser provisioning for that path. The wiki is where advanced installation is deferred to. On a host without a suitable browser, the tool has nothing to talk to.

Third, this is a screenshot and reconnaissance tool, not a crawler or a monitoring system. Nothing in the README describes scheduled rescans, change detection or alerting. The goimagehash dependency suggests image hashing exists somewhere in the codebase, but the README does not document a deduplication or diffing workflow, so do not assume one. If you need continuous visual regression checks on a fixed set of pages, you are describing a different class of product.

Finally, the report viewer is a convenience over a database you produced, not a hardened multi-tenant service. The compose file's own comments steer you toward a reverse proxy with basic auth, and there is no documented role model.

gowitness against a general-purpose browser automation stack

The obvious alternative is writing the same thing with Puppeteer, Playwright or a direct chromedp program. The difference is not the browser, since gowitness drives Chrome through chromedp and go-rod too. The difference is what comes pre-assembled.

With a general automation library you write the target enumeration, the concurrency, the timeout policy, the storage schema and the review UI. You get complete control over rendering behaviour, which matters if you need to script interactions before the screenshot, click through a consent banner, or wait on a specific selector. gowitness gives you none of that out of the box; it takes a target and produces a picture.

What gowitness gives you instead is the surrounding pipeline: parsers for Nmap and Nessus output, multiple writers including sqlite, jsonlines and csv, technology fingerprinting through wappalyzergo, and a report server with an API and Swagger docs. If your need is a visual inventory of many hosts discovered by a scanner, that assembly is the entire value. If your need is a scripted interaction with one application, a general library is the better fit and gowitness will feel like a wrapper you have to work around.

Maintenance, upgrades and the GPL-3.0 question

The last push to the repository was on 2026-09-16, and release 3.2.0 was tagged on 2026-09-14, following 3.1.1 in November 2025 and 3.1.0 a week before that. The repository is not archived. Recent activity is therefore real, but the release cadence between 3.1.1 and 3.2.0 spans roughly ten months, so pin a version rather than tracking master if you are deploying this into anything with an uptime expectation.

Upgrade cost is mostly environmental. The Go module targets go 1.26.0, and the build depends on a Node frontend stage: the Dockerfile builds web/ui with npm ci and npm run build before the Go build. Building from source therefore requires both a Go toolchain and npm, which the Makefile enforces with a check-npm target that aborts if npm is missing. If you consume release binaries or the published container image, you skip that entirely.

On licensing, gowitness is under the GNU General Public License v3.0, and the README adds that permissions beyond the scope of this license may be available via sensepost.com/contact. GPL-3.0 is a copyleft licence, so if you distribute a modified gowitness or a derivative work, the obligations attach to that distribution. Internal use inside an organisation is a different question from shipping a product that embeds it, and the answer depends on your facts. This is not legal advice; if you plan to redistribute anything built on gowitness, have counsel read the licence and the contact route the README offers.

Editorial conclusion

Adopt gowitness if you already have a list of hosts, from Nmap, Nessus or a CIDR range, and you want screenshots plus a browsable SQLite report without writing a browser harness yourself. Do not adopt it if you need a fully supported Windows pipeline: the README says Windows support is mostly working, which is not the same as supported. Before committing, verify that Chrome or a headless shell is present where gowitness runs, since the Dockerfile symlinks /headless-shell/headless-shell to the google-chrome, chromium and chromium-browser names rather than installing a browser itself, and check the GPL-3.0 obligations against how you intend to distribute anything you build from it.

Frequently asked questions

How do I install gowitness?

The README gives go install github.com/sensepost/gowitness@latest as the simplest method, assuming your $GOBIN path is on your shell $PATH. It also points to platform specific release binaries and compiling from source, with advanced installation covered in the project wiki.

How do I use gowitness?

The README's quick start scans one target and writes results to a SQLite database with gowitness scan single --url "https://sensepost.com" --write-db. The README notes there are many flags and scan types, and that adding -h anywhere prints them.

How do I install gowitness on Linux or macOS?

The README states that Linux and macOS are supported, with Windows support mostly working. On those platforms you can either run go install github.com/sensepost/gowitness@latest, grab a platform specific release binary, compile from source, or use the published container image.

What does gowitness do?

It is a website screenshot utility written in Go that uses Chrome Headless to generate screenshots of web interfaces from the command line. It can also save gathered data such as request logs, console logs, headers and cookies, and write results to formats including sqlite, jsonlines and csv.

What can I use instead of gowitness?

A general browser automation library such as Puppeteer, Playwright or a direct chromedp program covers the same rendering step. The trade-off is that you then write the target enumeration, storage and review interface yourself, whereas gowitness ships Nmap and Nessus parsers, multiple output writers and a report server.

Official sources

  1. Issues
  2. License: GPL-3.0
  3. README
  4. Releases
  5. sensepost/gowitness on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/sensepost-gowitness.svg)](https://hysenlabs.com/projects/sensepost-gowitness)