Library / SDK
projectdiscovery/wappalyzergo avatar
projectdiscovery/wappalyzergo

wappalyzergo: technology fingerprinting that parses HTML by hand

A high performance go implementation of Wappalyzer Technology Detection Library

1,122 stars171 forksGoMIT

At a glance

What is it?
wappalyzergo is a Go port of the Wappalyzer technology detection library that emphasises speed, parsing HTML manually instead of building a tree, and it ships a fingerprint database that updates itself through a small command line tool. There is also an optional runtime detector that drives a real browser, which is where the interesting engineering decisions sit.
Who is it for?
Adopt wappalyzergo if you need to know what technology a site runs, from headers and body alone, at a rate where a full browser would be too slow, and if you want a fingerprint database that updates without hand editing JSON. Do not adopt it expecting a general vulnerability scanner, since it identifies technologies rather than judging whether they are outdated or misconfigured.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 5 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 October 22, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What it detects, and where the data comes from

wappalyzergo is a high performance port of the Wappalyzer technology detection library to Go, inspired by Webanalyze, and the fingerprint data comes from two sources, the enthec/webappanalyzer repository and the HTTPArchive/wappalyzer project. That provenance matters more than it might appear, because a technology fingerprint is a set of patterns, usually regular expressions matched against response headers, cookies and body markup, and the quality of the detection is the quality of the pattern set. Wappalyzer is the well known original, and the HTTPArchive project maintains the widely used dataset that many tools ship, so this port is effectively a Go implementation with a maintained pattern corpus. The library is used to answer one question, what is this site running, and the answer comes back as a map from technology name to a set of matches, which is the shape a scanner or an inventory system wants.

Speed as the design constraint

The feature list names three things, and the third is the one that shapes the code. It is very simple and easy to use with a clean codebase, it has normalized regular expressions and an auto-updating database of wappalyzer fingerprints, and it is optimized for performance by parsing HTML manually for best speed. Manual HTML parsing is a deliberate trade. A DOM tree gives you robust queries, and it costs allocation and time, and a detector that has to run against thousands of hosts in a scan has neither to spare. The repository layout reflects the optimisations, with a `literal_index.go` that appears to pre-index literal substrings so that a candidate region can be rejected cheaply, a `patterns.go` for the compiled pattern set, and separate detection files for headers, cookies and the body, with `fingerprint_body.go`, `fingerprint_cookies.go` and `fingerprint_headers.go`. The test files are named for the work they do, with `benchmark_test.go`, `body_bench_test.go`, `prefilter_test.go`, `intensive_test.go` and `massive_test.go`, which suggests the performance claims are at least measured internally rather than asserted.

Getting the library and the fingerprint database in place

The installation step is unusual enough to be worth quoting, because it installs the library source rather than a binary. You run `go install -v github.com/projectdiscovery/wappalyzergo/cmd/update-fingerprints@latest`, and after that command the wappalyzergo library source will be in your go.mod. The `cmd/update-fingerprints` tool is the reason the database can be kept current without editing JSON by hand, and it is the piece that pulls the pattern data from the upstream sources. The usage itself is then a handful of lines, which is the shape you would expect from a library with one obvious entry point.

go
resp, err := http.DefaultClient.Get("https://www.hackerone.com")
if err != nil {
	log.Fatal(err)
}
data, _ := io.ReadAll(resp.Body) // Ignoring error for example

wappalyzerClient, err := wappalyzer.New()
fingerprints := wappalyzerClient.Fingerprint(resp.Header, data)
fmt.Printf("%v\n", fingerprints)

The result is a map keyed by technology name, and the README shows what that looks like for a real site, with entries for Acquia Cloud Platform, Amazon EC2, Apache, Cloudflare, Drupal, PHP, Percona, React and Varnish. Note the shape of the result, the key is the technology and the value is the set of matches that identified it, which is what lets a caller report evidence rather than a bare label.

The optional runtime detector, and who owns the browser

The passive `Fingerprint` method uses only the response headers and the body, and the README says so plainly, which is the right default for a tool that may face thousands of hosts. There is an optional second path, `FingerprintWithRuntime`, which also checks JavaScript properties, the rendered DOM and script content. The design here is careful about ownership. The optional headless adapter works with a Rod page that the caller has already loaded, and the caller remains responsible for launching, navigating and closing the browser, so the library never spawns a browser on your behalf and never leaves one running. The adapter is a thin wrapper over a collector, and the README notes that other browser integrations can implement the `RuntimeCollector` interface without importing the Rod adapter, which keeps the browser dependency optional in a real sense rather than a soft one. The error handling is also deliberate, since if runtime collection returns an error the result still includes the passive matches and any matches found before the failure, so a browser that crashes mid-scan costs you the runtime findings and not the whole result.

The source tree, read as a map of the detection strategy

The repository is a good example of a Go library organised by concern. `fingerprints.go` and `fingerprints_data.go` with its JSON payload hold the pattern database, `tech.go` and `versions.go` model the technologies and their version patterns, and `categories_data.json` carries the category information that lets a caller group detections. The detection surface is split across the three files named earlier, headers, cookies and body, and `runtime.go` holds the runtime path with the collector interface. The `cmd/` directory contains the updater, `headless/` contains the Rod adapter, and `examples/main.go` is a runnable example. The test suite covers each area separately, with `fingerprints_test.go`, `patterns_test.go`, `versions_test.go`, `runtime_test.go` and the general `wappalyzergo_test.go`, and the repository is in the ProjectDiscovery organisation, whose other tools this one is designed to sit alongside in a scanning pipeline.

Dependencies, toolchain and the pre-1.0 release line

The module requires Go 1.26.0 and has a short dependency list. The Rod browser automation library is there for the optional headless adapter, and it brings the `ysmood` family of packages with it, including fetchup, goob, got, gson and leakless, which is the price of the runtime path. `golang.org/x/net` is present for the HTML handling, and `stretchr/testify` for the tests. The two direct dependencies worth noticing are the ones that separate the two modes, because a user who never calls `FingerprintWithRuntime` pays for the Rod dependency at build time even if it never runs a browser. The release history shows a project moving quickly but not yet settled, with 0.3.3 on 2026-09-27, 0.3.4 on 2026-10-04 and 0.3.5 on 2026-10-11, and the last push on 2026-10-13. For a 0.x library, that cadence is normal, and it also means the API is still allowed to move, so a pin in your go.mod is worth more here than it would be for a 1.0 crate.

Editorial conclusion

Adopt wappalyzergo if you need to know what technology a site runs, from headers and body alone, at a rate where a full browser would be too slow, and if you want a fingerprint database that updates without hand editing JSON. Do not adopt it expecting a general vulnerability scanner, since it identifies technologies rather than judging whether they are outdated or misconfigured. Before you rely on it, decide whether you need the runtime detector, because the passive path uses only headers and body while `FingerprintWithRuntime` needs a browser you drive yourself. Also read the fingerprint provenance, since the database is assembled from two upstream projects, and the project is still pre-1.0, with releases in the 0.3.x range, so expect the API to move. The licence is MIT, the newest release is 0.3.5 from 2026-10-11, and the last push was on 2026-10-13.

Frequently asked questions

How do I install wappalyzergo?

Run `go install -v github.com/projectdiscovery/wappalyzergo/cmd/update-fingerprints@latest`, and the wappalyzergo library source will then be in your go.mod. The same command installs the tool that updates the fingerprint database, which is built from the enthec/webappanalyzer and HTTPArchive/wappalyzer data sources.

How do I detect the technologies a site runs?

Fetch the response, read the body, create a client with `wappalyzer.New()` and call `Fingerprint(resp.Header, data)`. The result is a map from technology name to the matches that identified it, and the README's example shows detections such as Apache, Cloudflare, Drupal, PHP, React and Varnish for a real site.

What is the difference between Fingerprint and FingerprintWithRuntime?

`Fingerprint` uses only the response headers and the body. `FingerprintWithRuntime` also checks JavaScript properties, the rendered DOM and script content, through a collector, with an optional headless adapter that works with a Rod page the caller has already loaded, leaving the caller responsible for launching, navigating and closing the browser.

What happens if the runtime detection fails?

The result still includes the passive matches and any matches found before the failure, so a browser that crashes mid-scan costs you the runtime findings rather than the whole result. Other browser integrations can also implement the RuntimeCollector interface without importing the Rod adapter.

Official sources

  1. Issues
  2. License: MIT
  3. projectdiscovery/wappalyzergo on GitHub
  4. README
  5. Releases
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/projectdiscovery-wappalyzergo.svg)](https://hysenlabs.com/projects/projectdiscovery-wappalyzergo)

Was this useful?