Open-source project
abrahamjuliot/creepjs avatar
abrahamjuliot/creepjs

CreepJS: a fingerprinting test that measures how well your browser lies

Creepy device and browser fingerprinting

2,518 stars289 forksTypeScriptMIT

At a glance

What is it?
CreepJS is a browser fingerprinting test page that detects JavaScript tampering and scores how consistent a browser's lies are. It is research and education tooling, not a library you ship.
Who is it for?
Use CreepJS if you are auditing an anti-fingerprinting extension, a hardened browser profile, or an automation stack and you want to see which of its lies are detectable and which are consistent. Do not use it as a fingerprinting library in a product: the README states the goal is research and education, the name is trademarked, and public mirrors are explicitly discouraged.
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 112 days ago.
What is it written in?
Mainly TypeScript, 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 CreepJS is for, and who actually needs it

CreepJS exists to expose the gap between what a browser claims and what it actually does. The README states the purpose directly: to shed light on weaknesses and privacy leaks among modern anti-fingerprinting extensions and browsers. That is a narrower job than generic fingerprint testing. The tool is aimed at people who build or audit the defenses, not at people who want a single number telling them they are anonymous.

The audience implied by the test list is specific. Tor Browser at security levels 1 and 2, Firefox with RFP, ungoogled-chromium, Brave in Standard and Strict mode, Bromite, and a long list of extensions including uBlock Origin, NoScript, CanvasBlocker, JShelter, Privacy Badger and several user-agent spoofers. If you maintain a privacy extension, or you are evaluating whether a hardened browser profile holds up, this is the target use case. If you just want to know whether a random site can identify you, the twenty test categories here will give you far more detail than you asked for, and much of it will be noise.

How the tests work: lies, patterns, and high-entropy APIs

The mechanism is built around detecting tampering rather than around collecting the largest possible set of values. The README lists the design goals in order: detect and ignore JavaScript tampering (prototype lies), fingerprint lie patterns, fingerprint extension code, fingerprint browser privacy settings, use large-scale validation and collect inconsistencies, and feature detect and fingerprint new APIs that contain high entropy. The ordering matters. Detection of a lie comes before the use of the value, because a spoofed value is not a stable identifier unless the spoof itself is stable.

The test categories split into two rough groups. Some probe rendering and runtime surfaces: CSS system styles, CSS computed styles, HTMLElement, Math, console errors, emoji measurement via DomRect, SVG, audio, MimeTypes, canvas variants (image, blob, paint, text, emoji), TextMetrics, WebGL, GPU parameters and renderer string, fonts, voices, screen, and timezone. Others are explicitly about resistance: the README names a category called Resistance (Known Patterns), which is where the lie-pattern comparison lives. The contentWindow (Self) object is tested first, which suggests the page inspects its own window before trusting anything inside it.

The stated preference is to use APIs that are the most difficult to fake. That is the opposite of the usual fingerprinting-library approach, which favors whatever is easiest to read. A canvas hash is trivial to perturb; a GPU renderer string or a font metrics set is harder to fake without breaking the page. The supported engines are listed as Gecko, Goanna, Blink and WebKit for layout, and SpiderMonkey, JavaScriptCore and V8 for the runtime, so the results are meant to be comparable across engine families rather than tuned to one browser.

Installing CreepJS and running the fingerprint test locally

For most readers the fastest path is the official deployment, and the README is emphatic about which one that is. It states that the only official live deployment is on GitHub Pages, at https://abrahamjuliot.github.io/creepjs, and that any .org, .com or custom domain claiming to be CreepJS is an unauthorized mirror to be treated as a malicious honeypot. So step one is simply opening that URL and letting the tests run. The page renders results as it goes, and the console exposes the underlying objects as window.Fingerprint and window.Creep, which is where you look when a rendered score is not enough.

If you want to modify the tests, the README gives the development commands. The package manager is pinned: package.json declares a preinstall script of npx only-allow pnpm, so npm and yarn installs are rejected before anything else happens. The README lists the four commands as install, build:dev, watch:dev, and build for release to GitHub Pages.

bash
pnpm install
pnpm build:dev
pnpm watch:dev
pnpm build

The build pipeline is two stages. build:js runs build:dev, which invokes rollup with tsconfig.build.json and NODE_OPTIONS=--no-warnings. build:css runs autoprefixer over public/style.css and then clean-css to produce docs/style.min.css. The watch:dev script is the one to use while editing: it starts rollup in watch mode and runs nodemon against server.js on localhost port 8000, restarting it after a three second delay.

bash
pnpm start

Running pnpm start directly executes node server.js without the watch wrapper. The README also notes that GitHub Codespaces is supported if you want to test over a secure connection, which matters because several of the APIs CreepJS probes behave differently outside a secure context. There is no published npm package described in the README, so treat the repository as the distribution channel.

Where CreepJS gives you less than you might expect

The most obvious limitation is that this is a web page, not a library. The README states the goal is to conduct research and provide education, not to create a fingerprinting library. There is no documented API for embedding the tests in your own application, no npm package described, and no versioned release. The package.json version is 1.0.0 and the test script is a stub that echoes an error and exits 1, so there is no automated test suite to tell you whether a change broke a detector.

A second constraint is environmental. Several listed tests depend on surfaces that vary by context: audio, WebGL and GPU renderer strings, fonts, and voices all behave differently across headless and headed browsers, across operating systems, and inside containers. A result collected in GitHub Codespaces is not directly comparable to one collected on a desktop Firefox install. The README's own suggestion to use Codespaces for a secure connection implicitly acknowledges this.

Third, the value of the output depends on the target. CreepJS is tuned toward the browsers and extensions in its test list. If your threat model involves a browser or extension that is not on that list, the Resistance (Known Patterns) category may have nothing to match against, and you will be reading raw values with no lie-pattern verdict. That is not a bug, but it does mean the tool can look less informative than it is. Finally, the trademark policy is a real constraint on deployment, and it is covered below.

CreepJS compared with Browserleaks and general fingerprint test suites

Browserleaks is the natural comparison, and the difference is in the question each one answers. A general fingerprint suite such as Browserleaks is organized around showing you what a site can read: here is your canvas hash, here is your WebGL renderer, here is your font list. The framing is exposure. You come away knowing what is visible.

CreepJS is organized around whether the visible values are honest. Its first stated goal is to detect and ignore JavaScript tampering, and one of its twenty test categories is explicitly named Resistance (Known Patterns). The output is not just a value but a judgement about the value, including whether it matches a pattern the project has seen before. That is why the README describes large-scale validation and collecting inconsistencies as a design goal: the tool is trying to learn what spoofing looks like in aggregate.

The practical consequence is that CreepJS is worse at the simple question and better at the adversarial one. If you want a clean inventory of your browser's exposed surface, a general fingerprint suite presents it more legibly. If you want to know whether your extension's canvas spoof is detectable, or whether your user-agent spoofer contradicts your navigator properties, CreepJS is built for that and a value-dump suite is not. They are complementary, and running both is reasonable when you are auditing a hardened profile.

Licence, trademark, and what forking actually costs you

The code is MIT licensed, which the README confirms: you are free to fork and modify it. The name is not. The README states that CreepJS is trademarked and that you may not use the name for commercial products or public websites, giving creepjs.org as an explicitly prohibited example. It also asks that people refrain from hosting public mirrors and says distinct public forks must be renamed to prevent user confusion. A TRADEMARKS.md file sits at the top level of the repository alongside LICENSE and SECURITY.md, so the policy is a first-class document rather than a footnote.

For an internal deployment this is mostly a non-issue: rename your fork, keep it off the public internet, and the MIT terms apply to the code. For anything user-facing the trademark clause is the binding constraint, and it is stricter than the licence. This is not legal advice; if you plan to ship something derived from CreepJS under a public domain, read TRADEMARKS.md yourself.

Maintenance is a separate question. The repository is not archived, and the last push was on 2026-06-11. There are no retrieved releases, so upgrades arrive as commits on master rather than as tagged versions. That means no changelog to read before pulling, and no version pin to hold. If you deploy a fork, budget for reading the diff yourself.

Editorial conclusion

Use CreepJS if you are auditing an anti-fingerprinting extension, a hardened browser profile, or an automation stack and you want to see which of its lies are detectable and which are consistent. Do not use it as a fingerprinting library in a product: the README states the goal is research and education, the name is trademarked, and public mirrors are explicitly discouraged. Before relying on any result, confirm you loaded the official GitHub Pages deployment rather than a mirror, and check window.Fingerprint and window.Creep in the console to see the raw objects behind the rendered score.

Frequently asked questions

What is CreepJS and what does it do?

CreepJS is a browser fingerprinting test page whose stated purpose is to shed light on weaknesses and privacy leaks among modern anti-fingerprinting extensions and browsers. It runs twenty test categories covering rendering surfaces such as canvas, WebGL, fonts and voices, plus a Resistance category that compares observed values against known spoofing patterns.

How do I use CreepJS?

Open the official deployment at https://abrahamjuliot.github.io/creepjs and let the tests run, then inspect window.Fingerprint and window.Creep in the console for the underlying objects. To modify the tests, clone the repository and use the pnpm commands the README lists: pnpm install, pnpm build:dev, pnpm watch:dev and pnpm build.

Can I bypass browser fingerprint detection with CreepJS?

No. CreepJS is the detector, not the evasion tool, and the README states its goal is research and education rather than providing a fingerprinting library. Its first design goal is to detect and ignore JavaScript tampering, so the project is oriented toward finding spoofing rather than helping you produce it.

Which browser is best for avoiding fingerprinting according to CreepJS?

The README does not rank browsers or declare a winner. It lists the browsers and extensions its tests focus on, including Tor Browser at security levels 1 and 2, Firefox with RFP, ungoogled-chromium, Brave in Standard and Strict mode, and Bromite, and leaves the interpretation of results to the reader.

Official sources

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