hstspreload.org: the website that decides who gets Chromium's HSTS preload list
:lock: Chromium's HSTS preload list submission website.
At a glance
- What is it?
- hstspreload.org is the submission site for Chromium's HSTS preload list, a small Go service that runs a site against the preload requirements, stores submissions in Cloud Datastore and drives the published list. The repository is the site and the front end, while the checking logic lives in a separate core library, and the local development setup needs the Cloud Datastore emulator.
- Who is it for?
- Adopt the hstspreload.org code if you want to run a copy of the preload submission service for your own domain list, or if you are contributing to the checks that decide whether a site qualifies. Do not adopt it if you are looking for a way to preload a single domain, because Chromium ships the list and the submission is the supported route.
- Can I use it commercially?
- Yes. BSD-3-Clause 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 51 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
The problem: HSTS helps only if the browser already trusts you
HTTP Strict Transport Security is a header that tells a browser to refuse to talk to a host over plain HTTP, ever. It is the mechanism that makes the padlock in the address bar mean something for a whole domain rather than for one page.
The catch is that the header only protects a visitor who has already received it, which means a site has to be visited over HTTPS first, and a first visit to a site that only sends the header on the secure version leaves the door open for an attacker on that first request. The preload list closes that gap. A domain on the list is treated as HSTS-enabled by the browser before it has ever been visited, so the first request is already protected.
The list is therefore a curated set, and the curation is the interesting part. A domain only gets in if it meets a set of requirements, and those requirements are checked by code. This repository is the website that runs those checks and collects the submissions: the project description calls it Chromium's HSTS preload list submission website, and the README says the folder contains the source for the HSTS preload list submission website at hstspreload.org.
The audience is site operators who want their domain preloaded, and the code is in the open because the rules are in the open. A preload entry is a promise that a domain will be HTTPS-only for years, so the criteria and the checking of them have to be inspectable, and the Chromium team is the one doing both.
The licence is BSD-3-Clause, the language is Go, the default branch is main, and the last push was on 2026-09-02, with no GitHub releases published.
The two repository split, and where the checking logic lives
The README points at a second repository, and the separation is the first thing to understand.
See github.com/chromium/hstspreload for the core library that checks websites against the submission requirements. So the rules live in a library, and this repository is the service and the site around it. That is a sensible division for a project with this shape: the checking code is a library other tools can consume, including the browser itself when it decides whether a navigation should be upgraded, and the service is where the submissions live.
Inside this repository the Go files at the root are the service itself: hstsserver.go, which is the preload list server, server.go, which is the submission server, and opensearch.go, which handles the search index. Around them sit api/ for the API surface, database/ for the data access layer, frontend/ for the web interface with its static assets, static-data/ for the data the service serves, and scripts/ for the supporting jobs.
The deployment configuration is at the top level as well, in app.yaml and cron.yaml, which are the App Engine service definition and the cron configuration. The version file is written into the frontend directory, which is how the deployed front end reports which commit it came from.
The dependency list confirms the shape of the service. The go.mod requires cloud.google.com/go/datastore, google.golang.org/api and google.golang.org/grpc, so the storage is Google Cloud Datastore reached over gRPC, plus the chromium hstspreload library itself pinned to a specific commit, and golang.org/x/net for the HTTP work. The indirect list is long and includes OpenTelemetry instrumentation for the gRPC and HTTP clients, which is what you would expect from a Google Cloud service that wants traces.
Running it locally, and the Datastore emulator you have to download first
The development instructions are short, and the setup has one dependency that surprises people.
The requirements are a go development environment, and the java commandline program for running JAR files, which is needed for the Cloud Datastore Emulator. The clone and start are:
git clone https://github.com/chromium/hstspreload.org && cd hstspreload.org
make serveThe first time you run it, make serve will download the Cloud Datastore Emulator, around 115MB, to a cache directory. The Makefile shows exactly where it goes: the emulator archive is fetched from a Google Cloud storage bucket, unzipped into a directory under the XDG cache home, and the Makefile's get-datastore-emulator target does the download, the unzip and the removal of the archive.
That dependency is the price of using the same database as production. It is a genuine trade rather than an inconvenience, because a service that stores submissions in a document store with a specific query model does not have a trivial file-based substitute, so the emulator is what makes the local loop faithful.
Once the emulator is in place, the serve target also depends on the version target, which writes the current commit hash into the frontend version file, and then it runs the service in local mode with go run over the top level Go files. The local flag is what switches the service from talking to real Cloud Datastore to talking to the emulator.
The test target follows the same pattern: it depends on the emulator and then runs the tests with verbose output and coverage enabled.
Deployment, the cron job, and why it takes ten minutes
Deployment assumes a specific Google Cloud environment.
If you have access to the Google Cloud hstspreload project, the deploy target is:
make deployAnd the documentation adds a warning about the cost of that command: unfortunately, this usually takes 5-10 minutes. The reason is visible in the Makefile, because the deploy target depends on version, and the deploy step runs gcloud app deploy against both app.yaml and cron.yaml, which is two App Engine deployments rather than one.
The cron.yaml file is the interesting artefact in that pair. A preload list is not a static file that can be published once, because domains are removed when they stop meeting the requirements, and the list has to be regenerated as the data changes. The cron configuration in the repository is how that regular work is scheduled.
The version target is a small thing with a real purpose. It runs git rev-parse HEAD and writes the result into the frontend version file, which is how the deployed site reports which commit of the source it was built from. For a service that decides which domains are preloaded in millions of browsers, being able to answer which code produced a given list is not decorative.
The disclaimer in the README is the other thing to read before deploying anything:
This project is used by the Chromium team to maintain the HSTS preload list. This is not an official Google product.
That last sentence matters for anyone running their own instance, because the support and the authority behind the real list are the Chromium team, not a Google service.
The build and the checks: go vet, staticcheck and a version stamp
The Makefile is small, and each target tells you what the project considers a gate.
The build target compiles the module, and the lint target runs go vet over the project and then installs and runs staticcheck at a pinned version, 2025.1.1. The pre-commit target chains lint, build and test, so the same three steps run before a commit as in continuous integration.
The lint target installing its own checker rather than assuming it is present is a small quality signal. A pinned staticcheck version means the checks do not drift between machines, and the fact that vet and staticcheck are both run means the project is not relying on one tool's blind spots.
The rest of the tooling is the App Engine configuration and the scripts directory. The go.mod declares Go 1.25.0, and the module path is github.com/chromium/hstspreload.org.
For a contributor the practical sequence is the one the documentation gives: clone, make serve, and then make test. The second command will download the emulator if it is not already cached, so the first run is slow and every later run is not.
One gap worth naming is that the repository publishes no GitHub releases. The service is deployed continuously from main to App Engine, so the version of the running service is identified by the commit hash in the frontend version file rather than by a tag. For a repository that is part of the security infrastructure of a major browser, that is a defensible choice, and it does mean there is no release history to consult when something changes.
Where hstspreload.org is the wrong tool
The boundaries here are narrow, and stating them plainly is more useful than listing features again.
If you run one domain and want it preloaded, this repository is the wrong tool, because the code does not add anything to your site. The preload list ships inside the browser, and the route to being on it is the submission website, which is a service operated by the Chromium team rather than something you deploy. A self-hosted copy of the code gives you a service that accepts submissions and applies the same checks; it does not get your domain into Chromium.
If you are looking for the requirements a domain must meet, that logic is in the core library, github.com/chromium/hstspreload, and the submission site is a consumer of it. Installing this repository to find out the rules is the wrong way round.
If your infrastructure is not on Google Cloud, the service as written is tied to Cloud Datastore and App Engine, and the local development path needs a Java runtime for the emulator. The code is readable Go and the Datastore access is behind a layer in database/, so porting it is plausible, but it is work that the project has not done.
What the repository is good for is the thing it was built for: a submission service with a public front end, a real datastore, a scheduled job to regenerate the list, and a core library that anyone can read to find out exactly why a domain was accepted or rejected. For a reader who wants to understand how Chromium decides who gets the padlock before the first visit, that is the whole value, and the code is small enough to read in an afternoon.
Editorial conclusion
Adopt the hstspreload.org code if you want to run a copy of the preload submission service for your own domain list, or if you are contributing to the checks that decide whether a site qualifies. Do not adopt it if you are looking for a way to preload a single domain, because Chromium ships the list and the submission is the supported route. Before you deploy, read the disclaimer, because the project is used by the Chromium team and is explicitly not an official Google product, and expect a Google Cloud project, an App Engine deployment and a Datastore emulator to be part of your local loop.
Frequently asked questions
What is hstspreload.org?
It is the source for the HSTS preload list submission website at hstspreload.org, used by the Chromium team to maintain the preload list. The checking of websites against the submission requirements lives in a separate core library, github.com/chromium/hstspreload.
How do I run hstspreload.org locally?
You need a go development environment and the java commandline program for running JAR files, then clone the repository and run make serve. The first run downloads the Cloud Datastore Emulator, around 115MB, into a cache directory before the service starts in local mode.
Where is the preload list data stored?
In Google Cloud Datastore, reached through cloud.google.com/go/datastore and gRPC, with the API surface in api/, the data access layer in database/ and the search integration in opensearch.go. The deployment uses app.yaml for the App Engine service and cron.yaml for the scheduled regeneration work.
What checks run before a pull request is accepted?
The Makefile's pre-commit target chains lint, build and test. The lint target runs go vet and then staticcheck at a pinned version, 2025.1.1, and the test target runs the tests with verbose output and coverage.
Is hstspreload.org an official Google product?
No. The disclaimer states that the project is used by the Chromium team to maintain the HSTS preload list and that this is not an official Google product. The licence is BSD-3-Clause, the language is Go with go 1.25.0, and the last push was on 2026-09-02.
Official sources
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.
[](https://hysenlabs.com/projects/chromium-hstspreload-org)Was this useful?